【问题标题】:Questions related to Garbage Collector and finalize() methodGarbage Collector 和 finalize() 方法相关的问题
【发布时间】:2014-03-14 11:37:27
【问题描述】:

我正在阅读有关 Java 的垃圾收集和 finalize() 方法的内容,其中一些疑问引起了我的注意。对不起,如果您认为这些怀疑真的很愚蠢。

  1. 我正在阅读文章http://javarevisited.blogspot.com/2011/04/garbage-collection-in-java.html。在这方面,第 5 点说: '在从内存中删除对象之前,垃圾收集线程调用该对象的 finalize() 方法,并提供执行所需的任何类型清理的机会'。 那么这件事肯定会发生吗?我的意思是在执行垃圾收集器方法之前总是调用 finalize() 方法吗?

  2. 垃圾收集器如何知道它需要执行?比如我有一个应用部署在服务器上,那么 GC 什么时候执行呢?它是定期执行,还是在收集一些(比如 1MB)垃圾并执行触发器或其他什么时执行,或者它只是随机的,无法确定何时执行?

  3. 由于没有进行垃圾回收,它如何降低我的应用程序的性能?

  4. 假设我的堆中有很多垃圾,但没有执行垃圾收集器。如果发生这种情况,那是不是 JVM 的不良行为或缺陷?

  5. 我们可以说在 C/C++ 中手动完成的垃圾收集比在 Java 中更好,因为我们作为程序员足够聪明并且知道什么时候需要处理掉“不那么引用” ' 指针?

【问题讨论】:

  • 不幸的是,finalize 不会“肯定”发生。它最初的设计方式存在几个错误,使其相当不可靠。
  • 一般来说,GC 做得足够好,你根本不需要编写终结器;有 一个 例外:如果您使用需要释放的本机资源。 GC 无法关心它们,因为它不知道它们。
  • 系统不会随着“垃圾”的积累而变慢。确实,垃圾占用了空间,但在释放对象之后,C++ 堆中的释放空间也是如此。最多,GC 环境可能需要稍大的工作集。
  • 没有“手动垃圾回收”之类的东西。
  • @FredOverflow - 你想在星期三晚上来我们家吗?

标签: java c++ c garbage-collection


【解决方案1】:
  1. finalize() 应该在对象被清理之前发生。问题是 - 你不知道它什么时候会发生(以及它是否会发生)。不要指望finalize 进行清理,只需在对象失去其范围之前自己进行清理。另外,请注意finalize() 在垃圾回收周期上运行。这意味着如果您实现finalize,您的垃圾对象将需要 2 个周期来清理,这意味着可以清理的内存浪费。还有更多 CPU 将被消耗以运行 finalize,而你不知道何时。如果您有很多具有finalize 的对象,那么它们可能会在 GC 期间一起运行,这可能会暂停整个应用程序很长一段时间

  2. 您可以调整不同的算法来决定垃圾回收发生的时间。此外,它取决于您分配给 JVM 的堆大小(以及其他参数,例如旧代与新一代大小、幸存者空间大小等)。如果您正在处理小型应用程序 - 通常默认配置对您来说就足够了。如果您正在编写大型应用程序并且需要考虑随时间变化的性能、CPU 时间和暂停时间(有时 GC 会暂停整个应用程序),那么您最好阅读有关堆内存模型以及可以调整的不同 GC 算法和参数的信息控制 GC 以更好地满足您的需求。

  3. 您的应用程序性能受发生的 GC 周期(而不是未发生的 GC 周期)的影响。例如 - 如果你的堆太小,你会有频繁的循环。如果您的堆太大,您的循环频率会降低,但每个循环可能需要更长的时间来执行。同样,这完全取决于您选择的 GC 算法和调整参数以及堆内存分配(年轻代有多少内存,老一代有多少内存,幸存者空间比率等等......)

  4. 我没有看到您有大量垃圾并且没有收集的情况,除非仍有足够的空间来分配新对象。当空间用完或即将用完(取决于您选择的收集算法和堆大小和其他参数)时,就会有一个收集。

  5. Java 垃圾收集器解决了程序员在CC++ 等非托管语言中遇到的痛苦问题。它有它的优点和缺点。当你需要绝对控制你的记忆时,你会使用C。如果您想更轻松地编写系统,并且不介意为 GC 分配一些额外的内存,并与 GC 共享一点 CPU 时间,那么您可以编写得更快(也更健壮 - 因为更少内存泄漏和其他讨厌的东西)与java。

【讨论】:

    【解决方案2】:
    1. 将始终在对象被垃圾回收之前调用 finalize() 方法。没有“垃圾收集器方法”。

    2. 垃圾收集器将在需要时运行。作为程序员,你无法控制它。从技术上讲,您可以通过制造大量垃圾或调用 System.gc(),但您不需要这样做。

    3. 垃圾收集器将在需要时运行。作为程序员,您不必担心垃圾收集器的性能,但有一些命令行选项可以调整垃圾收集器的行为。

    4. 如果内存不足并且垃圾收集器没有运行,那就是 JVM 缺陷。不过,它会运行。垃圾收集器将在需要且高效时运行。如果在收集任何垃圾之前让堆填满垃圾更有效,那么它会这样做。

    5. 这是一个非常主观的问题,双方都有充分的理由。 Java 的垃圾回收减少了编程错误,但 C 和 C++ 的手动内存管理提供了更一致的性能和内存使用。

    【讨论】:

      【解决方案3】:

      [1] finalize 调用是垃圾回收的一部分。

      [2] 垃圾收集器的策略和调用是实现的一个细节。因此这里没有答案。

      [3,4] 如果你有很多微小的垃圾,收集器可能不会执行垃圾收集。这种方式可能会浪费内存(我认为这是内存泄漏),如果“微小”对象持有收集器不知道的内存(图像可能由指向本机内存的微小句柄/指针表示)。

      [5] C++ 的概念非常不同(这里省略C)。析构函数可以在确定点执行以释放分配的资源(参见:RAII)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-07-01
        • 1970-01-01
        • 2019-04-10
        • 2021-10-12
        • 2011-03-19
        • 2011-08-17
        • 2022-01-25
        • 2020-01-22
        相关资源
        最近更新 更多