当堆栈中仍然可见时,未使用的对象是否可用于垃圾收集?

Pet*_*iuk 18 java garbage-collection jvm

在以下示例中,有两个功能相同的方法:

public class Question {

    public static String method1() {
        String s = new String("s1");
        // some operations on s1
        s = new String("s2");
        return s;
    }

    public static String method2() {
        final String s1 = new String("s1");
        // some operations on s1
        final String s2 = new String("s2");
        return s2;
    }
}
Run Code Online (Sandbox Code Playgroud)

但是在first(method1)中,字符串"s1"显然可用于return语句之前的垃圾收集.在第二个(method2)字符串中,"s1"仍然可以访问(虽然从代码审查预期它不再使用).

我的问题是 - 在jvm规范中是否有任何内容表明,一旦变量在堆栈中未使用,它可用于垃圾收集?

编辑: 有时变量可以像完全渲染图像一样引用对象,并且会对内存产生影响.

我是因为实际考虑而问的.我在一个方法中有大量内存贪婪的代码,并且只是通过将此方法分成几个小方法来思考我是否可以帮助JVM(一点点).

我真的更喜欢没有重新分配的代码,因为它更容易阅读和推理.

更新:按 jls-12.6.1:

Java编译器或代码生成器可以选择设置将不再用于null的变量或参数,以使此类对象的存储可能更快地回收

所以看起来GC可以声明仍然可见的对象.我怀疑,然而这种优化是在离线编译期间完成的(它会搞砸调试),而且很可能是由JIT完成的.

tbo*_*odt 5

不,因为你的代码可以想象得到它并用它做一些事情,而抽象的 JVM 不会考虑什么代码即将到来。然而,一个非常、非常、非常聪明的优化 JVM 可能会分析前面的代码,发现没有任何方法s1可以被引用,并对其进行垃圾收集。不过,你绝对不能指望这一点。

  • 不正确。即使在解释器级别,数据流分析也已完成(作为方法验证的一部分),并且解释器完全有可能(尽管不太可能)将引用清零或以其他方式使对象可用于“早期”收集。在 JITC 级别,作为正常优化的副作用,这种操作实际上很有可能发生。对此没有架构限制。 (4认同)