【问题标题】:How to mark an object for garbage collection by the GC (Garbage Collector)?GC(垃圾收集器)如何标记一个对象进行垃圾收集?
【发布时间】:2011-07-16 22:17:40
【问题描述】:

在 Java 中,有没有办法在其下一个清理循环中标记一个对象以供 GC 进行垃圾回收?

我听说将对象设置为null 不再有效。

【问题讨论】:

  • 您能否提供一些链接或文档说明为什么将对象设置为null 不起作用?当然,设置为 null 也不能保证它会被 gc'ed 。
  • 一旦您消除了对某个对象的所有引用(例如通过设置对null 的引用),它就成为符合垃圾收集的条件。在回收该内存之前,您不会用完内存(假设它会在堆空间用完和堆空间用完之间产生差异)。 GC 实际发生的时间取决于 VM。为什么你会担心?
  • 这是一个问题,因为我正在处理大量包含大量数据的对象。分配通常一次达到 1000 个。

标签: java memory garbage-collection


【解决方案1】:

不,你不能。如果另一个变量引用了它,你会期望发生什么?

请注意,您不能将 object 设置为 null - 您只能将 variable 设置为 null。如果另一个变量仍然有对该对象的引用,它仍然不符合垃圾回收的条件。

如果你认为你需要这样做,那可能意味着你误解了你的数据 - 或者你的代码中的某处可能有泄漏(例如,你只添加条目的列表,由静态变量引用- 当类加载器处于活动状态时,这些条目将永远无法进行垃圾收集)。

每个 JVM 都有自己的 GC,但在 Hotspot 中,对象将在下一次 GC 运行到该对象当前“存在”的一代时被垃圾收集(假设它没有终结器,这会使事情复杂化)。如果对象在“年轻”一代,那可能很快就会发生——如果它在“老”一代,可能需要更长的时间。

您可能希望查看Java 6 GC tuning documentation 以了解更多信息,当然,从那时起,OpenJDK 7 等的事情已经发生了变化。

【讨论】:

  • 好吧,正如我在评论中所说,我正在创建很多很多对象,在完成处理后,我不再需要它们了。我怀疑[分析器支持]它们没有被破坏。
  • @monksy:那么这表明你有一个关于他们潜伏在某个地方的引用,假设 GC 正在运行。
  • 那是我的怀疑[当前启动的对象数量很少下降,而且还在不断增长]您有什么工具可以帮助解决这个问题吗?我不得不使用 Netbeans Profiler 来找出答案。
  • @monksy:恐怕我没有任何建议 - 我已经很久没有使用 Java 分析器了 :(
  • 在一些有效的用例中您需要这样做。例如,如果您正在编写内存缓存,您可能希望定期删除较少使用的条目以避免内存泄漏,但您可以将其设为软引用,而不是将条目设置为 null,这样在清理对象之后仍然可用直到垃圾收集
【解决方案2】:

我知道这个问题已经得到解答,但是您可以通过一些方法来控制 Java 垃圾收集器查看您的引用的方式。您可以通过软引用、弱引用和幻像引用来做到这一点。查看java.lang.ref package 以获得更好的解释。

这里还有一个nice sample,用于确定 PhantomReference 何时将被垃圾回收:

幻像引用用于确定对象何时即将被回收。幻影引用比终结更安全,因为一旦一个对象幻影可达,它就不能被复活。

// Create the phantom reference.
ReferenceQueue rq = new ReferenceQueue();
PhantomReference pr = new PhantomReference(object, rq);

// Wait until the object is about to be reclaimed.
try {
    while (true) {
        Reference r = rq.remove();
        if (r == pr) {
            // The object is about to be reclaimed.
            // Clear the referent so that it can be reclaimed.
            r.clear();
        }
    }
} catch (InterruptedException e) {
}
【解决方案3】:

Java 垃圾收集器使用标记和清除方法。这意味着从已知仍在使用的对象中跟踪所有引用,并标记以这种方式访问​​的对象。这样,根本没有引用的对象就不会被标记,并且应该确保被删除。因此,您可以确保删除对该对象的所有引用,以便在垃圾收集器的下一轮中删除该项目。

另外你可以使用

Runtime.getRuntime().gc();

表示垃圾收集器应该运行。注意:你不能确定它是否真的运行。

【讨论】:

  • 垃圾收集器不是基于引用计数的。所有现代 JVM 都是标记和清除的,其中大多数是多代的。
  • 不依赖JVM的实现吗?
  • 没有。由于引用周期的问题,引用计数将不允许您正确实现 Java 语言规范。因此,不仅没有现有的 JVM 实现使用引用计数,而且如果不实现完全不同且正确的收集机制,任何一个都不能并且符合。
  • @Mike Samuel。好的我明白了。我改变了答案。
【解决方案4】:

你听错了,但是描述也是错误的。

您没有将对象设置为null,而是将变量设置为null。如果该变量可用于获取某个对象,则该变量具有该对象的引用。将变量设置为null 与变量“失去对对象的引用” 相同。

一旦 Java 检测到正在运行的程序无法访问一个对象或一组对象,它将从内存中删除这些对象。它不会立即将它们从内存中删除,因为如果这样做了,并且程序的其他部分尝试使用对该对象的引用,那么该引用将以 Java 不允许的方式失败。

诀窍不是只设置一个对null 的引用,您必须设置所有可能对null 进行的引用。这就是为什么每次创建新引用时都要考虑的重要原因,因为您希望以最终将被清除的方式创建它们(除非您想要内存泄漏)。

【讨论】:

    猜你喜欢
    • 2018-06-10
    • 2011-02-08
    • 1970-01-01
    • 2014-08-26
    • 2023-03-30
    • 1970-01-01
    • 2018-12-30
    • 1970-01-01
    • 2010-11-08
    相关资源
    最近更新 更多