我有一个简单的代码段:
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()发生。 但是,即使设置了“整数= null”,“ wi”也拒绝为null。而sr在“ System.gc()”之后为null。它打印:
2
3
step 1 wi = 2
step 1 sr =: null
step 1 wi = 2
step 1 sr =: null
我的问题: (1)wi和sr之间的核心区别是什么? (2)如何使jvm回收无线?
非常感谢。
答案 0 :(得分:2)
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;
是语法糖。编译器最终最终编译的内容是以下代码,因为“自动装箱”是javac想象力的虚构(JVM对此一无所知,完全是javac为您完成的工作),是以下代码:
Integer x = Integer.valueOf(2);
当然,如果您调用new Integer
,您总会得到一个新对象,因为规范就是这样说的。您也可以对此进行测试:
System.out.println(new Integer(5) == new Integer(5));
以上打印false
。
实际上,java.lang.Integer
类本身拥有对您的wi
引用所指向的东西的引用,因此它永远不会被收集。
重试完全相同的代码,但是这次,而不是'= 2',请尝试'= 128',这一次它将与sr收集相同的代码。