Java System.gc() 后未释放弱引用

Java weak reference is not freed after System.gc()

我有一个简单的片段:

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()" 之后为 null。它打印:

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 class 为 Integer 保存 'cache' 个实例,对于所有字节值,从 -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;

是语法糖。编译器实际上最终编译的是什么,因为 'autoboxing' 是 javac 想象的虚构(JVM 对此一无所知,它完全是 javac 为你做的),是这段代码:

Integer x = Integer.valueOf(2);

然而,当然,如果您调用 new Integer,您总是会得到一个新对象,因为,这就是规范所说的。你也可以测试这个:

System.out.println(new Integer(5) == new Integer(5));

以上打印 false.

实际上,java.lang.Integer class 本身持有对您的 wi 引用指向的事物的引用,因此,它永远不会被收集。

重试完全相同的代码,但这次尝试使用“= 128”而不是“= 2”,这次它将收集与 sr 相同的代码。