Java:WeakReference.get()未返回null

Java:WeakReference.get()未返回null,java,Java,我对WeakReferences不熟悉,所以我只是想了解一下。我拼凑了这段代码来测试他们的行为。我计划在我正在工作的项目中使用它们,因为我需要临时跟踪对对象的引用。也就是说,我想在收藏中引用它们,只要它们不在其他地方使用 不过,到目前为止,这个简短的测试代码示例并没有像我希望的那样工作。无论我等待多长时间,weakRef.get()总是返回值,它从不返回null 请帮我找出我做错了什么。谢谢 public static void main(String[] args) throws Except

我对WeakReferences不熟悉,所以我只是想了解一下。我拼凑了这段代码来测试他们的行为。我计划在我正在工作的项目中使用它们,因为我需要临时跟踪对对象的引用。也就是说,我想在收藏中引用它们,只要它们不在其他地方使用

不过,到目前为止,这个简短的测试代码示例并没有像我希望的那样工作。无论我等待多长时间,weakRef.get()总是返回值,它从不返回null

请帮我找出我做错了什么。谢谢

public static void main(String[] args) throws Exception{
    String s = "Hello World!";

    WeakReference<String> weakRef = new WeakReference<>(s);
    System.out.println("Original1: " + s);
    System.out.println("Weak1: " + weakRef.get());

    s = null;

    Thread.sleep(10000);

    Runtime.getRuntime().gc();

    int count = 0;
    while(weakRef.get() != null){
        System.out.println("Not null " + count);
        count++;
        Thread.sleep(1000);
    }
    System.out.println("Null");
}
publicstaticvoidmain(字符串[]args)引发异常{
String s=“你好,世界!”;
WeakReference weakRef=新的WeakReference;
System.out.println(“原始1:+s”);
System.out.println(“Weak1:+weakRef.get());
s=零;
睡眠(10000);
Runtime.getRuntime().gc();
整数计数=0;
while(weakRef.get()!=null){
System.out.println(“非空”+计数);
计数++;
睡眠(1000);
}
System.out.println(“空”);
}
编辑:更新了我的代码示例。我甚至尝试手动调用垃圾收集器,最终的println仍然输出“Weak2:helloworld!”


编辑2:再次更改它。将10秒的等待时间移到垃圾回收之前,然后包括循环。垃圾回收后,循环一直运行48秒(在我决定关闭它之前)。

在Java中,字符串文字,如您的
“Hello,World!”
是“interned”;也就是说,它们被放在缓存中以供重用。只要加载的类依赖于这些内部字符串之一,垃圾收集器就不会回收它,这就是阻止清除
WeakReference
的原因。请尝试以下方法:

WeakReference<String> weakRef = new WeakReference<>(new String(s));
WeakReference weakRef=新的WeakReference(新字符串);

当然,在源代码中没有从文本值分配的字符串(例如,从文件内容创建的
字符串
)将在适当的时间被垃圾收集。您刚刚选择了一个微妙而棘手的例子进行测试。

上面说我可以在三分钟内接受这个答案,但有一个像样的变化我会忘记。我只是想说这太棒了,非常感谢。“也就是说,它们被放在缓存中,而不是垃圾收集。”。这比那更复杂。字符串池缓存是垃圾收集的(它使用弱引用),但是有一个来自代码对象的强引用,该代码对象使用字符串对象的文本。强引用将文本保留在缓存中。。。除非类被卸载。@StephenC True,否则确切的细节会更复杂。但一个肤浅的解释就足以解决这个问题。