我试图了解GC的行为,但发现了一些我无法理解的有趣的东西。

请查看代码和输出:

public class GCTest {
    private static int i=0;

    @Override
    protected void finalize() throws Throwable {
        i++; //counting garbage collected objects
    }

    public static void main(String[] args) {
        GCTest holdLastObject; //If I assign null here then no of eligible objects are 9 otherwise 10.

        for (int i = 0; i < 10; i++) {
             holdLastObject=new GCTest();
        }

        System.gc(); //requesting GC

        //sleeping for a while to run after GC.
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // final output
        System.out.println("`Total no of object garbage collected=`"+i);
    }
}

在上面的示例中,如果我将holdLastObject分配为null,则得到Total no of object garbage collected=9。如果没有,我得到10

有人可以解释吗?我找不到正确的原因。

最佳答案

我怀疑这是由于任务明确。

如果在循环之前为holdLastObject分配了一个值,则肯定是为整个方法分配的(从声明开始)-因此,即使您在循环后没有访问它,GC也会知道您可以编写代码访问它,因此它不会最后确定实例。

由于您没有在循环之前为变量分配值,因此除了循环​​内之外,其他变量均未分配值-因此我怀疑GC会将其视为在循环中声明的值-它知道循环后没有代码可以读取从变量中获取(因为未明确分配),因此它知道可以完成并收集最后一个实例。

如果您添加以下内容,只是为了澄清我的意思:

System.out.println(holdLastObject);

就在System.gc()行之前,您会发现它在第一种情况下(没有分配)不会编译。

我怀疑这是VM的详细信息-我希望,如果GC可以证明实际上没有从本地变量中读取任何代码,则无论如何收集最终实例都是合法的(即使不是) t目前已采用这种方式)。

编辑:与TheLostMind的答案相反,我相信编译器会将这些信息提供给JVM。使用javap -verbose GCTest我发现这没有分配:
  StackMapTable: number_of_entries = 4
    frame_type = 253 /* append */
      offset_delta = 2
      locals = [ top, int ]
    frame_type = 249 /* chop */
      offset_delta = 19
    frame_type = 75 /* same_locals_1_stack_item */
      stack = [ class java/lang/InterruptedException ]
    frame_type = 4 /* same */

并附有以下内容:
  StackMapTable: number_of_entries = 4
    frame_type = 253 /* append */
      offset_delta = 4
      locals = [ class GCTest, int ]
    frame_type = 250 /* chop */
      offset_delta = 19
    frame_type = 75 /* same_locals_1_stack_item */
      stack = [ class java/lang/InterruptedException ]
    frame_type = 4 /* same */

注意第一个条目的locals部分的区别。奇怪的是,如果没有初始分配,class GCTest条目不会出现在任何地方...

07-24 19:08
查看更多