0

我有一个简单的片段:

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”也拒绝为空。而 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?

非常感谢。

4

1 回答 1

2

它与无法保证的事实System.gc()(它没有,但这不是您看到您所看到的内容的原因)或弱引用如何与 gc 交互无关。

jlInteger 类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那样收集。

于 2019-01-26T16:34:54.653 回答