【问题标题】:Should Java streams be closed Before the backing socket is closed?Java 流应该在后备套接字关闭之前关闭吗?
【发布时间】:2012-06-18 01:52:41
【问题描述】:

我有以下代码:

public void disconnect()
{
    running = false;
    if(thread != null)
        thread.interrupt();
    thread = null;

    try
    {
        socket.close();
    }catch(Exception e){e.printStackTrace();}
}

我有一个从流中收集输入的 BufferedReader 和一个通过输出流发送消息的 PrintWriter。在我关闭套接字之前是否应该关闭 BufferedReader 和 PrintWriter?让 i/o 流保持打开状态是不是很糟糕?

【问题讨论】:

  • 使用流的代码应该能够对 IO 异常做出反应,这些异常可能(并且将会)由于后台意外关闭(本地代码或网络错误等)而导致。
  • @user166390 网络错误不会导致“关闭支持 [socket]”。它保持打开状态,直到创建它的应用程序关闭它。

标签: java sockets networking optimization io


【解决方案1】:

根据Java Networking Tutorial

“在关闭套接字本身之前,您应该关闭连接到套接字的所有流。”

【讨论】:

  • 这还不够。看我的回答。
  • EJP 是对的,该问题的完整答案需要涵盖询问是否将更高级别的流打开是否不好的位。而引用的句子并没有涵盖这一点。
【解决方案2】:

必须关闭输出流,这样它就会被刷新。这将关闭套接字和输入流。关闭其中任何一个都会关闭另外两个。您根本不需要关闭输入流。严格来说,为了安全起见,您可能还应该在 finally 块中关闭套接字本身。

【讨论】:

  • 不关闭输入流会导致系统资源泄漏,所以我真的不喜欢这个建议。是的,当流被 GC 时,我认为它的终结器确实释放了资源,但是使用 GC资源处理也是有充分理由的。
  • @Voo 你错了。不关闭输入流不会不会“导致系统资源泄露”。这里唯一起作用的“系统资源”是套接字,它确实被关闭了。
  • @user207421 在很多帖子中看到你关于关闭套接字相关资源的论点,我仍然很想知道:既然关闭输出也会关闭套接字,为什么我们还需要为了“安全起见”而关闭套接字?这种“为了安全”的预防措施在什么特定情况下会显示出他的力量?
【解决方案3】:

如果您不关闭BufferedWriter,您可能会丢失一些缓冲但未刷新的数据。

还有一种观点认为你不应该使用PrintWriter,或者在使用时要小心,因为它会吞噬IOExceptions。

【讨论】:

    【解决方案4】:

    您打开的每个流都使用操作系统资源。当您在流上调用 close 时,它​​被标记为垃圾收集,并且内存在 GC 之后被释放。如果您不关闭流,它将被 GC 关闭(http://docs.oracle.com/javase/7/docs/api/java/io/FileInputStream.html#close%28%29),但完全不清楚 GC 何时会命中该对象。

    所以最好关闭流以立即释放内存。

    【讨论】:

    • 关闭流会释放底层资源,例如一个套接字或文件fd。关闭流并不会将其标记为垃圾回收,或以任何方式使其可用于 GC。事实上,没有什么可以标记垃圾收集。 Java GC 的工作原理是可达性,而不是标记。
    猜你喜欢
    • 2013-07-17
    • 2017-09-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多