【问题标题】:In which cases is finalize() actually USED?在哪些情况下 finalize() 实际使用?
【发布时间】:2014-09-16 13:54:54
【问题描述】:

我发现多个帖子说明什么时候不应该使用 finalize() 并且一般不应该使用它,因为没有人保证对象会在应用程序的生命周期内被垃圾收集(除非你真的需要整个应用程序生命周期中的对象,这是我书中的内存泄漏)。但是假设我有一个 Java 类,它通过 JNI 在本机空间中初始化某些东西(进行内存分配和初始化)。就我而言,有两种方法可以实现:
1、在类中实现init()和deinit()方法,进行原生初始化和反初始化。这有一个缺点,我必须处理对象生命周期并且不能将其留给垃圾收集器(这不是很像 Java)。
2. 在构造函数中进行初始化,在 finalize() 方法中进行反初始化。这基本上使对象能够像任何其他 Java 类一样自动进行垃圾收集。

我要问的是 - 我有理由不选择 2 号吗?

谢谢,
内德

【问题讨论】:

  • 所有相同的原因:特别是,不能保证何时调用它。通常,手动管理本机对象是一种惯例,try-with-resources 使某些用途更容易。
  • 使用 finalize 来确保在 JNI 代码中释放内存是 finalize 的常见用法,并且完全没问题。我会同时使用这两种方式。
  • 为什么这被否决了?我认为这个问题是完全合法的......
  • @NESPowerGlove:如果我严格使用 finalize() 来释放内存,如果大量内存分配在本机空间而不是 Java 空间中,是否会调用 GC?是否保证定期调用 GC,因为我的大部分内存分配将在本机空间中完成?

标签: java android garbage-collection


【解决方案1】:

我要问的是 - 我有理由不选择 2 号吗?

其中一个原因是,在 GC 回收其finalize 方法将回收它的 Java 对象之前,本机资源不会被释放。

这个原因是否真正相关取决于原生资源的性质。


真的,仔细想想,这与 Java 设计者关于关闭流的争论是一样的。

  • 他们可能没有提供close() 方法,而将其完全留给finalize 方法...除了这会导致输出流没有足够快地刷新,并且用完的问题“文件描述符”。

  • 他们本可以将其完全留给close() 方法...除非你确实忘记了close() 一个文件(并且没有finalize 方法)你会泄漏文件描述符...永久。

  • 相反,他们实现了close()finalize,并且他们实现了后者来调用前者。因此,您可以获得在程序这样说时关闭的优势,如果它忽略调用 close(),则需要清理一些东西1

1 - 当然,如果您依赖流finalize 方法进行清理,可能会出现问题;例如如果流仍然可以意外访问,或者如果它没有足够快地收集垃圾,并且无论如何您都会用完文件描述符。并且不确定的刷新输出也可能是一个问题。


好的。当所讨论的资源纯粹是内存时呢?那不就和垃圾回收一样吗?

我没看到。真正的垃圾回收不依赖于您实现 finalize 方法、close 方法或其他显式释放内容的方法。

【讨论】:

  • 好的。当所讨论的资源纯粹是内存时呢?那不是和垃圾收集一样吗?但我喜欢同时实现两者的想法,我可能会同意。
【解决方案2】:

当应该释放资源时,代码执行不一定会释放资源。因此,一旦您知道如果这些资源很重要,就不再需要这些资源,我就会使用 finalize。如果资源很小,请不要使用 finalize,因为它会带来开销。

【讨论】:

    猜你喜欢
    • 2023-03-12
    • 2021-09-14
    • 1970-01-01
    • 2023-04-02
    • 1970-01-01
    • 2021-11-06
    • 2016-03-02
    • 2012-02-11
    • 2016-02-19
    相关资源
    最近更新 更多