有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Java弱引用在系统运行后未被释放。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()”调用应该强制回收所有弱引用,对吧,我甚至等了一秒钟以确保gc()发生。 但即使设置了“integer=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循环wi

非常感谢


共 (1) 个答案

  1. # 1 楼答案

    它与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引用指向的对象的引用,因此,它永远不会被收集

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