Java 创建一个新的 ObjectInputStream 块

Posted

技术标签:

【中文标题】Java 创建一个新的 ObjectInputStream 块【英文标题】:Java Creating a new ObjectInputStream Blocks 【发布时间】:2011-08-05 05:04:22 【问题描述】:

我正在尝试使用从 Socket 检索的 InputStream 创建一个新的 ObjectInputStream。这是我的代码:

这是我的 MessageGetterSender 类的构造函数。程序无法到达检查点 4。

public MessageGetterSender(Socket socket) 

    System.out.println("MessageGetterSender: Checkpoint 1");

    this.socket = socket;

    // Get input and output streams
    try 
        System.out.println("MessageGetterSender: Checkpoint 2");

        InputStream is = socket.getInputStream();

        System.out.println("MessageGetterSender: Checkpoint 3");

        this.in = new ObjectInputStream(is);

        System.out.println("MessageGetterSender: Checkpoint 4");

     catch (IOException ioe) 
        System.out.println("Could not get ObjectInputStream on socket: " + socket.getLocalPort());
    

    try 
        this.out = new ObjectOutputStream(socket.getOutputStream());
     catch (IOException ioe) 
        System.out.println("Could not get ObjectOutputStream on socket: " + socket.getLocalPort());
    

    System.out.println("MessageGetterSender: Checkpoint 5");

我正在从一个连接到服务器以获取套接字的类中实例化一个新的 MessageGetterSender 对象。这是相关的代码。它是 InstantMessageClass 的构造函数,该类实例化 MessageGetterSender 对象:

public InstantMessageClient(String username) 

try 
    socket = new Socket("localhost", 5555);
 catch (IOException ioe) 
    System.out.println("Error: Could not connect to socket on port: " + serverPort);


messageGetterSender = new MessageGetterSender(socket);

...

由于代码没有执行到检查点 4,但它确实到达了检查点 3,我很确定 ObjectInputStream 的实例化是罪魁祸首。我不知道为什么。有任何想法吗?感谢您的帮助。

【问题讨论】:

【参考方案1】:

当您构造ObjectInputStream 时,该类在构造函数中尝试读取连接另一端的关联ObjectOutputStream 已写入的标头。在读取该标头之前它不会返回。因此,如果您看到构造函数“挂起”,那是因为套接字的另一端没有使用ObjectOutputStream,或者还没有刷新数据。

【讨论】:

【参考方案2】:

只是为了扩展 FatGuy 对其他发现此问题的 Google 员工的回答;解决这个“鸡和蛋问题”的方法是让每一方先打开输出流,刷新输出流,然后再打开输入流。

ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
out.flush();
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());

【讨论】:

这确实是正确的解决方案。你把它描述为“鸡和蛋”的问题,一针见血。 我想说out.flush() 不是必需的(除非您使用一些缓冲流作为底层流),因为ObjectOutputStream 使用的BlockDataOutputStream 在启用块数据之前写入流标头模式。【参考方案3】:

您还可以延迟 ObjectInputStream 的初始化,直到底层流中的数据可用。

无论流初始化顺序如何,这种方法都有效,如果通道的一端位于您无法更改的库代码中,则特别有用。

【讨论】:

我能问一下如何去做吗? 我认为您可以查看底层流以查看是否有可用数据。我已经有一段时间没有查看 Stream API 了。

以上是关于Java 创建一个新的 ObjectInputStream 块的主要内容,如果未能解决你的问题,请参考以下文章

java 序列化机制深度解析

Android Serialization序列化

Java 创建一个新的 ObjectInputStream 块

为啥我不能内联创建新的 Java 数组? [复制]

为啥我不能内联创建新的 Java 数组? [复制]

如何定义一个新的 Java 类并在运行时创建它的实例?