【问题标题】:How WeakReference is affecting working of this programWeakReference 如何影响这个程序的工作
【发布时间】:2013-12-14 14:03:11
【问题描述】:

为什么在下面的程序中调用 System.exit(0) 下面?只有当映射引用变量为空时才应该调用它。

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*******

【问题讨论】:

    标签: java map reference weak-references


    【解决方案1】:

    map 变量在while 循环内的任何地方(或进一步向下)都未使用(未引用)。只是因为变量仍在范围内,如源代码所示;或者它在方法的字节码中确实有一个指定的局部变量条目这一事实并不意味着变量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*******
    

    【讨论】:

    • 但它被仍在使用的myMap弱引用。
    • 弱引用完全被 GC 忽略。毕竟,这就是“弱”的意思。
    • 您没有使用(变量)mapmyMap 是弱引用;是的,myMap.get() 确实返回了与变量 map 初始化相同的对象,但它与(变量)map 无关。
    • @afk5min 好的,可以说“在 while 循环内的任何地方都没有使用地图”然后我仍然没有将其设为 null,为什么它会被垃圾收集?
    • 首先,如果您将代码更改为System.out.println("*******im free*******" + map);。您会注意到您的循环不再停止。可能有两种可能:JIT(-XX:+PrintCompilation)或GC(达到堆限制,用低堆测试,例如-Xmx4M
    【解决方案2】:

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

    对 HashMap 的弱引用将在内存压力下被删除,从而使您的整个地图无法访问,甚至在您的情况下终止程序。 WeakHashMap 使用对其键的弱引用,因此只有映射会在内存压力下丢失(键,值)对。

    【讨论】:

    • 实际上我想知道为什么我的代码不起作用,我在这里缺少一些东西,所以在这个特定的例子中需要帮助。
    • 你的代码试图实现什么?当请求越来越多的内存时它会生存吗?那么问题是,如果资源变得稀缺,你将丢弃什么。如果是地图条目,我会考虑阅读 WeakHashMap 或真正的缓存解决方案。
    猜你喜欢
    • 2012-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多