【问题标题】:Java Garbage CollectionJava 垃圾回收
【发布时间】:2010-05-26 05:19:12
【问题描述】:

我想知道在 Java 中发生的垃圾收集。它真的能够处理所有未使用的对象并释放尽可能多的内存吗?

我还想知道 Java 垃圾收集与另一种语言(比如 C#)相比如何?然后,自动垃圾收集与 C 等语言的手动收集相比如何?

【问题讨论】:

  • 您比较垃圾收集的哪些方面?垃圾收集是一个活跃的研究领域,在过去的几十年里一直如此。只是要求比较的一般问题可能会在此处关闭,因为 SO 答案无法容纳数十年的研究结果。
  • 这个问题似乎过于宽泛
  • 我不会担心 - GC 做得很好。如果您遇到问题,请发布您的问题并获得答案。
  • @Greg,我不想比较 GC 的任何特定方面,我想要一个广泛的概述。我确实知道我的问题对其他人来说可能有点模糊,但我问的正是我想知道的。并不是说我对 GC 有任何问题,我只是坐着想知道。如果我需要更清楚我的问题,我不介意这样做。

标签: c# java comparison garbage-collection


【解决方案1】:

是的,这就是垃圾收集的重点。

有许多不同形式的垃圾收集。最简单的形式是引用计数,如果不增强算法,就无法处理某些类型的垃圾(循环引用)。

Java(Sun JVM)使用分代标记和清除收集器,尽管这不是标准化的,并且不同的 JVM 确实使用不同的收集器。我不知道 .NET CLR 使用的确切收集器。

垃圾收集器可以减少程序员的开销,并且可以使某些算法性能更好。但是,它们的内存占用通常比紧凑的手动分配系统要大。

关于这个主题的实际参考是book Garbage Collection,它写得很好而且很全面。

【讨论】:

  • 谢谢。会看看你推荐的书。
【解决方案2】:

真的能处理所有不用的对象吗

不,它不能。但是,它可以收集所有不能再使用的对象,而且它做得很好。区别很细微,见下文。


说明

例如,假设您有以下代码:

class A {
    public static Date d = new Date(); // d will never be collected
}

假设 知道在一定时间后d 将永远不会再被访问。但是,运行时系统没有这些信息,d 将无限期地保持活动状态,而在 C++ 中您可以显式删除它。

相反,垃圾收集器收集所有不再可访问的对象。例如:

void f() {
    Date d = new Date();
    System.out.println(d.toString());
} // d is no longer accessible at this point

垃圾收集器检测到d 引用的对象不可能再次被访问,因为d 是它的唯一引用,并且它在方法结束时超出范围。收集不可访问的对象是对“可以收集哪些对象”问题的低估,但它是安全的,因为它保证永远不会收集任何活动对象。

区别是微妙的,事实上,在大多数正常的代码中,所有不再使用的对象都会被收集。 该集合本身是完整的,能够正确识别和收集每个不可访问的对象,其中包括无法访问的对象,因为它们的所有引用都驻留在其他不可访问的对象中。

【讨论】:

    【解决方案3】:

    垃圾收集器搜索对象并检查它们是否被有效指针引用。如果没有,它们将被完全删除。这消除了潜在的问题,例如活指针引用死对象,从而卡在内存中无所事事。

    使用一种需要您自己分配、释放和重新分配空间的语言(例如 C)一开始可能会非常棘手,因为您需要完全控制为您需要的任何对象分配空间,并且- 分配您完成的任何对象,而不会忘记任何不需要的对象坐在某个地方占用空间。尽管它可能很棘手,但它确实具有性能优势。

    垃圾收集器倾向于在低级别取消分配空间,这可能会损害性能。不过,对于大多数应用程序来说,性能下降不会很大,因此并不明显。

    【讨论】:

      【解决方案4】:

      垃圾收集器是由实现定义的。存在不同类型的 GC;使用哪一个不是程序必须担心的。

      我不能说 C,但在 C++ 中,我们实际上很少使用成熟的垃圾收集器,因为 C++ 程序员拥有像 RAII 和引用计数智能指针这样有助于简化内存管理的技术。

      【讨论】:

      • “简化”是一个相对术语;)
      • 当您将使用“RAII 和智能指针”与“不使用 RAII 和智能指针”进行比较时,“简化”不是相对的 :)
      【解决方案5】:

      垃圾收集器(GC)不时运行以查找对象的引用。首先标记那些没有任何引用的,然后调用 finalize() 方法。下次将对象从内存中删除。 GC 使程序有点慢。您可以影响 GC 行为,但不能保证。

      【讨论】:

      • 简化??我认为托管语言比不使用 GC 的传统语言更简化。托管语言将内存管理的所有复杂性隐藏在底层,使开发人员更容易。
      • 你是对的。你的陈述中有什么我遗漏的吗?
      • "GC 使程序有点慢"。实际上,这取决于。甚至在某些情况下,GC 可以比手动内存管理更快。通常它只是没有区别......
      【解决方案6】:

      对于 .NET,请查看Garbage Collector Basics and Performance Hints,您还会在其中找到一些性能提示。

      对于 Java,请查看 Java theory and practice: Garbage collection and performance。在那里你也会发现一些提示和“反提示”,即使 GC 变得更糟的方法。

      【讨论】:

        猜你喜欢
        • 2014-03-09
        • 1970-01-01
        • 2011-06-25
        • 2016-01-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多