Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java网络代码在接收对象之前执行_Java_Sockets_Networking_Nullpointerexception_Objectinputstream - Fatal编程技术网

Java网络代码在接收对象之前执行

Java网络代码在接收对象之前执行,java,sockets,networking,nullpointerexception,objectinputstream,Java,Sockets,Networking,Nullpointerexception,Objectinputstream,我有一个使用网络的Java游戏,我有一个客户端(使用套接字)从ObjectInputStream获取对象,运行在自己的线程中 发件人: 这很有效。获取对象并将其传递给侦听器,侦听器是链接到my main GameApp类的类 从侦听器(): “app”是处理接收到的所有新对象并处理它们的实例 从应用程序()(编辑:非摘要提供了更大的上下文): 我已经在调试器中一步一步地运行了这段代码,它工作得非常好。但是,当我正常运行它时,会得到一个空指针(输出如下所示:) 现在,我看到这个物体被打印了两次,所

我有一个使用网络的Java游戏,我有一个客户端(使用套接字)从ObjectInputStream获取对象,运行在自己的线程中

发件人:

这很有效。获取对象并将其传递给侦听器,侦听器是链接到my main GameApp类的类

从侦听器():

“app”是处理接收到的所有新对象并处理它们的实例

从应用程序()(编辑:非摘要提供了更大的上下文):

我已经在调试器中一步一步地运行了这段代码,它工作得非常好。但是,当我正常运行它时,会得到一个空指针(输出如下所示:)

现在,我看到这个物体被打印了两次,所以我知道它已经收到了。。。但我得到一个空指针

我在函数中间添加了一个睡眠函数:

    else if(o instanceof GameList) {
        GameList gameList = (GameList) o;
        System.out.println("gamelist: " + gameList);
        try {
            Thread.sleep(1000); // sleep 100 still gave null pointer
        } catch (InterruptedException e) {}
        this.lobbyControl.gotGameList(gameList);
    }
让它睡一阵子,这一切终于奏效了

知道我为什么要这样睡觉吗?有什么我应该做的不同吗?我不知道为什么我能够打印对象,而它仍然被认为是空的


编辑:添加了更多的上下文。

好吧,我首先要说的是,发布的代码片段似乎有助于说明这个问题,但我不认为完整的情况已经描绘出来了。我会要求更多的代码,以帮助获得完整的上下文

话虽如此,我将提供以下指导:

  • 不要依赖java内置的对象序列化。很好,而且 易于使用,但在运行时可能非常不稳定且容易出错。 我建议使用自定义对象序列化和反序列化 计划

  • 根据你正在制作的游戏的范围,NIO可能是 内特选择。如果您坚持使用常规IO,那么请确保 有一个岩石坚实的线程管理器到位,以正确处理线程 处理套接字IO的线程


  • …没有更多的代码,这是我能提供的最多的了。

    看起来
    游说控制
    null
    ,而不是
    游戏列表
    。如果
    gameList
    为空,堆栈顶部将是
    gotGameList()
    方法,而不是
    gotObject()

    如果睡眠有助于解决问题,那么您必须在没有适当并发保护措施的情况下操作
    lobbyControl
    成员。
    ObjectInputStream
    在从流中完全读取对象之前不会返回对象,因此您的问题与没有完全读取对象无关



    更新:我无法理解所有的代码,但似乎对正在构造的对象的引用泄漏到了线程(NetControl中的
    客户端
    ),该线程在构造函数完成之前启动。如果是这样的话,那就太糟糕了。您不应该允许部分构造的对象对另一个线程可见。

    只是为了改进我的评论…当我需要等待一个或多个线程完成时,我喜欢使用java.util.concurrent.CountDownLatch。很简单:

    //game class
    public class DummyGame
    {
        CountDownLatch signal;
    
        public DummyGame( CountDownLatch signal)
        {
            this.signal = signal;
        }
       public void run()
       {
          doLogic();
          signal.countDown();
       }
    }
    
    //game controller class
    
     public void run()
     { 
        while (! gameOver)
        {
           CountDownLatch signal = new CountDownLatch(1); //wait one thread to finish
           new thread(newGame(signal)).start();
    
           //wait for game run() to finish
            signal.await();
    
           updateInterface();
        }
     }
    

    这只是一个想法,希望能有所帮助。

    更多信息:我向一位朋友询问了这一点,他提到了阻塞,例如等待先准备好的东西。我不熟悉这个概念,但我猜我可能想做的是等待我的对象完全接收(伪代码:Thread.sleep(直到对象完全接收);但我不确定当我需要等待一个(或多个)线程时,将如何完成(或如何检查何时完成)我使用倒计时锁存器进行同步。为什么要测试null?是否计划发送null?@EJP代码最初是在while(in.readObject()!=null)时读取的,但我将其更改为您看到的,因为这不起作用…我现在看到,这可能在一段时间内是不必要的(true)循环。谢谢你指出这一点!@ZachHall,但你为什么要测试null?除非你发送null,否则你不会得到null。也许你认为这是一个EOS测试,但事实并非如此。
    EOFEException
    告诉你。Java序列化非常成熟和健壮。它没有任何不稳定或容易出错的地方。特别是相对于你自己的滚动序列化协议。在恢复以相同命名类的旧格式存储的二进制数据时,我们实际上遇到了多个问题。此外,如果一个类在包a中存在时被序列化,那么随后的重构会导致该类移动到包B,那么每次对所述对象的反序列化都会失败。a“roll your own”协议可以很容易地利用工厂和命令模式的强大功能,并允许您完全避免使用java的内省功能对性能造成的影响。而且,根据我的经验,它允许更好的线程安全性和更高的健壮性。感谢您的回复!如果您喜欢,我的所有代码都可以在线获得ll故事。-这是游戏应用程序,显示NetControl和其他一些。(我想还不能包含超过2个链接,但其余的可以在com.lgposse.net中找到。(我知道我的软件包太多了)。同样,这些都是我的经验,就像Java一样。许多方法可以简化序列化猫。出于上述原因,我不喜欢使用内置的Java对象序列化机制。我会看看你的代码,然后再给你回复。有趣的一点!我想我现在意识到,我的代码并没有给出完整的故事,正如我所说的那样bbyControl是一个从服务器请求对象的类。-这是我一直在处理的非抽象类(忘记了这一点),它创建了一个新的LobbyControl,然后在其构造函数方法中请求一个新的游戏列表。(可能它被认为是空的,因为请求在构造函数完成之前通过?)嗯,我再次检查,添加了System.out.println(LobbyControl);我得到了null。你肯定有什么问题。我将尝试移动请求,以便仅在类完全成形时调用它。完成后我会发回结果。感谢你的洞察力!我知道了
    public void gotObject(Object o) {
        // select instance:
        if(o instanceof GameList) {
            GameList gameList = (GameList) o;
            System.out.println("gamelist: " + gameList);
            this.lobbyControl.gotGameList(gameList);
        }
    }
    
    Game ID: 0. Name: game1. Players: 1 / 1. // the object, as it is printed in Client.java
    
    gamelist: Game ID: 0. Name: game1. Players: 1 / 1. // the object, as it is printed again in GameApp.java
    
    Exception in thread "Thread-1" java.lang.NullPointerException
    at com.lgposse.game.app.GameApp.gotObject(GameApp.java:61)
    at com.lgposse.game.net.NetControl.gotObject(NetControl.java:47)
    at com.lgposse.net.client.Client.run(Client.java:49)
    
        else if(o instanceof GameList) {
            GameList gameList = (GameList) o;
            System.out.println("gamelist: " + gameList);
            try {
                Thread.sleep(1000); // sleep 100 still gave null pointer
            } catch (InterruptedException e) {}
            this.lobbyControl.gotGameList(gameList);
        }
    
    //game class
    public class DummyGame
    {
        CountDownLatch signal;
    
        public DummyGame( CountDownLatch signal)
        {
            this.signal = signal;
        }
       public void run()
       {
          doLogic();
          signal.countDown();
       }
    }
    
    //game controller class
    
     public void run()
     { 
        while (! gameOver)
        {
           CountDownLatch signal = new CountDownLatch(1); //wait one thread to finish
           new thread(newGame(signal)).start();
    
           //wait for game run() to finish
            signal.await();
    
           updateInterface();
        }
     }