System.gc()之后未释放Java弱引用
我有一个简单的片段:System.gc()之后未释放Java弱引用,java,reference,garbage-collection,system,weak,Java,Reference,Garbage Collection,System,Weak,我有一个简单的片段: 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()
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());
我的问题是:
(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;
语法是糖。编译器最终编译的是以下代码,因为“自动装箱”是javac想象的虚构(JVM对此一无所知,完全是javac为您完成的):
Integer x = Integer.valueOf(2);
当然,如果你调用newinteger
,你总是会得到一个新的对象,因为,这就是规范所说的。您也可以对此进行测试:
System.out.println(new Integer(5) == new Integer(5));
上面打印的是false
实际上,java.lang.Integer
类本身持有对您的wi
引用指向的对象的引用,因此它永远不会被收集
重试完全相同的代码,但这一次,尝试“=2”,而不是“=128”,这一次它将收集与sr相同的代码。这与
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);
当然,如果你调用newinteger
,你总是会得到一个新的对象,因为,这就是规范所说的。您也可以对此进行测试:
System.out.println(new Integer(5) == new Integer(5));
上面打印的是false
实际上,java.lang.Integer
类本身持有对您的wi
引用指向的对象的引用,因此它永远不会被收集
重试完全相同的代码,但这次,请尝试“=2”,而不是“=128”,这次它将收集与sr相同的代码。@krzysztofcichochiki请解释可能随时更改。这个答案中解释的所有行为都在Javadoc和Java语言规范中有很好的文档记录。@krzysztofcichochi你错了。虽然我同意依赖整数缓存感觉很奇怪,但这个答案是准确的。关于WeakReference,只要引用的对象可以从整数缓存强访问,它就不会被清除。依赖内部缓存并不好,这只是实现细节,可以随时更改。System.gc()不能保证真正运行gc,它只是善意地要求jvm这样做。同样,这只是一个实现细节,您不能如此精确地依赖它,就像JComponent.repaint()和Thread.yeld()一样,尽管这些调用通常会产生一些效果,您不能真正保证他们会在特定的时间内运行底层任务。您应该连接到gc通知:以确保在您检查这些通知时确实执行了gcvalues@KrzysztofCichocki请解释一下,任何时候都可能发生变化。这个答案中解释的所有行为都在Javadoc和Java语言规范中有很好的文档记录。@krzysztofcichochi你错了。虽然我同意依赖整数缓存感觉很奇怪,但这个答案是准确的。关于WeakReference,只要引用的对象可以从整数缓存强访问,它就不会被清除。依赖内部缓存并不好,这只是实现细节,可以随时更改。System.gc()不能保证真正运行gc,它只是善意地要求jvm这样做。同样,这只是一个实现细节,您不能如此精确地依赖它,就像JComponent.repaint()和Thread.yeld()一样,尽管这些调用通常会产生一些效果,您无法真正保证它们会在特定的时间内真正运行基础任务。您应该连接到gc通知:为了确保在检查这些值时确实执行了gc,您应该连接到gc通知:为了确保在检查这些值时确实执行了gc检查这些值您应该连接到gc通知:为了确保在检查这些值时确实执行了gc