简体   繁体   English

System.gc()之后无法释放Java弱引用

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

I've got a simple snippet: 我有一个简单的代码段:

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());

The "System.gc()" call should force all weak reference to be recycled, right, and I even waited 1 second to make sure gc() happens. “ System.gc()”调用应强制所有弱引用被回收,对,我什至等了1秒钟以确保gc()发生。 But even when "integer = null" is set, "wi" refuse to be null. 但是,即使设置了“整数= null”,“ wi”也拒绝为null。 While sr is null right after "System.gc()". 而sr在“ System.gc()”之后为null。 It prints: 它打印:

2
3
step 1 wi = 2
step 1 sr =: null
step 1 wi = 2
step 1 sr =: null

My questions: (1) What is the core difference between wi and sr? 我的问题:(1)wi和sr之间的核心区别是什么? (2 )how to make jvm recycle wi? (2)如何使JVM回收无线?

Thanks a lot. 非常感谢。

It has nothing whatsoever to do with either the fact that System.gc() makes no guarantees (it doesn't, but that's not why you're seeing what you're seeing), or how weak references interact with gc. 它与System.gc()不作任何保证(不作保证,但这不是为什么您看到所看到的内容)或弱引用如何与gc交互无关。

The jlInteger class holds a 'cache' of instances for Integer , for all byte values, so, from -128 to +127. jlInteger类为所有字节值(即从-128到+127)保存Integer实例的“缓存”。 You can watch this in action: 您可以观看此动作:

System.out.println(Integer.valueOf(127) == Integer.valueOf(127));
System.out.println(Integer.valueOf(128) == Integer.valueOf(128));

The above prints true false . 上面打印的是true false

This code: 这段代码:

Integer x = 2;

is syntax sugar. 是语法糖。 What the compiler actually ends up compiling, because 'autoboxing' is a figment of javac's imagination (the JVM knows nothing about it, it's entirely javac doing that for you), is this code: 编译器实际上最终进行编译的原因是:“自动装箱”是javac想象力的虚构(JVM对此一无所知,这完全是javac为您完成的),是以下代码:

Integer x = Integer.valueOf(2);

whereas, of course, if you call new Integer , you ALWAYS get a new object, because, well, that's what the spec says. 但是,当然,如果您调用new Integer ,那么您总会得到一个新对象,因为规范就是这么说的。 You can test this too: 您也可以对此进行测试:

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

the above prints false . 以上打印false

Effectively, the java.lang.Integer class itself holds a reference to the thing your wi reference points to, hence, it never gets collected. 实际上, java.lang.Integer类本身拥有对您的wi参考所指向的东西的引用,因此,它永远不会被收集。

Retry the exact same code, but this time, instead of ' = 2', try ' = 128', and this time it'll collect same as sr will. 重试完全相同的代码,但是这次,而不是'= 2',尝试'= 128',这一次它将收集与sr相同的代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM