弱引用的对象将不会收集垃圾

我关心的是曾经被强引用的对象的实例,但是在对其强引用进行显式的空赋值以及显式的System.gc()调用之后,该实例仍然可以通过 weak到达参考。如果我理解正确,当所引用的对象仅剩下弱引用时,可以确保在下一个 GC 会话中清除该引用。我想念什么?

参考代码:

public class References {
    public static void main(String[] args) {

        Example strongReferenceWrappedInWeak = new Example(42);
        strongReferenceWrappedInWeak.printA();

        WeakReference<Example> exampleWeakReference = new WeakReference<>(strongReferenceWrappedInWeak);

        System.gc();

        Example retrievedExample = exampleWeakReference.get();
        retrievedExample.printA(); //this works,because a strong reference is present to the instance,hence it's not cleared

        strongReferenceWrappedInWeak = null; //eligible for garbage collection

        System.gc();

        Example retrievedExampleTwo = exampleWeakReference.get(); //should be null
        retrievedExampleTwo.printA(); //should throw NPE
    }
}

class Example {
    private int a;

    Example(int a) {
        this.a = a;
    }

    void printA() {
        System.out.println(this.a);
    }
}

lclei_2 回答:弱引用的对象将不会收集垃圾

垃圾收集的工作方式很神秘。

Java生态系统中有几种垃圾回收器实现,它们的行为非常不同。

运行垃圾收集的时间因垃圾收集器的实现而异,并且还可能取决于JVM的当前条件。一个收集器可能几乎连续运行,而另一个收集器可能要等到内存不足时才运行。 (在这里,我要简化太多,以使观点更清楚。)

是收集所有垃圾还是仅收集其中的一部分,也可能因收集器实现和JVM状态而异。

调用 System.gc只是一个建议,而不是命令。垃圾收集器可以随意忽略它。

在Java中,您不应该在管理内存上花大力气。现代的JVM实现远胜于任何单个程序员。只要确保在使用完对象后释放它们的所有引用即可。或使用WeakReference / SoftReference。然后信任JVM和垃圾收集器来完成其工作。

在极端情况下(非常大的内存或大量的对象搅动),您可能需要研究各种垃圾收集器实现的行为。也许可以考虑使用替代方案,例如Azul Systems的 Zing 或Oracle的 GraalVM 。但是对于大多数项目,通常基于OpenJDK的JVM都可以很好地工作。

,

strongReferenceWrappedInWeak = null不能使Example对象实例有资格进行垃圾回收,因为 retrievedExample仍然对其有很强的引用

要修复,请添加retrievedExample = null;

Example strongReferenceWrappedInWeak = new Example(42);
strongReferenceWrappedInWeak.printA();

WeakReference<Example> exampleWeakReference = new WeakReference<>(strongReferenceWrappedInWeak);

System.gc();

Example retrievedExample = exampleWeakReference.get();
retrievedExample.printA(); //this works,because a strong reference is present to the instance,hence it's not cleared

retrievedExample = null;
strongReferenceWrappedInWeak = null; //now eligible for garbage collection

System.gc();

Example retrievedExampleTwo = exampleWeakReference.get(); //will be null
retrievedExampleTwo.printA(); //will throw NPE

或者,不要使用局部变量创建强引用,只需直接从弱引用中调用该方法即可。这样一来,您就不会像您那样意外地留下大量参考。 *(在printA()调用期间,this引用是一个强引用,因此在调用期间 不能对对象进行GC处理)*

Example strongReferenceWrappedInWeak = new Example(42);
strongReferenceWrappedInWeak.printA();

WeakReference<Example> exampleWeakReference = new WeakReference<>(strongReferenceWrappedInWeak);

System.gc(); //does not collect object,since strong reference still exists

exampleWeakReference.get().printA(); //works

strongReferenceWrappedInWeak = null; //eligible for garbage collection
System.gc(); //collects object,since it is now weakly referenced only

exampleWeakReference.get().printA(); //throws NPE

输出(两者)

42
42
Exception in thread "main" java.lang.NullPointerException
    at Test.main(Test.java:**)

在Java 13上测试

本文链接:https://www.f2er.com/2744061.html

大家都在问