0

我有以下代码:

public class MyOjbect {
public Integer z = 111;
@Override
protected void finalize() throws Throwable {
    System.out.println("invoking GC in MyOjbect");
    super.finalize();
         }
     }
      public class GC {
private MyOjbect o; 
private void doSomethingElse(MyOjbect obj) {
    o = obj;
}
@SuppressWarnings("unused")
public void doSomething() throws InterruptedException {
    System.out.println("Start");
    MyOjbect o = new MyOjbect();        
     doSomethingElse(o);        
     o = new MyOjbect();
     doSomethingElse(null);
     System.gc();
    // System.out.println("checking "+o.z);
}
public static void main(String[] args) throws InterruptedException {
    GC gc = new GC();
    gc.doSomething();
       }
}

我想知道为什么在执行该方法后变量GC垃圾。甚至变量还不是空的。事实上,当我调试代码后 不是空的而是垃圾它。此外,如果我取消注释最后一行,GC 会打印变量,然后调用 GC。odoSomethingElseoodoSomethingElseGCo.z

更新:对于问为什么局部变量与字段相同的人。我刚刚从 SCJP 测试考试中复制了一个问题,因为它是

4

1 回答 1

1

很多话题在这里讨论!

首先,正如 Gyro 所说,GC 不收集变量。它收集死对象的实例。死对象是没有指向它的强引用(变量)的对象。请注意,还有更微妙的情况(弱引用、软引用、幻像引用,...),但让我们关注最常见的情况 :-) 您可以在此处找到更多信息:https://weblogs.java。 net/blog/2006/05/04/understanding-weak-references

如果取消注释最后一行,则会打印“111”,因为 o 是引用您创建的 MyObject 实例的局部变量o = new MyOjbect();

现在,最棘手的事情是:您有两个不同的 MyObject 实例。但是,您的程序只打印一次“在 MyObject 中调用 GC”。如果您像这样转换“MyObject”类,就会变得很明显:

public class MyOjbect {
    public Integer z = 111;

    public MyOjbect() {
        System.out.println("Creating MyObject " + hashCode());
    }

    @Override
    protected void finalize() throws Throwable {
        System.out.println("invoking GC in MyOjbect " + hashCode());
        super.finalize();
    }
}

您的程序现在打印了两个 MyObjects 创建,但只有一个由 GC 恢复。这是因为绝对不能保证 finalize() 方法会被调用。根据 JLS 和 finalize() 的javadoc

Java 编程语言不保证哪个线程将为任何给定对象调用 finalize 方法

在您的情况下,应用程序的结束使每个对象都死了。无需运行 GC,因为一旦 JVM 退出,堆将完全恢复。

于 2013-05-01T09:38:02.657 回答