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

问题描述 投票:1回答:2

[我担心的是曾经被强引用的对象的实例,但是在对其强引用进行显式的空赋值之后,以及在显式的System.gc()调用之后,仍可以通过弱引用访问该实例。如果我理解正确,当所引用的对象仅剩下弱引用时,可以确保在下一个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);
    }
}

java reference weak-references
2个回答
1
投票

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

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

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

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

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

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

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


0
投票

[SoftReference不会使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

Java 13上测试

© www.soinside.com 2019 - 2024. All rights reserved.