Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.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
如果没有引用变量,java GC如何工作?_Java_Garbage Collection - Fatal编程技术网

如果没有引用变量,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创建对象并在其上调

我知道,如果指向对象的引用变量手动设置为null或设置为指向另一个对象,java GC可以销毁堆上的对象:

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()
本身,因此对象永远不会有一个引用变量指向它,并且它仍然会被收集。)