【问题标题】:When you discard the reference to a SoftReference, will it's clearing still be put on the ReferenceQueue?当您丢弃对 SoftReference 的引用时,它的清除是否仍会放在 ReferenceQueue 上?
【发布时间】:2020-09-20 05:02:58
【问题描述】:

我想了解垃圾收集器在什么情况下会通知您清除软引用。文档清楚地表明,当可能发生 OOM 时会发生这种情况,但是如果您完全丢弃引用,GC 会出现并收集 SoftReference 可能会注意到不存在其他强/软引用并清除内部引用值。

ReferenceQueue<Object> cleared = new ReferenceQueue<>();
Object X = new Object();
SoftReference<Object> Xs = new SoftReference<>(X, cleared);

Thread.sleep(10);
X = null;
Xs = null;

System.GC();
Thread.sleep(100);
Reference ref;
while ((ref = cleared.poll()) != null) {
   System.err.println(ref);
}

那么关于这个队列的规则记录在哪里?一定有比我要问的更多的极端案例,所以也许这个问题必须扩大一点。

【问题讨论】:

    标签: java garbage-collection java-memory-model soft-references


    【解决方案1】:

    相关点可以在通知部分的the package documentation找到:

    已注册的引用对象与其队列之间的关系是片面的。也就是说,队列不会跟踪向其注册的引用。如果已注册的引用本身变得无法访问,那么它将永远不会入队。使用引用对象的程序有责任确保只要程序对它们的引用对象感兴趣,这些对象就一直是可访问的。

    所以答案很简单。由于您将引用SoftReference 的唯一变量设置为null,因此它永远不会被排队。它是否会被收集或清除,没关系,因为你无法感知它。在实践中,典型的实现会像 Eugene 写的那样,垃圾收集器只遍历活动引用,并不关心剩余内存中存在什么样的垃圾。

    【讨论】:

    • 这比我写的和文档中的内容要准确得多。非常好的先生。
    • 谢谢,错过了,总是忘记看包文档。
    【解决方案2】:

    在我看来,您的问题不止一个。第一个是当引用将出现在引用队列中。

    文档(故意?)留有解释空间,取自here:

    提供引用对象类,这些类支持与垃圾收集器进行有限程度的交互。程序可以使用引用对象来维护对某个其他对象的引用,这样后一个对象仍然可以被收集器回收。 在收集器确定给定对象的可达性发生变化后的某个时间,程序也可以安排收到通知。

    所以,它发生在之后的某个时间。在当前的实现下它是一个异步进程,所以文档没有错。

    你的第二个问题是从一个错误的前提开始的:

    ... GC 会过来收集 SoftReference...

    不是真的。如果此 SoftReference 不可访问,GC 甚至不会知道它的存在。 GC 找到 alive 对象,而其他一切都是垃圾,听起来很奇怪。因此,GC 甚至不会知道存在 SoftReference,因为它从未访问过它。发生这种情况时,ReferenceQueue 上没有任何内容。为此,需要遍历 SoftReference,但因为这从未发生过......

    仅仅因为SoftReference 不可访问并不意味着所指对象的相同。所指对象可强可达是完全有效的,但 SoftReference 不可可达。

    到你的最后一点(我暗示你会关心):当 SR 是可达的,但所指的对象已经死了。当GC发现这样的事情时,它应该清除引用(后续get将返回null)并将其发布到ReferenceQueue,对吗?嗯,差不多。这取决于实际的 GC。作为一个反例,以Shenandoah GC 为例,它有一个名为ShenandoahRefProcFrequency 的标志(默认为5)。它显示了弱引用应该多久被清除一次,如果不是5,当这种情况发生时:引用被声明为“活动的”。在达到该限制之前,该指示物会被人为地保持活动状态。

    【讨论】:

    • 感谢您的详细信息!我一直认为 Soft/Weak/PhantomReferences 以特定方式注册自己,但阅读本文我意识到在 GC 发现阶段以特殊方式处理它们更有意义。就像你说的那样,另一个答案指向正确的文档部分,所以我会接受,但你有我的 +1 ;)
    • @DavyLandman 是的,它们在发现过程中受到特殊处理,但在 STW 阶段被处理。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-17
    • 1970-01-01
    • 1970-01-01
    • 2021-08-30
    • 2010-11-06
    • 2020-06-22
    • 1970-01-01
    相关资源
    最近更新 更多