为什么Java垃圾收集批量执行?

时间:2022-05-21 03:49:37

I understand that Garbage Collection in Java runs automatically by freeing up spaces used up by objects that are not reachable any more.

我知道Java中的垃圾收集是通过释放由不再可达的对象使用的空间自动运行的。

But why does it do that in a batch mode? References to heap objects are already stored in a stack so why not free those objects as and when the frame containing those references is popped out from the stack?

但为什么它会以批处理模式执行此操作?对堆对象的引用已存储在堆栈中,那么为什么不从堆栈中弹出包含这些引用的帧时释放这些对象?

1 个解决方案

#1


1  

Well, generally speaking the fact that one of the references to the object (which was used in a method) is destroyed is not sufficient to state that the object is not reachable any more via any other path (for example method could share the reference by assigning it to a field of any object hence making the created object referenced from the heap as well). Just consider the following example :

好吧,一般来说,对象的一个​​引用(在方法中使用)被破坏的事实不足以说明对象不再可以通过任何其他路径到达(例如方法可以通过以下方式共享引用)将它分配给任何对象的字段,从而使得从堆引用的创建对象也是如此)。请考虑以下示例:


    public class GarbageCollectionReferenceShareDemo {

        private Object objectReference;

        public void runDemo() {
            final Object methodReference = new Object();
            objectReference = methodReference;
        }
    }

In the example above the reference to the object being created is also published into a field of a class. After the execution of the runDemo method is complete the methodReference reference variable will be destroyed (when popping the stack frame). However, it is essential to realize that only the reference will be destroyed and not the created object (which is stored in the heap). The JVM runtime can not clean up the created object since it has to analyze whether it is reachable or not and judging from the example above doing it requires scanning references out of the method as well.

在上面的示例中,对正在创建的对象的引用也发布到类的字段中。完成runDemo方法的执行后,将销毁methodReference引用变量(弹出堆栈帧时)。但是,必须认识到只会销毁引用而不会销毁创建的对象(存储在堆中)。 JVM运行时无法清理已创建的对象,因为它必须分析它是否可访问,并且从上面的示例判断它需要扫描引用方法。

So long story short : in order to determine whether the object is reachable or not garbage collector has to scan all paths starting from the GC roots, which mainly include all thread's stacks and global variables , eg static fields. Only this approach allows to cope with the cases when a reference is shared out of the method via an assignment.

长话短说:为了确定对象是否可达,垃圾收集器必须扫描从GC根开始的所有路径,主要包括所有线程的堆栈和全局变量,例如静态字段。只有这种方法允许处理通过赋值从方法*享引用的情况。

However, the garbage collection topic is quite an extensive one, hence if you are interested in the details of Garbage Collection then I would strongly recommend following book which will spread a light on quite a lot of GC details :

但是,垃圾收集主题是一个非常广泛的主题,因此如果您对垃圾收集的细节感兴趣,那么我强烈推荐以下书籍,它将在很多GC细节上传播:

The Garbage Collection Handbook: The Art of Automatic Memory Management

垃圾收集手册:自动内存管理的艺术

#1


1  

Well, generally speaking the fact that one of the references to the object (which was used in a method) is destroyed is not sufficient to state that the object is not reachable any more via any other path (for example method could share the reference by assigning it to a field of any object hence making the created object referenced from the heap as well). Just consider the following example :

好吧,一般来说,对象的一个​​引用(在方法中使用)被破坏的事实不足以说明对象不再可以通过任何其他路径到达(例如方法可以通过以下方式共享引用)将它分配给任何对象的字段,从而使得从堆引用的创建对象也是如此)。请考虑以下示例:


    public class GarbageCollectionReferenceShareDemo {

        private Object objectReference;

        public void runDemo() {
            final Object methodReference = new Object();
            objectReference = methodReference;
        }
    }

In the example above the reference to the object being created is also published into a field of a class. After the execution of the runDemo method is complete the methodReference reference variable will be destroyed (when popping the stack frame). However, it is essential to realize that only the reference will be destroyed and not the created object (which is stored in the heap). The JVM runtime can not clean up the created object since it has to analyze whether it is reachable or not and judging from the example above doing it requires scanning references out of the method as well.

在上面的示例中,对正在创建的对象的引用也发布到类的字段中。完成runDemo方法的执行后,将销毁methodReference引用变量(弹出堆栈帧时)。但是,必须认识到只会销毁引用而不会销毁创建的对象(存储在堆中)。 JVM运行时无法清理已创建的对象,因为它必须分析它是否可访问,并且从上面的示例判断它需要扫描引用方法。

So long story short : in order to determine whether the object is reachable or not garbage collector has to scan all paths starting from the GC roots, which mainly include all thread's stacks and global variables , eg static fields. Only this approach allows to cope with the cases when a reference is shared out of the method via an assignment.

长话短说:为了确定对象是否可达,垃圾收集器必须扫描从GC根开始的所有路径,主要包括所有线程的堆栈和全局变量,例如静态字段。只有这种方法允许处理通过赋值从方法*享引用的情况。

However, the garbage collection topic is quite an extensive one, hence if you are interested in the details of Garbage Collection then I would strongly recommend following book which will spread a light on quite a lot of GC details :

但是,垃圾收集主题是一个非常广泛的主题,因此如果您对垃圾收集的细节感兴趣,那么我强烈推荐以下书籍,它将在很多GC细节上传播:

The Garbage Collection Handbook: The Art of Automatic Memory Management

垃圾收集手册:自动内存管理的艺术