面试题答案
一键面试选择G1而非CMS的原因
- 分代与分区
- CMS:基于分代收集算法,将堆分为年轻代和老年代,回收时需要扫描整个老年代,可能导致较长的停顿时间,在高并发对响应时间敏感的场景下,这是不利的。
- G1:采用分区(Region)的方式,逻辑上仍然分代,但物理上不再是连续的空间。G1可以有选择地回收部分Region,优先处理垃圾最多的Region(即垃圾优先回收原则),能有效控制停顿时间,更适合高并发响应时间敏感场景。
- 停顿时间可预测性
- CMS:虽然致力于减少老年代回收时的停顿时间,但在并发标记和清理阶段,仍可能因为浮动垃圾等问题导致停顿时间不可预测,尤其是在堆内存较大且高并发情况下。
- G1:通过设定预期停顿时间(-XX:MaxGCPauseMillis参数),能在该时间预算内尽量完成垃圾回收工作,停顿时间更具可预测性,满足高并发Web应用对响应时间的要求。
- 内存碎片化
- CMS:在回收过程中容易产生内存碎片化问题,随着时间推移,可能导致大对象无法分配到连续内存空间,即使堆内存还有足够的空闲空间,从而提前触发Full GC,增加停顿时间。
- G1:在回收过程中,会进行空间整合,减少内存碎片化,有利于应用长期稳定运行。
G1垃圾回收器调优参数
- 停顿时间相关
- -XX:MaxGCPauseMillis:设定G1收集器目标最大停顿时间,单位是毫秒。例如 -XX:MaxGCPauseMillis=200,表示希望每次垃圾回收停顿时间不超过200毫秒。G1会尽力在这个时间内完成垃圾回收工作,但这只是一个软目标,实际可能会稍有超出。
- 堆内存相关
- -Xmx:设置Java堆的最大内存。例如 -Xmx4g,表示最大堆内存为4GB。在高并发Web应用中,合理设置堆内存大小能避免频繁的垃圾回收。
- -Xms:设置Java堆的初始内存。通常建议 -Xms 和 -Xmx 设置为相同的值,以避免在运行时不断调整堆大小带来的额外开销。例如 -Xms4g 。
- Region相关
- -XX:G1HeapRegionSize:设置G1区域(Region)的大小,取值范围是1MB到32MB,且必须是2的幂次方。例如 -XX:G1HeapRegionSize=16m ,较小的Region可以更细粒度地进行垃圾回收,但也会增加元数据的开销;较大的Region适合存储大对象。
- 并发线程相关
- -XX:ConcGCThreads:设置并发标记阶段使用的线程数。默认值是根据逻辑处理器数量动态计算的。在高并发场景下,如果逻辑处理器资源充足,可以适当增加该值以加快并发标记速度,但过多的线程也会带来线程上下文切换的开销。例如 -XX:ConcGCThreads=8 。
- -XX:G1ParallelGCThreads:设置并行垃圾回收阶段使用的线程数。同样,默认值根据逻辑处理器数量动态计算。在硬件资源允许的情况下,增加该值可以加快垃圾回收速度。例如 -XX:G1ParallelGCThreads=16 。