Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/324.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JAVAGC的奇怪行为_Java_Garbage Collection - Fatal编程技术网

JAVAGC的奇怪行为

JAVAGC的奇怪行为,java,garbage-collection,Java,Garbage Collection,我有以下代码: 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; pri

我有以下代码:

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();
       }
}
我想知道为什么执行
doSomethingElse
方法后,
GC
会对
o
变量进行垃圾处理。甚至
o
变量也不是空的。事实上,当我调试
o
之后的
doSomethingElse
代码时,它不是空的,而是
GC
垃圾。此外,如果我取消注释最后一行,GC将打印
o.z
变量,然后调用GC


更新:对于询问为什么局部变量与字段相同的人。我刚刚从SCJP测试中复制了一个问题,因为这里有很多主题要讨论

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

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

现在,最棘手的事情是:有两个不同的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();
    }
}
您的程序现在打印两个MyObject,但只有一个由GC恢复。这是因为绝对不能保证finalize()方法会被调用。根据JLS和finalize()的说明:

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


在您的例子中,应用程序的结尾会使每个对象都死掉。无需运行GC,因为一旦JVM退出,堆将完全恢复。

您能清理并格式化代码吗?然后不含糊地重写它?你使用
o
两次,一次作为字段名,一次作为变量名,但它们彼此没有影响,这让人感到困惑。我怀疑,即使你不知道你在问题的每一点上引用的是哪个
o
。顺便说一句,在底层对象被垃圾收集之前,引用不必是
null
。如果对象不能从任何垃圾收集根(相当于一个线程)强访问,那么即使它有传入的引用,它也有资格被收集。我刚刚从考试310-065测试中复制/粘贴了一个对象。最初的问题是:这意味着什么?GC垃圾收集仍然有引用的变量???你不需要g/c变量,你是g/c对象实例!你创建了两个对象,但只有一个得到gced。。。猜猜哪一个超出了范围!(当您添加一个默认构造函数:public MyOjbect(){System.out.println(“New MyObject:+this”);}和this to finalize():System.out.println(“调用MyOjbect中的GC:+this”)时,这一点就变得很清楚了。);这有点令人困惑。为什么GC会丢弃仍然引用的对象。换句话说,GC会释放o变量占用的内存大小写,这就是为什么我们会看到“在MyOjbect中调用GC”,但在这之后,我可以打印我的o变量的z整数。有人能向我澄清一下吗?没有,你有两个“MyObject”实例。第一个被收集,但第二个没有,因此
z
整数仍然可用。