【问题标题】:Object garbage collection after reference's scope expires引用范围过期后的对象垃圾回收
【发布时间】:2021-06-13 10:42:04
【问题描述】:

首先让我说我知道 System.gc() 更多的是收集垃圾而不是命令的建议,并且不能保证收集完成、启动或收集特定对象。然而……

使用下面的代码,只有当我在引用中明确放置 null 时才会收集 a1 实例。如果 a1 超出范围,则不会被收集。

class A {
    @Override
    protected void finalize() throws Throwable {
        System.out.println("Collecting A");
    }
}
public class Example {
    public static void main(String[] args) throws InterruptedException {
        try {
            A a1 = new A();
            //a1 = null; // a1 gets collected only if I uncomment this line
        }
        finally {
            System.out.println("Finally executed");
        }
        System.gc();
        Thread.sleep(1000);
    }
}

如果 a1 超出范围,并且没有强引用,为什么不收集它?是不是因为这个作用域不构成单独的栈帧?

【问题讨论】:

    标签: java garbage-collection


    【解决方案1】:

    完全由 JVM 来决定何时收集a1 或终结器是否运行。

    例如,JVM 可能决定在解释器中运行它,该解释器只有一个局部变量表,其中保存方法中的每个局部变量 - 类似于字节码中的工作方式 - 变量并没有真正去'在方法退出之前,从 GC 的角度来看超出范围。

    但是,例如,JIT 编译器可能会更积极地限制本地的 GC 范围(或者更确切地说,它根本不跟踪它不需要的内容)。因此,如果您使用 -Xcomp(在 HotSpot JVM 上)运行程序,强制此代码进行 JIT 编译,您可能(或可能不会)看到输出:

    Finally executed
    Collecting A
    

    没有将a1 明确设置为null

    另一方面,如果您使用 Epsilon GC(这是一个无操作 GC)使用 VM 选项运行此程序:-XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC(同样在 HotSpot 上),您可能不会在输出中看到 Collecting A完全没有,即使您将a1 明确设置为null

    所以,是的,这完全取决于虚拟机。

    【讨论】:

    • 原则上也可以看到输出Collecting A ␍ Finally executed
    猜你喜欢
    • 2017-06-20
    • 2016-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-11
    • 1970-01-01
    • 2011-01-18
    相关资源
    最近更新 更多