2016-03-14 93 views
1

我是WeakReferences的新手,所以我只是试图理解这一点。我把这段简短的代码放在一起来测试他们的行为。我计划在我正在开发的一个项目中使用它们,因为我需要临时跟踪对象的引用。也就是说,只要他们没有在其他地方使用过,我想在集合中引用它们。Java:WeakReference.get()不返回null

尽管如此,这个简短的测试代码示例并没有像我想要的那样工作。无论等待多久,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"); 
} 

编辑:更新我的代码示例。我甚至尝试手动调用垃圾回收器,最后的println仍然输出“Weak2:Hello World!”。

编辑2:再次更改它。将10秒钟的等待移至垃圾收集之前,然后包含循环。垃圾回收后,循环持续运行48秒(在我决定关闭它之前)。

回答

3

在Java中,字符串文字,如"Hello, World!"是“interned”;也就是说,它们被放入缓存以供重用。只要一个被加载的类依赖于这些实际的字符串中的一个,它就不会被垃圾回收器回收,这就是阻止你的WeakReference被清除的原因。试试这个:

WeakReference<String> weakRef = new WeakReference<>(new String(s)); 

当然,不是从字面值在源代码—例如分配一个字符串,从文件内容—创建将在适当的时候收集垃圾一个String。你只是挑了一个微妙的棘手的例子来测试。

+0

它说我可以在三分钟内接受这个答案,但有一个体面的变化,我会忘记。只是想说这很好,非常感谢。 – user2223059

+0

*“也就是说,它们放在缓存中,而不是垃圾收集”*。比这更复杂。字符串池缓存是垃圾收集的(它使用弱引用),但是有一个强大的引用来自将字面值用于String对象的代码对象。强引用保留了缓存中的字面值......除非类被卸载。 –

+0

@StephenC确实,确切的细节更复杂。但表面的解释足以解决这个问题。 – erickson