java - 为什么当你有 finalize() 时关闭资源很重要

标签 java garbage-collection resources

好的,所以我知道您应该始终关闭您的流和其他 native 资源,但我目前不确定原因。

我明白其中一个原因,那就是可用资源数量有限,您希望在用完后立即释放它们。 但是让我们假设您的应用程序不使用那么多资源,那么应该不需要关闭资源吧?

特别是因为您有 finalize() block ,它应该在 GC 到达时关闭所有 native 资源。

最佳答案

假设“你有 finalize() block ,当 GC 到达它时应该关闭所有 native 资源”首先是错误的。无法保证表示 native 资源的每个对象都具有这样的 finalize() 方法。

其次,资源不一定是native资源。
当你有,例如BufferedOutputStreamObjectOutputStreamZipOutputStream 包装 FileOutputStream,后者可能有一个 finalize () 方法释放底层 native 资源(依赖于实现),但不会写入正确写入数据所需的包装流的任何待处理数据。关闭包装器流是强制性的,以确保写入的输出是完整的。

天真地向这些包装流类添加一个 finalize() 方法来关闭它们是行不通的。当流对象被收集时,这意味着没有对它的引用,换句话说,不再有定向的应用程序→包装流→ native 流图。由于对象图可能是循环的,因此无法保证在死对象之间进行昂贵的顺序搜索会成功,这就是 JVM 甚至不尝试的原因。

或者,作为 the specification说:

The Java programming language imposes no ordering on finalize method calls. Finalizers may be called in any order, or even concurrently.

因此,包装器的 finalize() 方法不能保证在底层原生流的 finalize() 方法之前被调用,因此,底层原生流流可能在包装流之前已经完成并关闭,因此无法写入挂起的数据。

兔子洞变得更深了。对象实例由 JVM 根据代码需要维护,但代码可以优化为直接使用封装数据。如果包装流类具有 finalize() 方法,您可能会发现包装实例甚至可以比预期更早被释放,如 finalize() called on strongly reachable object in Java 8 中所述。 .

或者,简而言之,显式关闭是确保它在正确的时间点准确发生的唯一方法。

关于java - 为什么当你有 finalize() 时关闭资源很重要,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46558100/

相关文章:

java - 如何在android中定义地理围栏的矩形

java - 基于时间和大小的记录器备份策略

c# - 在什么情况下,引用会指向排队等待垃圾回收的对象?

java - 从 URL 获取图像返回 NullPointerException (Java)

Java 中垃圾收集器的出现

Java PhantomReference 与 finalize()

java - 如果在 preparedstatement.execute() 期间互联网中断,则在 JDBC 上下载 blob 文件会导致内存泄漏

java - Class.getResource 中奇怪的区分大小写错误?

java - InputStream的AudioInputStream(从资源目录加载)

java - 在消息资源文件中查找未使用的值