在Java中递归地清空成员对象?

在Java中递归地清空成员对象?,java,null,memory-leaks,member,recursive-datastructures,Java,Null,Memory Leaks,Member,Recursive Datastructures,当父对象进行垃圾收集时,作为另一个对象成员的对象是否有资格进行垃圾收集?例如,让我们想象一下这个场景: MyClass_1的代码: MyClass_2的代码: 好的,现在我们确定MyClass_3的代码不相关: // Instantiation of one root object MyClass_1 object_1 = new MyClass_1(); // Composition of two more objects object_1.setMyClass_2(new MyClas

当父对象进行垃圾收集时,作为另一个对象成员的对象是否有资格进行垃圾收集?例如,让我们想象一下这个场景:

MyClass_1的代码:

MyClass_2的代码:

好的,现在我们确定MyClass_3的代码不相关:

// Instantiation of one root object
MyClass_1 object_1 = new MyClass_1();

// Composition of two more objects
object_1.setMyClass_2(new MyClass_2());
object_1.getMyClass_2().setMyClass_3(new MyClass_3());

// And now...
object_1 = null;
当然,在这一点上,对象_1是可垃圾回收的,但是对象_2和对象_3呢?我应该这样做以避免内存泄漏吗

object_1.getMyClass_2().setMyClass_3(null);
object_1.setMyClass_2(null);
object_1 = null;

或者JVM会自动释放引用吗?如果需要手动完成,我可以依靠finalize完成吗?

这是隔离岛的一个经典示例

是的。。标记为null的所有对象以及相互引用的对象岛对象;但是他们中没有一个是可以到达的,因为他们需要收集垃圾

看到这个漂亮的帖子了吗

在这种情况下,不需要显式地将My_class2和My_class3设置为null。一旦父项为空,GC也将回收它们

Finalize不是执行垃圾收集的方法。基本上finalize使您有机会在垃圾收集该类的对象时执行某些操作。但是,甚至不要依赖finalize方法进行任何清理,因为对象可能永远不会被垃圾收集,因此finalize永远不会被调用


有关finalize的详细信息,请参见这是隔离岛的一个经典示例

是的。。标记为null的所有对象以及相互引用的对象岛对象;但是他们中没有一个是可以到达的,因为他们需要收集垃圾

看到这个漂亮的帖子了吗

在这种情况下,不需要显式地将My_class2和My_class3设置为null。一旦父项为空,GC也将回收它们

Finalize不是执行垃圾收集的方法。基本上finalize使您有机会在垃圾收集该类的对象时执行某些操作。但是,甚至不要依赖finalize方法进行任何清理,因为对象可能永远不会被垃圾收集,因此finalize永远不会被调用


有关finalize的更多信息,请参见

要了解对象何时将被垃圾收集,您需要了解一些对象是如何分配的

所有程序都有两部分内存;堆栈和堆。当程序执行时,它将输入新的函数或方法-这将创建一个新的作用域。每当创建一个新的作用域时,相应的新“框架”就会放置在堆栈的“顶部”。此框架引用了该范围内使用的所有变量

创建对象时,例如通过新关键字MyObject obj=new MyObject;,堆上留出一部分内存供该对象占用。然后,当前堆栈帧将引用对象在堆中的位置

显然,该对象可能引用了堆上的其他对象。程序知道如何访问这些对象的方法是从堆栈上的引用移动到堆上的第一个对象,然后移动到直接或间接连接的任何其他对象。所有这些对象都在堆上

当堆栈帧被卸载时(当程序离开该作用域时发生),该帧持有的任何引用都会被释放。这可能意味着堆上的一个或多个对象不再被堆栈上的任何对象直接或间接引用。这些是可用于垃圾收集的对象。如果您想知道对象是否将被垃圾收集,只需询问它当前是否连接到堆栈

请注意,这些对象可用于垃圾收集,而不是自动进行垃圾收集。任何标记的物体将在收藏者选择的时候被拆除。可能永远不会。finalize在任何被收集的对象上运行:这可以确保在收集对象时发生某些事情,但是由于您不能保证它永远都会发生,因此它的用处是有限的

现在,举个例子:

public void A() {//entering this method creates a new stack frame
  MyObject obj = new MyObject();//'obj' is a reference belonging to the current stack frame.
    //the obj reference is now pointing to a place in memory on the heap

  this.B();
}

public void B() { //Now we are in a new stack frame on top of the older one.
  obj.doSomething();//Doesn't work! There is no 'obj' reference in this stack frame
    //This results in a null pointer exception
  MyObject obj2 = new MyObject();//A totally new object is created on the heap!
} //When we leave this method we leave the scope, and the stack frame. 
 //obj2 is no longer referenced, and so is available for garbage collection

最后一项说明;假设您实例化了三个对象;A、 C.C被传递给A和B,并保存为这些对象的成员变量。现在让我们假设您离开定义B的范围。C不是垃圾收集的,因为A仍然有对它的引用;堆栈上仍然有一些地方保留着一些保留着C的东西。

要了解对象何时被垃圾收集,您需要了解一些对象是如何分配的

所有程序都有两部分内存;堆栈和堆。当程序执行时,它将输入新的函数或方法-这将创建一个新的作用域。每当创建一个新的作用域时,相应的新“框架”就会放置在堆栈的“顶部”。此框架引用了该范围内使用的所有变量

创建对象时,例如通过新关键字MyObject obj=new MyObject;,堆上留出一部分内存供该对象占用。当前堆栈帧 然后将引用对象在堆中的位置

显然,该对象可能引用了堆上的其他对象。程序知道如何访问这些对象的方法是从堆栈上的引用移动到堆上的第一个对象,然后移动到直接或间接连接的任何其他对象。所有这些对象都在堆上

当堆栈帧被卸载时(当程序离开该作用域时发生),该帧持有的任何引用都会被释放。这可能意味着堆上的一个或多个对象不再被堆栈上的任何对象直接或间接引用。这些是可用于垃圾收集的对象。如果您想知道对象是否将被垃圾收集,只需询问它当前是否连接到堆栈

请注意,这些对象可用于垃圾收集,而不是自动进行垃圾收集。任何标记的物体将在收藏者选择的时候被拆除。可能永远不会。finalize在任何被收集的对象上运行:这可以确保在收集对象时发生某些事情,但是由于您不能保证它永远都会发生,因此它的用处是有限的

现在,举个例子:

public void A() {//entering this method creates a new stack frame
  MyObject obj = new MyObject();//'obj' is a reference belonging to the current stack frame.
    //the obj reference is now pointing to a place in memory on the heap

  this.B();
}

public void B() { //Now we are in a new stack frame on top of the older one.
  obj.doSomething();//Doesn't work! There is no 'obj' reference in this stack frame
    //This results in a null pointer exception
  MyObject obj2 = new MyObject();//A totally new object is created on the heap!
} //When we leave this method we leave the scope, and the stack frame. 
 //obj2 is no longer referenced, and so is available for garbage collection
最后一项说明;假设您实例化了三个对象;A、 C.C被传递给A和B,并保存为这些对象的成员变量。现在让我们假设您离开定义B的范围。C不是垃圾收集的,因为A仍然有对它的引用;堆栈中仍然有一些地方保留着一些保留着C的内容。

任何事情都不要依赖finalize。在这种情况下,对象_2和对象_3引用的对象也将被收集,因为代码无法访问它们。任何事情都不要依赖finalize。在这种情况下,还将收集对象_2和对象_3引用的对象,因为代码无法访问它们。
public void A() {//entering this method creates a new stack frame
  MyObject obj = new MyObject();//'obj' is a reference belonging to the current stack frame.
    //the obj reference is now pointing to a place in memory on the heap

  this.B();
}

public void B() { //Now we are in a new stack frame on top of the older one.
  obj.doSomething();//Doesn't work! There is no 'obj' reference in this stack frame
    //This results in a null pointer exception
  MyObject obj2 = new MyObject();//A totally new object is created on the heap!
} //When we leave this method we leave the scope, and the stack frame. 
 //obj2 is no longer referenced, and so is available for garbage collection