用于Java中的WeakReference和StrongReference的GC

时间:2015-08-30 15:15:49

标签: java garbage-collection jvm

我在Java 7的java api文档中阅读了一些有关WeakReference的文献,并尝试使用以下内容对其进行测试

    package com.finalize;

import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;

public class WeakRefernceTest {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        String x = new String("x1");
        String y = new String("x2");

        Map<String, Object> mw = new WeakHashMap<>();
        mw.put(x, new Object());

        Map<String, Object> m = new HashMap<>();
        m.put(y, new Object());

        x = null;
        y = null;

        for(int i = 0; i < 5;++i)
        System.gc();

        System.out.println(mw.size());
        System.out.println(m.size());

    }

}

当我多次运行它时,我可以看到mw.size()被打印为0.但我有点困惑,因为m.size()永远不会打印为0.所以基本上,我试图理解在这个热点jvm中运行的默认GC。因此,当GC开始标记可到达的对象并且在x和y被设置为null之后运行时,为什么它将y引用的对象标记为可达对象,因为y已被设置为null?即使根变量设置为m,为什么GC到达y先前指向的对象并将其声明为可达?

相比之下,x的生命周期变化的详细顺序是什么?

2 个答案:

答案 0 :(得分:0)

单步执行代码

  • 您复制了字符串"x2"并将其分配给y
  • 您将字符串"x2"添加为m
  • 中的密钥
  • 当您使用GC时,m可以访问,就像它的所有密钥一样。
  • GC后
  • m及其所有密钥都会被保留。

答案 1 :(得分:0)

您正在主线程上执行main方法。主线程在其堆栈上具有变量m。此变量m是对HashMap实例的引用。此HashMap实例具有对映射条目数组的引用。此数组中包含的唯一映射条目具有对“x2”键和相应对象的引用。

因此,存在从根(主线程堆栈)到存储在地图中的对象的强引用链。这会阻止GC在地图中收集对象。

thread stack -> m -> HashMap -> entries -> entry -> "x2"
                                                 -> Object

另一个地图和另一个对象同样如此,除了它是一个WeakHashMap,所以由于地图键是一个弱引用,并且是唯一指向“x1”的引用,允许GC收集对“x1”的引用。 GC收集完毕后,地图会从其数组中删除相应的条目。