推荐答案
G1(Garbage-First)收集器是 Java 虚拟机(JVM)中的一种垃圾收集器,主要用于大内存、多处理器的服务器环境。G1 收集器的执行过程可以分为以下几个阶段:
- 初始标记(Initial Marking):标记所有从 GC Roots 直接可达的对象。这个阶段需要暂停所有应用线程(Stop-The-World)。
- 并发标记(Concurrent Marking):从 GC Roots 开始,遍历整个堆,标记所有存活的对象。这个阶段与应用线程并发执行。
- 最终标记(Final Marking):处理并发标记阶段中发生变化的对象,并完成标记。这个阶段也需要暂停所有应用线程。
- 筛选回收(Evacuation):根据用户指定的停顿时间目标,选择一些区域进行回收,并将存活的对象复制到新的区域。这个阶段也需要暂停所有应用线程。
本题详细解读
1. 初始标记(Initial Marking)
初始标记阶段是 G1 收集器的第一个阶段,主要任务是标记所有从 GC Roots 直接可达的对象。GC Roots 包括:
- 虚拟机栈中引用的对象
- 方法区中类静态属性引用的对象
- 方法区中常量引用的对象
- 本地方法栈中 JNI(即一般说的 Native 方法)引用的对象
这个阶段需要暂停所有应用线程(Stop-The-World),但由于只标记直接可达的对象,所以暂停时间通常很短。
2. 并发标记(Concurrent Marking)
并发标记阶段是 G1 收集器的核心阶段之一。在这个阶段,G1 收集器会从 GC Roots 开始,遍历整个堆,标记所有存活的对象。这个阶段与应用线程并发执行,因此不会长时间阻塞应用线程。
并发标记阶段的主要挑战是处理并发修改,即应用线程在标记过程中可能会修改对象的引用关系。G1 收集器通过使用写屏障(Write Barrier)来记录这些修改,并在后续阶段进行处理。
3. 最终标记(Final Marking)
最终标记阶段是并发标记阶段的补充,主要任务是处理并发标记阶段中发生变化的对象,并完成标记。这个阶段需要暂停所有应用线程(Stop-The-World),但由于只需要处理少量的变化对象,所以暂停时间通常较短。
最终标记阶段还包括一些额外的处理,如处理弱引用、清理未使用的类元数据等。
4. 筛选回收(Evacuation)
筛选回收阶段是 G1 收集器的最后一个阶段,主要任务是根据用户指定的停顿时间目标,选择一些区域进行回收,并将存活的对象复制到新的区域。这个阶段也需要暂停所有应用线程(Stop-The-World)。
G1 收集器通过将堆划分为多个大小相等的区域(Region),并根据每个区域的垃圾比例(即存活对象的比例)来选择回收哪些区域。这样可以最大限度地减少回收过程中的停顿时间,同时保证回收效率。
在筛选回收阶段,G1 收集器会将存活的对象复制到新的区域,并清理旧区域中的垃圾对象。这个过程称为“疏散”(Evacuation)。