JVM的垃圾回收(Garbage Collection, GC)算法,在面试八股文时偶尔会被问到,了解一些常见的垃圾回收算法有利于面试时吊打面试官。
以下是JVM常见的几种垃圾回收算法的介绍:
1. 标记-清除算法(Mark-Sweep)
这是最基本的垃圾回收算法,主要步骤包括:
- 标记:从GC Root出发,标记所有可达的对象。
- 清除:遍历堆内存,清除所有未被标记的对象。
- 优点:简单,不需要移动对象。
- 缺点:会产生内存碎片。
2. 标记-整理算法(Mark-Compact)
为了解决标记-清除算法的内存碎片问题,引入了标记-整理算法:
- 标记:和标记-清除算法相同,标记所有可达对象。
- 整理:将存活对象压缩到堆的一端,清理边界外的内存。
- 优点:减少了内存碎片。
- 缺点:移动对象需要额外的成本。
3. 复制算法(Copying)
复制算法主要用于年轻代(Young Generation)对象的回收:
- 步骤:将存活的对象从一个内存区域复制到另一个内存区域,原来的内存区域全部清空。
- 优点:效率高,没有碎片问题。
- 缺点:需要额外的内存空间。
4. 分代收集算法(Generational Collection)
现代JVM使用分代收集算法,将堆内存分为不同的代(年轻代、年老代)进行管理:
- 年轻代(Young Generation):主要使用复制算法,分为Eden区和两个Survivor区(From和To)。
- 年老代(Old Generation):主要使用标记-整理算法。
- 持久代(Permanent Generation):用于存储类元数据,Java 8之后改为元空间(Metaspace)。
- 优点:根据对象的生命周期优化回收效率。
- 缺点:需要更多的调优和管理。
5. CMS(Concurrent Mark-Sweep)
CMS是为了减少GC暂停时间的一种垃圾回收器,主要用于年老代:
- 步骤:
-
- 初始标记(Initial Mark):标记GC Root直接可达的对象。
- 并发标记(Concurrent Mark):并发地标记所有可达对象。
- 重新标记(Remark):修正并发标记期间产生的新对象。
- 并发清除(Concurrent Sweep):并发地清除未被标记的对象。
- 优点:降低了停顿时间。
- 缺点:会产生内存碎片,且并发清理阶段对CPU资源要求较高。
6. G1(Garbage-First)
G1垃圾回收器是一种面向服务端应用的低暂停垃圾回收器,适用于大堆内存环境:
- 区域(Region):将堆划分为若干固定大小的区域,每个区域可以是年轻代或老年代的一部分。
- 回收过程:
-
- 初始标记(Initial Mark):标记GC Root直接可达的对象。
- 并发标记(Concurrent Mark):并发地标记所有可达对象。
- 最终标记(Final Mark):标记那些在并发标记阶段还存活的对象。
- 筛选回收(Live Data Counting and Evacuation):根据每个区域的回收价值进行回收。
- 优点:通过分区和增量回收,优化了停顿时间。
- 缺点:相对较新,需要更多的调优。
了解和调优这些垃圾回收算法对于Java应用性能优化非常关键。根据不同应用场景选择合适的GC策略,可以显著提升系统的稳定性和响应速度。