📌 一、你们项目中使用了什么垃圾回收器?为什么?
答题结构:
-
选择哪种垃圾回收器(GC)
-
我们线上项目主要使用的是 G1 GC
-
历史系统曾使用过 CMS GC
-
-
为什么选择这个回收器?(场景驱动)
场景 回收器 原因 核心交易服务、高并发接口 G1 GC 停顿时间低、可预测、吞吐稳定 报表导出、批处理系统 CMS GC 并发回收、老年代回收性能好 容器化部署、大堆服务 ZGC/Shenandoah 超低延迟,适合8G+内存服务 -
项目实战举例:
我们在支付模块用 G1 替代 CMS,GC 停顿由 400ms 降至 60ms,提升了 TPS 峰值和稳定性。
📌 二、CMS GC 的原理是什么?用了什么算法?
答题结构:
-
基本介绍:
-
CMS(Concurrent Mark Sweep)是一种 老年代回收器
-
采用 标记-清除算法,追求最小化 STW 停顿时间
-
-
工作流程分为 4 步:
阶段 是否 STW 描述 初始标记 是 标记 GC Roots 的直接引用对象 并发标记 否 多线程并发标记可达对象 重新标记 是 修复并发标记期间的变化 并发清除 否 回收不可达对象,不移动对象 -
优点与缺点:
-
✅ 优点:响应时间低,适合对延迟敏感场景
-
❌ 缺点:内存碎片、并发失败会触发 Full GC,造成长时间 STW(
ConcurrentModeFailure)
-
-
项目实战举例:
我们曾在订单系统中使用 CMS,但出现碎片和并发失败问题,最终切换到 G1 解决。
📌 三、老年代都有哪些回收器?用了什么算法?
| 回收器 | 所属年代 | 回收算法 | 特点说明 |
|---|---|---|---|
| Serial Old | 老年代 | 标记-整理 | 单线程,适用于客户端或小堆 |
| Parallel Old | 老年代 | 标记-整理 | 吞吐量优先,多线程 Full GC |
| CMS | 老年代 | 标记-清除 | 并发回收、低延迟、可能碎片 |
| G1 GC | 新+老通用 | Region + 并发复制 | 分区管理堆,停顿可控 |
| ZGC / Shenandoah | 通用 | 并发回收 + 增量更新 | 超低延迟,适合大内存高实时场景(Java 11+) |
📌 四、G1 GC 与 CMS 的对比?
| 维度 | G1 GC | CMS GC |
|---|---|---|
| 回收算法 | Region + 并发复制 | 标记-清除 |
| 停顿控制 | ✅ 停顿可预测(PauseMillis) | ❌ 不可控 |
| 内存整理 | 自动整理碎片 | 无整理,可能出现碎片 |
| 并发能力 | 多阶段并发 | 并发标记+清除,其他需 STW |
| 弃用状态 | 默认垃圾回收器(Java 9+) | Java 14 起已弃用 |
📌 五、GC 调优和分析怎么做?
实操建议:
-
开启 GC 日志
-XX:+PrintGCDetails -Xloggc:/var/log/gc.log -
工具分析:
-
jstat / jvisualvm
-
GCViewer / GCeasy
-
Prometheus + Grafana 监控 GC 次数、时间、堆使用率
-
调优参数示例:
# G1 GC 优化
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
-XX:InitiatingHeapOccupancyPercent=45
📌 六、项目场景中的典型 GC 优化策略(面试可说服力更强)
| 场景 | 采取优化措施 |
|---|---|
| 多服务部署在容器中,堆大小不一致 | 加 -XX:+UseContainerSupport 让 JVM 识别 cgroup 限制 |
| CMS 出现 OOM | 调整 CMSInitiatingOccupancyFraction=70 或切换 G1 |
| 高并发业务交易 TPS 突增 | 使用 G1 + 限制新生代比例 + 降低 PauseMillis |
| 数据导出、异步服务 | 使用 Parallel GC 或 CMS 优化吞吐 |
✅ 面试小结口播建议(带结构):
“我们线上核心服务使用的是 G1 GC,结合业务延迟需求,通过
PauseMillis进行停顿控制。之前也使用过 CMS,但出现碎片和 FullGC 风险,因此替换。GC 日志我们通过 Grafana 可视化分析,一旦发现 GC 时间异常,就会结合 jstat 和 heap dump 工具排查内存热点,整体稳定性良好。”

974

被折叠的 条评论
为什么被折叠?



