我在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的生命周期变化的详细顺序是什么?
答案 0 :(得分:0)
单步执行代码
"x2"
并将其分配给y
"x2"
添加为m
m
可以访问,就像它的所有密钥一样。m
及其所有密钥都会被保留。答案 1 :(得分:0)
您正在主线程上执行main方法。主线程在其堆栈上具有变量m
。此变量m
是对HashMap实例的引用。此HashMap实例具有对映射条目数组的引用。此数组中包含的唯一映射条目具有对“x2”键和相应对象的引用。
因此,存在从根(主线程堆栈)到存储在地图中的对象的强引用链。这会阻止GC在地图中收集对象。
thread stack -> m -> HashMap -> entries -> entry -> "x2"
-> Object
另一个地图和另一个对象同样如此,除了它是一个WeakHashMap,所以由于地图键是一个弱引用,并且是唯一指向“x1”的引用,允许GC收集对“x1”的引用。 GC收集完毕后,地图会从其数组中删除相应的条目。