【问题标题】:Java object is gc-ed when it's still linked with a strong reference and a weaked reference [duplicate]当 Java 对象仍然与强引用和弱引用链接时,它是 gc-ed [重复]
【发布时间】:2019-12-11 06:49:57
【问题描述】:

这里有一个例子:

import java.lang.ref.WeakReference;

public class WeakRefTest {
    public static void main(String[] args) {
        Object obj = new Object();
        WeakReference<Object> weakRef = new WeakReference<Object>(obj);
        int i = 0;
        while (true) {
            if (weakRef.get() != null) {
                i++;
                System.out.println("The object is alive for " + i + " loops - " + weakRef);
            } else {
                System.out.println("The object has been collected.");
                break;
            }
        }
    }
}

当运行这个程序时,我们会在一段时间后得到"The object has been collected."的输出,这意味着对象将被gc-ed。

但是,仍然有一个名为"obj" 的强引用链接到该对象,如何回收它?因为JVM后来发现没有强引用使用,所以不强可达?

【问题讨论】:

  • 但是,仍然有一个名为“obj”的强引用链接到该对象你到底是什么意思?究竟是谁在阻止Object 被收集?
  • @Eugene 为什么要重新打开? Stuart Marks 的回答解释说,obj 可以被收集,因为程序中没有任何内容,在它被用于初始化 WeakReference 之后,使用它。即使堆栈上有对它的“强引用”,它也不能“在任何活动线程的任何潜在持续计算中访问”,因此可以被收集。副本没有解决WeakReference,但这与程序的行为无关,它是Object的集合。

标签: java reference


【解决方案1】:

由于您的循环在资源使用方面运行得非常“热”,JVM 将希望对其进行优化。这样做可能会使编译器指出事实上进入循环后无法达到强引用,从而将其优化掉。

如果您在循环后添加 System.out.println(obj) 之类的内容,此行为可能会发生变化。您可能需要调整循环条件,以便编译器无法看到新语句实际上是无法访问的代码......(类似于while (weakRef.get() != null)

【讨论】:

  • 我不明白,所以你究竟是如何理解这部分问题的:但是,仍然有一个名为“obj”的强引用链接到该对象,它怎么能被回收? OP 的意思是obj 引用weakRef 吗?如果是这样,这与JVM优化无关
  • 变量 'obj' 存储了对存储在 weakRef 中的对象的引用。
【解决方案2】:

WeakReference 不会使所指对象强可达,这会破坏WeakReferences 的全部目的。比如这个:

 public static void main(String[] args) {

    Object obj = new Object();
    WeakReference<Object> weakRef = new WeakReference<>(obj);

    while (weakRef.get() != null) {
        System.out.println("Object is still alive");
        System.gc();
    }

    System.out.println("Collected : " + weakRef.toString());
}

我们仍然会看到Collected(最终,希望如此),然后是来自toString 的一些hash;证明即使weakRef 不可访问,所指对象也已经消失。

还有,这句话:

因为后来JVM发现没有强引用使用,所以不强可达?

不要将可达性与引用的类型混淆,即使是强可达对象也可以变成可达;同样可以收集它们。强可达对象只不过是java中的普通引用,想象一下如果这不是GC-ed...

【讨论】:

  • 我不认为他们声称WeakReference 使对象[强烈] 可达。他们在谈论obj,在他们的sn-p 中,它从未被分配任何其他值。因此有一个对Object 对象的强引用,经典学派认为强引用会阻止GC。您的 sn-p 将 null 分配给 obj 并因此删除了对 Object 对象的强引用,因此您正在更改问题的上下文。
  • 至于您的最后一段,他们所描述的(使用一些错误的术语)实际上是正在发生的事情。 一个 reachable 对象不能被最终确定和收集。 所以即使通过obj 变量对该对象进行强引用,相应的对象也不再可以被程序,这就是它可以被收集的原因(就像旧的重复链接解释的那样)。我相信这就是他们的困惑所在。
  • @SotiriosDelimanolis 确实是重复的,我花了一段时间才承认这一点。
  • 一切都好,但您是否也想解决这些 cmets 问题,以便我重新投票^?
  • @SotiriosDelimanolis 啊! obj = null 的分配不是我应该发布的,我同意
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-21
  • 2014-10-18
相关资源
最近更新 更多