JVM(Java 虚拟机)中有多种垃圾回收算法,以下是对常见垃圾回收算法的汇总:
**一、标记-清除算法(Mark-Sweep)**
1. 过程:
- **标记阶段**:从根对象开始遍历所有可达对象,并标记它们。
- **清除阶段**:扫描整个堆内存,回收未被标记的对象所占用的空间。
2. 优点:
- 实现简单。
3. 缺点:
- 会产生内存碎片,可能导致后续分配大对象时无法找到连续的内存空间。
- 两次扫描堆内存,效率不高。
**二、复制算法(Copying)**
1. 过程:
- 将内存分为两块相等的区域,一般称为 From 区和 To 区。
- 当进行垃圾回收时,将 From 区中存活的对象复制到 To 区,然后清空 From 区。
- 下次垃圾回收时,From 区和 To 区角色互换。
2. 优点:
- 不会产生内存碎片。
- 只需要扫描一次存活对象,效率较高。
3. 缺点:
- 浪费一半的内存空间。
- 当对象存活率较高时,复制操作的开销较大。
**三、标记-整理算法(Mark-Compact)**
1. 过程:
- 与标记-清除算法的标记阶段相同,先标记出所有可达对象。
- 然后将所有存活的对象向一端移动,使它们紧凑地排列在一起,最后清理掉端边界以外的内存空间。
2. 优点:
- 不会产生内存碎片。
3. 缺点:
- 移动存活对象的操作比较耗时,效率相对较低。
**四、分代收集算法**
1. 概念:
- 根据对象的生命周期将内存划分为不同的代,针对不同代的特点采用不同的垃圾回收算法。一般分为年轻代(Young Generation)和老年代(Old Generation)。
2. 年轻代回收算法:
- 通常采用复制算法。因为年轻代中的对象大多生命周期较短,复制算法在这种情况下效率较高。
- 年轻代又分为 Eden 区和两个 Survivor 区(From Survivor 和 To Survivor)。新创建的对象首先在 Eden 区分配,当 Eden 区满时,触发一次 Minor GC(小型垃圾回收),将 Eden 区和 From Survivor 区中存活的对象复制到 To Survivor 区,然后清空 Eden 区和 From Survivor 区。经过多次 Minor GC 后,仍然存活的对象会被晋升到老年代。
3. 老年代回收算法:
- 通常采用标记-清除算法或标记-整理算法。因为老年代中的对象大多生命周期较长,存活率较高。
分代收集算法结合了不同的垃圾回收算法的优点,根据不同代的特点进行针对性的垃圾回收,提高了垃圾回收的效率。