JVM(Java Virtual Machine)中的垃圾回收器负责自动管理内存,它通过识别并释放不再被程序使用的对象来回收堆内存。以下是垃圾回收器的基本工作原理:
- 标记-清除(Mark-Sweep)算法:
- 初始时,垃圾回收器将所有对象都标记为“存活”状态。
- 从根对象(如静态变量、栈中的引用等)开始,递归地访问对象的所有引用,并将这些对象标记为“可达”或“存活”。
- 标记完成后,垃圾回收器会遍历整个堆内存,将所有未被标记的对象(即不可达对象)视为垃圾对象。
- 最后,垃圾回收器会清除这些垃圾对象,释放其占用的内存空间。
- 分代收集(Generational Collection):
- JVM将堆内存划分为不同的区域,如新生代(Young Generation)和老年代(Old Generation)。新生代又进一步细分为Eden区、Survivor From区和Survivor To区。
- 不同区域的对象具有不同的生命周期和回收特性。新生代中的对象通常生命周期较短,而老年代中的对象则生命周期较长。
- JVM使用不同的垃圾回收器来管理不同区域的内存。例如,针对新生代的垃圾回收器(如Serial、ParNew、Parallel Scavenge等)通常具有较高的回收频率和较低的回收成本;而针对老年代的垃圾回收器(如CMS、G1等)则具有较低的回收频率和较高的回收成本。
- 复制(Copying)算法:
- 主要用于新生代中的内存管理。新生代中的Eden区和Survivor区采用复制算法进行垃圾回收。
- 当Eden区内存不足时,会触发一次Minor GC(年轻代垃圾回收)。此时,存活的对象会被复制到其中一个Survivor区(假设为From区),然后清空Eden区和另一个Survivor区(To区)。
- 当下一次Minor GC发生时,存活的对象会被复制到另一个Survivor区(To区),并清空之前存放存活对象的Survivor区(From区)。此时,From区和To区的角色会互换。
- 标记-整理(Mark-Compact)算法:
- 主要用于老年代中的内存管理。当老年代空间不足时,会触发一次Full GC(整堆垃圾回收)。
- 与标记-清除算法类似,标记-整理算法也会从根对象开始标记所有可达对象。但不同的是,在标记完成后,它会将所有存活的对象移动到一端,然后直接清理掉边界以外的内存。
- 并发和并行收集:
- 为了提高垃圾回收的效率,JVM中的垃圾回收器支持并发和并行收集。并发收集允许垃圾回收器与应用线程同时运行,以减少垃圾回收对应用性能的影响;而并行收集则使用多个线程同时执行垃圾回收任务,以加快垃圾回收的速度。
- G1(Garbage-First)垃圾回收器:
- G1是Java 7及以后版本中引入的一种新型垃圾回收器。它结合了分代收集和并发收集的思想,旨在实现可预测的停顿时间(Pause Time)和较高的吞吐量。G1将整个堆内存划分为多个大小相等的区域(Region),并优先回收垃圾最多的区域。
总的来说,JVM中的垃圾回收器通过标记-清除、分代收集、复制、标记-整理等算法来识别并释放不再被程序使用的对象,从而回收堆内存。同时,为了提高垃圾回收的效率,JVM还支持并发和并行收集以及G1等新型垃圾回收器。