【问题标题】:Java Null pointer exception in sending a hashmap from a server to a client将哈希图从服务器发送到客户端时出现 Java 空指针异常
【发布时间】:2014-07-20 08:35:09
【问题描述】:

我编写了一个服务器/客户端代码,它使用ObjectOutputStream 从服务器向客户端发送哈希图。我还编写了一个 update 函数,它每 50 毫秒调用一次以发送该 hashMap。

public void update() {
    try {
        //oos is an objectoutput stream
        HashMap<String, HashMap<String, Integer>> hash = new HashMap<>();
        for (int j = 0; j < objects.size(); j++)
            hash.put(objects.get(j).toString(), judge.getInfo(objects.get(j)));
        for (int i = 0; i < 2; i++) {
            oos[i].writeObject("money#"
                    + judge.getMoney(player[i].getTeam()));
            //System.out.println(judge.getMoney(player[i].getTeam()));
            oos[i].writeObject("time#" + judge.getTime());
            if(hash==null)
                System.out.println("HASH"+hash);
            if(oos[i]==null)
                System.out.println("nulllllllll");
            oos[i].writeObject(hash); //*****line 229 of Game.java ******/
            oos[i].flush();

            //oos[i].reset();
            //System.out.println(hash.size());
        }

    } catch (IOException ioe) {
        ioe.printStackTrace();

    } catch (MahyariseExceptionBase meb) {
        // TODO
    }

}

有时上面的代码会抛出这样的异常:

java.lang.NullPointerException
     at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1500)
     at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
     at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
     at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
     at network.Game.update(Game.java:229)
     at judge.judge.next50milis(judge.java:403)
     at judge.judge$1.run(judge.java:421)
     at java.util.TimerThread.mainLoop(Timer.java:555)

那个 HashMap 的尺寸很小,如果 update 函数每 1000 毫秒调用一次,我们可以看到上面的异常被抛出。

遵循客户端代码:

    Thread read = new Thread() {
    public void run() {
        while (running) {
            Object a=null;
            try {
                if (socket.isConnected() && !socket.isClosed()) {
                    a = inputStream.readObject();
                    if (a != null)
                        analyze(a);
                }
            } catch (ClassNotFoundException e) {
                 e.printStackTrace();
            } catch (IOException e) {
                loose();
            }
        }
    };
};

【问题讨论】:

  • @kruemel HashMaps 可能包含 null,因此序列化必须能够处理它。
  • 您在这里没有以有效的方式使用 isConnected()。它不会告诉您任何有关连接状态的信息,只告诉您套接字本身。
  • @EJP 是的,我对检查客户端和服务器之间的连接知之甚少。如果你能帮助我,我会很高兴

标签: java serialization objectoutputstream


【解决方案1】:

我查看了 Grepcode 上的源代码,试图弄清楚堆栈跟踪的含义。行号对Java 8 version of the code 有意义,但对旧版本没有意义。

但除此之外,很难说。看起来ObjectOutputStream 对象中的currContext 内部字段是null,但我对第 1500 行之前的代码的阅读是它不可能发生!

除非...

... 有两个线程试图使用相同的 ObjectOutputStream 却没有正确同步。请记住,ObjectOutputStream 没有记录为线程安全的,并且不会在内部同步。

这就是我对导致 NPE 的原因的理论。

【讨论】:

  • 这和我读了这门课的三个版本后得出的结论是一样的。另外,我很怀疑w.r.t。短期调度(“每 N 毫秒”)的处理方式,以及在开始下一个任务之前是否完成了一个这样的任务。
  • 我也遇到了同样的问题,绝对是线程安全问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多