Java 输入/输出流是否在销毁时关闭?

Java 输入/输出流是否在销毁时关闭?,java,scope,Java,Scope,Java中的InputStreams和OutputStreams是否在销毁时关闭()?我完全理解这可能是坏的形式(特别是在C和C++世界),但我很好奇。 另外,假设我有以下代码: private void foo() { final string file = "bar.txt"; Properties p = new Properties(); p.load( new FileInputStream(file) ); //... } 没有名字的FielePix

Java中的InputStreams和OutputStreams是否在销毁时关闭()?我完全理解这可能是坏的形式(特别是在C和C++世界),但我很好奇。 另外,假设我有以下代码:

private void foo()
{
    final string file = "bar.txt";
    Properties p = new Properties();
    p.load( new FileInputStream(file) );
    //...
}

没有名字的FielePixStand在P. Load()之后脱离范围,因此被破坏,有点像C++范围规则吗?我试着在谷歌上搜索java的匿名变量范围,但结果并没有达到我的预期


谢谢。

不,Java中没有析构函数。即使对对象的一个特定引用超出范围(或被修改),也可能存在对该对象的其他引用。如果对象不再可访问,则流可能会在稍后某个时间调用其最终器,从而关闭流

Properties.load
是一种特殊的方法,它关闭传递给它的流。编辑:
Properties.loadFromXML
是我五年前一直在思考的一种特殊方法。(API文档可能应该说在前面而不是后面。)谢谢@tzimnoch。

变量超出范围,因此被销毁。但是在Java中,变量和变量指向的对象之间有很大的区别


仅当变量超出范围时,指向的对象不会被销毁。当java运行时引擎决定它感觉像是在破坏任何范围内的变量所指向的对象时,对象就被破坏了。

< P>第一个答案:在爪哇中没有C++中的“破坏”。只有垃圾收集器,当它看到一个准备被收集的对象时,它可能会也可能不会醒来并完成它的工作。Java中的GC通常是不可信的

第二个答案:有时是,有时不是,但不值得冒险。发件人:

并非所有流都需要关闭字节数组输出流不需要关闭 例如,需要关闭。但是,与文件关联的流 网络连接在使用完毕后应始终关闭。 例如,如果您打开一个文件进行写入,但在 您完成后,其他进程可能会被阻止读取或删除 正在写入该文件


根据哈罗德的说法,输入或输出流也是如此。也有一些例外(他在System.in中指出),但一般来说,如果您在完成时不关闭文件流,您就是在冒险。并在finally块中关闭它们,以确保即使抛出异常也能关闭它们。

我过去认为流最终会通过垃圾收集自动关闭,但轶事证据表明,手动关闭它们的失败会导致资源泄漏。您将希望执行以下操作:

InputStream stream = null;

try {
  stream = new FileInputStream("bar.txt");
  Properties p = new Properties();
  p.load(stream);
}
catch(Exception e) {
  // error handling
}
finally {
  closeQuietly(stream);
}
closequityle()
是Apache的commons io库中的
IOUtils
上的一个方法。

简短的回答是“可能,但不要打赌!”

在实现FileInputStream的类堆栈中的某个地方有一个类,该类有一个
终结器
,它将在流运行时有效地关闭流(并释放资源)

问题是不能保证终结器会运行。引用JLS(第12.6节):

Java编程语言不支持 指定终结器的运行时间 被调用,除了说它会 发生在存储之前 对象被重用

这使得流最终确定有问题:

  • 如果流对象永远不会变成垃圾,它将永远不会被最终确定
  • 如果流对象是终身的,则可能需要很长时间才能对其进行垃圾收集和最终确定
  • 在执行终结器之前,JVM可能需要在对象被标识为不可访问之后执行额外的GC循环。这当然是JLS允许的
  • JVM永远不执行终结器在技术上是合法的,只要它永远不使用终结器重用对象存储。(我不知道有任何生产质量JVM采用这条生产线,但您永远不知道…)

  • 没有析构函数,但有终结器。来自java.io的大多数InputStream/OutputStream类的终结器都会关闭该流。@chsply76:对,但无法保证何时甚至是否调用终结器。没有一个“此方法返回后,指定的流将保持打开状态。”感谢所有人的帮助!请注意,使用Java 7或更高版本中的资源进行的
    try
    将使解决此问题成为一个相对简单的操作(只需要一个额外的变量赋值,当然还有
    try
    本身)。还请注意,上面的代码将在我的Eclipse环境中生成一个警告(关于缺少关闭)。(不要宽恕自己不打扫卫生。)你可能会认为。。。但是,如果文件描述符用完,则不会触发GC运行,该GC运行将检测到其他流对象(假设)现在是可终结的。@mike jones:不是这样的。这是可以实际证明的。内存不足可能会触发垃圾收集(它甚至被要求在抛出
    OutOfMemoryError
    之前尽最大努力),但gc与终结不同。垃圾收集将导致带有终结器的对象排队等待稍后的终结,但在何时进行终结时,它是完全未定义的。因此,尽管文件描述符(或任何其他非内存资源)耗尽,但无论如何都不会触发gc(正如Stephen已经指出的),即使触发了gc,也不会强制完成。