如果没有引用变量,java GC如何工作?
我知道,如果指向对象的引用变量手动设置为null或设置为指向另一个对象,java GC可以销毁堆上的对象:如果没有引用变量,java GC如何工作?,java,garbage-collection,Java,Garbage Collection,我知道,如果指向对象的引用变量手动设置为null或设置为指向另一个对象,java GC可以销毁堆上的对象: TestObject test = new TestObject(); test.dosomething(); test = null; 我的问题是,如果我在创建该对象时没有给它命名(引用变量),那么在我处理完该对象后,如何释放该对象占用的内存: (new TestObject()).dosomething(); 在程序结束之前,此对象是否会永远存在于堆中?使用new创建对象并在其上调
TestObject test = new TestObject();
test.dosomething();
test = null;
我的问题是,如果我在创建该对象时没有给它命名(引用变量),那么在我处理完该对象后,如何释放该对象占用的内存:
(new TestObject()).dosomething();
在程序结束之前,此对象是否会永远存在于堆中?使用
new
创建对象并在其上调用方法dosomething()
后,没有对它的引用,因此它可以进行垃圾收集
即使您创建了两个对象,它们通过引用彼此指向对方,并且它们不再具有到根引用的连接,它们也将符合gc的条件(jvm可以在没有根连接的情况下检测此循环引用)
因此,为了回答您的问题:No在您调用dosomething
后,将对第二个示例中的对象进行gc-ed
请注意:在实践中,您不需要
null
您的引用(实际上我几乎从未这样做过),只要将它们保留在局部范围内就足够了,这样当您离开它时,局部变量就会被清除。我将通过字节码来解释这一点。首先要注意的是,虽然存在对对象的可访问引用,但无法收集该对象。其中一个重要方面是,如果引用值位于方法堆栈帧中的堆栈上,则可以访问被引用的对象。因此,它不能被垃圾收集
编译以下程序
public class Example {
public static void main(String[]args) {
new Example().sayHello();
}
public void sayHello() {}
}
运行javap-c示例
会得到如下结果
public static void main(java.lang.String[]);
Code:
stack=2, locals=1, args_size=1
0: new #2 // class Example
3: dup
4: invokespecial #3 // Method "<init>":()V
7: invokevirtual #4 // Method sayHello:()V
10: return
publicstaticvoidmain(java.lang.String[]);
代码:
堆栈=2,局部变量=1,参数大小=1
0:new#2//类示例
3:dup
4:invokespecial#3//方法“”:()V
7:invokevirtual#4//方法sayHello:()V
10:返回
索引0
,即new
字节码指令,创建一个新对象,并将对该对象的引用推送到堆栈上。dup
指令复制该值并将其推到堆栈顶部。现在有两个对该对象的引用invokespecial
使用其中一个,invokevirtual
使用另一个(它们弹出它们使用的参考值)。一旦完成,就不再有对对象的引用,并且可以对其进行垃圾收集
作为参考,.谢谢,当你提到循环参考时,你是指类似强参考循环的东西吗?java中有弱引用还是强引用?java中有弱引用(加上soft和phantom),但我刚才说的是两个对象相互引用,但没有被任何其他对象引用。GC删除没有引用的对象。在
(newtestobject()).dosomething()中代码>Java堆栈中有一个对TestObject非常简短的引用,然后它就消失了,要么是因为堆栈条目被重用,要么是因为方法返回。一旦它消失了,对象就可以被收集。(用你的术语来说,当对象被创建时,它的引用变量并没有给它一个“名称”。相反,它的“名称”(堆地址)是在“出生”时分配的,并且“名称”被复制到引用它的任何引用变量中。你可以做newtestobject()
本身,因此对象永远不会有一个引用变量指向它,并且它仍然会被收集。)