try-with-resource是否有可能无法关闭资源?

时间:2016-04-25 02:39:37

标签: java

根据Oracle文档

  

try-with-resources语句是一个声明一个或多个资源的try语句。资源是一个对象,必须在程序完成后关闭它。 try-with-resources语句确保在语句结束时关闭每个资源。实现java.lang.AutoCloseable的任何对象(包括实现java.io.Closeable的所有对象)都可以用作资源

如果资源没有实现AutoCloseable,则无法在try块中声明它,它必须在body部分中声明。必须在finally块中显式关闭。 try-with-resource是否有可能无法清理资源,除非您使用不正确的习惯用法,如果有嵌套资源& close()调用对底层资源不是幂等的? 我所理解的是try-with-resource只能确保在场景后面调用close(),但如果close本身不关闭底层资源,try-with-resource将无法清理资源。 有没有人有相反的观点或更多的澄清?

2 个答案:

答案 0 :(得分:1)

忽略实际上不起作用的代码(比如你的close()方法没有实际关闭资源的例子)或者人们将调试器附加到边步清理这样的完全外部因素,我可以想到三种情况try-with-resources可能无法清理资源:

  • 电源故障,硬件故障,操作系统崩溃或VM崩溃。任何软件都无法做到这一点,因此它们超出了资源处理的范围。但是,如果您正在考虑使用try-with-resources语句来管理强制锁定文件和诸如此类的东西,您仍需要牢记这一点。
  • 异步异常,例如Thread.stop()生成的异常。如果在清理代码中以这种方式“停止”某个线程,则清除代码将被中止。此类异步异常的不安全性是Thread.stop()deprecated并替换为Thread.interrupt()的原因,这是安全的。
  • 如果调用System.exit()。这可能被认为是上述任何一种情况,除非它可能在“正常情况下”发生。

在所有其他方面,您应该能够放心,close()将被召唤。尝试使用多个资源与嵌套的try块相同,因此抛出异常的清理代码不会阻止其他清理例程。

答案 1 :(得分:0)

try (FileSystem fs = FileSystems.getDefault()) {
    return fs.getPath(aStringVar);
}

如果FileSystems.getDefault()返回sun.nio.fs.UnixFileSystem,就像在使用Java 8 SE的RedHat机器上为我做的那样,它会在关闭时抛出UnsupportedOperationException。尽管IntelliJ显示警告并告诉你将其包装在try-with-resources中,但你不应该这样做,除非你想处理那个愚蠢的例外。