弱引用对这个程序的工作有什么影响?

3
为什么下面的程序调用了System.exit(0)?只有当map引用变量变为null时才应该调用它。
import java.lang.ref.WeakReference; 
import java.util.HashMap; 
import java.util.Map; 
public class ReferencesTest { 
    private WeakReference<Map<Integer, String>> myMap; 
    public static void main(String[] args) { 
        new ReferencesTest().doFunction(); 
    } 

    private void doFunction() { 
        Map<Integer, String> map = new HashMap<Integer, String>(); 
        myMap = new WeakReference<Map<Integer, String>>(map); 
        int i = 0; 
        while (true) { 
            if (myMap != null && myMap.get() != null) { 
                myMap.get().put(i++, "test" + i);
                System.out.println("im still working!!!!"+i+" Map Size"+myMap.get().size()); 
                System.gc();
            } else { 
                System.out 
                .println("*******im free*******"); 
                System.exit(0);
            } 
        } 
    } 
}

输出的最后几行如下:
im still working!!!!15586 Map Size15586
im still working!!!!15587 Map Size15587
im still working!!!!15588 Map Size15588
*******im free*******
2个回答

5
变量mapwhile循环中(或之后的代码)都未被使用。仅仅因为该变量在源代码中仍然在作用域范围内,或者它在方法的字节码中确实有一个指定的本地变量入口,并不意味着变量map在运行时实际上处于作用域范围内,特别是在JIT编译之后。

除非您使用选项明确保留未使用的局部变量(在其整个作用域范围内),否则这是预期的行为。

证明(--XX:+PrintCompilation):

im still working!!!!15586 Map Size15586
im still working!!!!15587 Map Size15587
im still working!!!!15588 Map Size15588
 259509   23 %           eu.revengineer.sync.ReferencesTest::doFunction @ -2 (144 bytes)   made not entrant
*******im free*******

你没有使用变量 mapmyMap 是一个弱引用;是的,myMap.get() 返回的确实是变量 map 初始化时所使用的相同对象,但它与变量 map 没有任何关系。 - Tadas S
@afk5min 好的,假设“map在while循环中没有使用”,那为什么我没有将其置为空,它就被垃圾回收了呢? - Vipin
问题与Hotspot即时编译器有关。请查看答案。 - Tadas S
@afk5min,如果是因为即时编译器,那不是很糟糕吗?如果我们以这种方式使用WeakHashMap,它永远不会起作用。如果我想要将此映射用于缓存目的,我可能会失去整个映射。 - Vipin
我现在懂了,如果我想要使用map进行缓存,就不应该使用它作为局部变量,因为由于JIT编译器的缘故,它会变得适合垃圾回收。如果我将map用作实例变量,它会正常工作。感谢@afk5min的完美解释。我之前并不知道JIT可以做到这些 :) - Vipin
显示剩余3条评论

0

我想你实际上想要使用的是WeakHashMap(http://docs.oracle.com/javase/6/docs/api/java/util/WeakHashMap.html)。

对于HashMap的弱引用会在内存压力下被删除,导致整个映射不可达,甚至在你的情况下终止程序。而WeakHashMap则使用对其键的弱引用,因此只有映射会在内存压力下丢失(键,值)对。


其实我在想为什么我的代码不起作用,可能是我漏掉了什么,所以需要在这个特定的例子中寻求帮助。 - Vipin
你的代码试图实现什么目标?当请求更多内存时,它是否能够生存下来?那么问题是,如果资源变得稀缺,你将要抛弃什么。如果是映射表的条目,我建议阅读一下WeakHashMap或使用真正的缓存解决方案。 - andi5

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接