面试题答案
一键面试Serial垃圾回收器
- 回收流程:
- 新生代:采用复制算法。当新生代空间不足时,会触发Minor GC,暂停所有用户线程,将存活对象复制到Survivor区或老年代(晋升)。
- 老年代:采用标记 - 整理算法。当老年代空间不足时,触发Full GC,暂停所有用户线程,标记出所有存活对象,然后将存活对象整理到内存一端,清理掉另一端的空间。
- 适用场景:适用于单核环境下的客户端应用,因为它简单高效,且停顿时间在可接受范围内。
- 调优思路:可通过调整堆大小、新生代与老年代比例(-XX:NewRatio)来优化。如果新生代对象朝生夕灭,可适当增大新生代空间;如果老年代对象存活时间长,可增大老年代空间。
Parallel垃圾回收器
- 回收流程:
- 新生代:与Serial类似,采用复制算法,但它是多线程并行进行垃圾回收。在Minor GC时,多个线程同时工作,能更快完成对象复制和空间清理,同样会暂停用户线程。
- 老年代:采用标记 - 整理算法,多线程并行执行标记和整理过程,Full GC时也会暂停所有用户线程。
- 适用场景:适用于多CPU的服务器环境,追求高吞吐量,能快速处理大量数据。
- 调优思路:可通过设置并行线程数(-XX:ParallelGCThreads)来调优。如果CPU核心数多,可适当增加线程数提高回收效率;也可通过调整堆大小、新生代与老年代比例来优化整体性能。
CMS(Concurrent Mark Sweep)垃圾回收器
- 回收流程:
- 新生代:采用与Parallel类似的多线程复制算法进行Minor GC,暂停用户线程。
- 老年代:采用标记 - 清除算法,回收过程分为4个阶段:
- 初始标记:暂停所有用户线程,标记出直接与GC Roots相连的对象,速度很快。
- 并发标记:与用户线程并发执行,从初始标记的对象开始,标记出所有存活对象。
- 重新标记:暂停用户线程,修正并发标记期间因用户线程活动而产生变化的标记记录。
- 并发清除:与用户线程并发执行,清除未标记的对象,释放空间。
- 适用场景:适用于对响应时间要求高的应用,如Web应用,尽量减少垃圾回收时的停顿时间。
- 调优思路:可通过调整CMS线程数(-XX:ConcGCThreads)来优化并发阶段性能;还可通过设置CMS开始回收的阈值(-XX:CMSInitiatingOccupancyFraction),避免老年代空间被填满才开始回收导致Full GC。
G1(Garbage - First)垃圾回收器
- 回收流程:
- 整体:将堆内存划分为多个大小相等的Region,这些Region动态扮演新生代或老年代角色。
- 新生代:采用复制算法,新生代回收(Minor GC)时,选取所有新生代Region进行回收,暂停用户线程。
- 老年代:采用标记 - 整理算法,回收过程包括:
- 初始标记:暂停用户线程,标记出直接与GC Roots相连的对象。
- 并发标记:与用户线程并发执行,标记出所有存活对象。
- 最终标记:暂停用户线程,处理并发标记阶段的剩余任务。
- 筛选回收:根据每个Region的回收价值和成本,选择部分Region进行回收(混合回收),可并发或并行执行,暂停用户线程。
- 适用场景:适用于大堆内存,且对响应时间和吞吐量都有一定要求的应用,能在有限时间内尽量减少停顿时间。
- 调优思路:可通过设置G1堆区域大小(-XX:G1HeapRegionSize)、最大停顿时间目标(-XX:MaxGCPauseMillis)来调优。如果希望更关注响应时间,可降低最大停顿时间目标,但可能会影响吞吐量;还可通过调整新生代和老年代的比例等参数优化整体性能。