我有一个简单的片段:
Integer integer = 2;
WeakReference<Integer> wi = new WeakReference<>(integer);
WeakReference<Integer> sr = new WeakReference<>(new Integer(3));
System.out.println(wi.get());
System.out.println(sr.get());
System.gc();
System.out.println("step 1 wi = " + wi.get());
System.out.println("step 1 sr =: " + sr.get());
integer = null;
System.gc();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("step 1 wi = " + wi.get());
System.out.println("step 1 sr =: " + sr.get());
"System.gc()"调用应该强制回收所有弱引用,对吧,我甚至等了1秒才确保gc()发生。但是,即使设置了"integer=null","wi"也拒绝为null。而sr在"System.gc()"之后为空。它打印:
2
3
step 1 wi = 2
step 1 sr =: null
step 1 wi = 2
step 1 sr =: null
我的问题:(1) wi和sr的核心区别是什么?(2)如何让jvm回收wi?
非常感谢。
这与System.gc()
不能保证这一事实无关(它没有保证,但这不是您看到所看到的内容的原因),也与弱引用如何与gc交互无关。
j.l.Integer类为Integer
保存了一个实例的"缓存",用于所有字节值,从-128到+127。你可以观看这个动作:
System.out.println(Integer.valueOf(127) == Integer.valueOf(127));
System.out.println(Integer.valueOf(128) == Integer.valueOf(128));
上面打印的是true false
。
此代码:
Integer x = 2;
是语法糖。编译器最终实际编译的是以下代码:
Integer x = Integer.valueOf(2);
当然,如果你调用new Integer
,你总是会得到一个新对象,因为规范就是这么说的。你也可以测试一下:
System.out.println(new Integer(5) == new Integer(5));
上述打印CCD_ 5。
实际上,java.lang.Integer
类本身拥有对wi
引用所指向的对象的引用,因此,它永远不会被收集。
重试完全相同的代码,但这次不是'=2',而是尝试'=128',这次它将收集与sr相同的代码。