一次 JVM Full GC 排查全过程

一、问题背景

某天下午,运维收到生产环境告警:某业务系统的定时任务服务 CPU 使用率飙升至 90%+,服务响应变慢,部分定时任务执行超时。

告警信息: [ALERT] xxx-schedule 服务 CPU 使用率 92.3% [ALERT] xxx-schedule 服务 Full GC 次数: 15次/分钟 [ALERT] syncDataJob 执行超时,耗时: 180s

二、问题现象

2.1 GC 日志分析

登录服务器查看 GC 日志:

tail -100f /logs/xxx-schedule/gc.log

2026-01-11T14:32:15.234+0800: [Full GC (Ergonomics) [PSYoungGen: 87296K->0K(153088K)] [ParOldGen: 349568K->298456K(349696K)] 436864K->298456K(502784K), [Metaspace: 128456K->128456K(1169408K)], 2.3456789 secs] 2026-01-11T14:32:18.123+0800: [Full GC (Ergonomics) [PSYoungGen: 87296K->0K(153088K)] [ParOldGen: 348234K->301234K(349696K)] 435530K->301234K(502784K), [Metaspace: 128456K->128456K(1169408K)], 2.5678901 secs] 2026-01-11T14:32:21.456+0800: [Full GC (Ergonomics) [PSYoungGen: 87296K->0K(153088K)] [ParOldGen: 349012K->305678K(349696K)] 436308K->305678K(502784K), [Metaspace: 128456K->128456K(1169408K)], 2.7890123 secs]

关键发现:

  • Full GC 频繁触发,约 3 秒一次
  • 老年代使用率持续在 85%+ (298456K/349696K)
  • 每次 Full GC 后老年代释放空间有限,呈上涨趋势
  • GC 耗时较长(2.3s ~ 2.8s)

2.2 使用 jstat 观察

jstat -gcutil 1000 10

S0 S1 E O M CCS YGC YGCT FGC FGCT GCT 0.00 98.23 45.67 86.34 94.12 91.23 1234 12.345 156 312.456 324.801 0.00 0.00 78.90 87.56 94.12 91.23 1235 12.456 157 315.234 327.690 0.00 97.45 12.34 88.91 94.12 91.23 1236 12.567 158 318.012 330.579

分析:

  • O (老年代) 持续增长:86% → 87% → 88%
  • FGC 次数快速增加
  • FGCT (Full GC 总时间) 占 GCT 的 96%+

三、定位过程

3.1 Dump 堆内存

# 生成堆转储文件 jmap -dump:format=b,file=/tmp/heap_dump_20260111.hprof

# 或者使用 jcmd(推荐) jcmd GC.heap_dump /tmp/heap_dump_20260111.hprof

3.2 使用 MAT 分析

导入 Eclipse MAT (Memory Analyzer Tool) 分析:

Leak Suspects 报告:

Problem Suspect 1:

The thread "xxl-job, JobThread-15-1704960000000" keeps local variables with total size 156,789,456 bytes (45.2% of total heap). Keywords: java.util.ArrayList, java.util.HashMap

Dominator Tree 分析:

3.3 追踪到具体代码

通过 MAT 的 “Path to GC Roots” 功能,定位到内存持有路径:

Thread: xxl-job, JobThread-15-1704960000000

└── SyncDataJob.handler() └── dataList (ArrayList) └── HashMap (156MB) └── Order objects (300,000+ 条)

四、根因分析

4.1 问题代码定位

查看 SyncDataJob.java:

@XxlJob(“syncDataJob”) public ReturnT handler(){

log.info("数据同步Job开始执行"); Long minId = 0L; while (true) { // 问题1: 每次查询100条,但内存中累积了所有处理过的数据 List<Map<String, Object>> dataList = orderMapper.selectByPage(minId, BATCH_SIZE); if (CollectionUtils.isEmpty(dataList)) { break; } // 问题2: 循环内创建大量临时对象 for (Map<String, Object> data : dataList) { Map<String, Object> map = new HashMap<>(); // 每条记录创建新Map // ... 填充数据 List<Map<String, Object>> paramList = new ArrayList<>(); paramList.add(map); // 调用外部服务 externalService.process(paramList); } // 更新minId继续下一批 minId = dataList.stream() .map(d -> ((Number) d.get("id")).longValue()) .max(Long::compareTo) .orElse(minId); } return ReturnT.SUCCESS;

}

4.2 问题分析

问题一:MyBatis 查询返回 Map 类型触发自定义 TypeHandler


项目配置了全局 TypeHandler: mybatis.type-handlers-package=com.xxx.domain.typehandler
JsonTypeHandler 会拦截 Map 类型,尝试将每个列值反序列化:
@MappedJdbcTypes(JdbcType.VARCHAR) public class JsonTypeHandler extends BaseTypeHandler {
private Map<String,String> map = new TreeMap<>(); // 每次实例化都创建 @Override public Map getNullableResult(ResultSet resultSet, String s) throws SQLException { return this.toObject(resultSet.getString(s), map.getClass()); // 频繁创建TreeMap }
}
问题二:循环内频繁创建临时对象
每处理一条记录就创建:

  • 1 个 HashMap (约 200 bytes)
  • 1 个 ArrayList (约 88 bytes)
  • 若干 String 对象

当数据量大时(如 30 万条),产生大量短生命周期对象,导致 Young GC 频繁,部分对象晋升到老年代。
问题三:数据量估算
– 查询符合条件的数据量 SELECT COUNT(1) FROM order_info WHERE status = 0; – 结果: 324,567 条
五、解决方案
5.1 修复 TypeHandler 冲突

5.2 优化内存使用

@XxlJob(“syncDataJob”) public ReturnT handler(){ log.info("数据同步Job开始执行"); Long minId = 0L; // 复用对象 Map<String, Object> map = new HashMap<>(16); List<Map<String, Object>> paramList = new ArrayList<>(1); while (true) { List<Map<String, Object>> dataList = orderMapper.selectByPage(minId, BATCH_SIZE); if (CollectionUtils.isEmpty(dataList)) { break; } for (Map<String, Object> data : dataList) { map.clear(); // 复用Map Long id = ((Number) data.get("id")).longValue(); minId = Math.max(minId, id); // 填充数据... map.put("orderId", data.get("orderId")); // ... paramList.clear(); paramList.add(map); externalService.process(paramList); } // 显式释放引用,帮助GC dataList.clear(); dataList = null; log.info("处理了一批数据,当前minId={}", minId); } return ReturnT.SUCCESS; }

5.3 JVM 参数调优

# 原参数 -Xms512m -Xmx512m -XX:+UseParallelGC # 优化后 -Xms1g -Xmx1g -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:G1HeapRegionSize=8m -XX:InitiatingHeapOccupancyPercent=45 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/logs/xxx-schedule/

六、效果验证

6.1 修复后 GC 情况

jstat -gcutil 1000 10

S0 S1 E O M CCS YGC YGCT FGC FGCT GCT 0.00 45.23 23.45 34.56 92.34 89.12 234 4.567 2 0.234 4.801 0.00 0.00 56.78 34.78 92.34 89.12 235 4.678 2 0.234 4.912 0.00 43.21 12.34 35.12 92.34 89.12 236 4.789 2 0.234 5.023

对比:

七、经验总结

7.1 排查流程

告警触发 → GC日志分析 → jstat观察 → heap dump → MAT分析 → 代码定位 → 修复验证

7.2 常见 Full GC 原因

  1. 内存泄漏:对象被长生命周期引用持有
  2. 大对象分配:直接进入老年代
  3. TypeHandler/序列化问题:隐式创建大量临时对象
  4. 批处理未分批:一次性加载过多数据
  5. MetaSpace 不足:类加载过多

7.3 预防措施

  1. 代码规范:批量处理必须分页,循环内避免频繁创建对象
  2. 监控告警:配置 GC 次数、老年代使用率告警
  3. 定期审查:review MyBatis resultType、TypeHandler 配置
  4. 压测验证:大数据量场景必须压测

7.4 常用排查命令速查

# 查看 GC 统计 jstat -gcutil 1000

# 查看堆内存使用 jmap -heap

# 生成堆转储 jcmd GC.heap_dump /tmp/dump.hprof

# 查看线程栈 jstack > /tmp/thread_dump.txt

# 查看类加载统计 jmap -histo | head -50

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1195068.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

盘点顺德猪杂粥加盟品牌,排名前十的都有谁?

问题1:想加盟顺德猪杂粥品牌,该怎么选口碑不错的品牌?关键看哪些维度? 选择口碑不错的顺德猪杂粥加盟品牌,核心要从产品壁垒、供应链实力、运营扶持、市场验证四个维度判断。很多创业者容易陷入只看加盟费高低的误…

2025年业界推荐:三集一体除湿热泵机组优质生产商口碑榜单,市面上可靠的三集一体除湿热泵机组公司口碑推荐榜普沃泰专注行业多年经验,口碑良好

随着全民健身意识的提升与文旅产业的蓬勃发展,室内恒温泳池、水上乐园等场所的建设需求日益旺盛。然而,此类高湿环境对空气品质、能耗控制及设备耐久性提出了严峻挑战。三集一体除湿热泵机组,作为集除湿、制冷/制热…

银川市灵武永宁贺兰英语雅思培训辅导机构推荐,2026权威出国雅思课程中心学校口碑排行榜

在留学热潮持续升温的当下,雅思考试已成为银川市灵武、永宁、贺兰地区学子开启海外求学之路的关键通行证。然而,雅思培训选课难、提分效率低、优质资源稀缺等痛点普遍存在,多数考生在备考中面临技巧匮乏、方案不匹配…

聊聊口碑不错的AI应用技能培训机构哪家性价比高

2026年数字经济与实体经济深度融合,AI应用技能已成为个人职业升级、企业数字化转型的核心驱动力。无论是AI+新媒体运营、工业AI智能体部署,还是数据资产确权与交易,优质的AI应用技能培训机构能帮助企业与个人快速突…

**Apache Hadoop生态**构建,整合分布式存储、资源调度、计算引擎、数据管理、运维治理等全链路工具,提供从数据采集、存储、计算、分析到治理的端到端大数据处理能力

大数据加工基础组件平台技术白皮书 一、 平台概述 本大数据加工基础组件平台基于Apache Hadoop生态构建&#xff0c;整合分布式存储、资源调度、计算引擎、数据管理、运维治理等全链路工具&#xff0c;提供从数据采集、存储、计算、分析到治理的端到端大数据处理能力。平台覆盖…

2025小游戏买量真相:每天烧掉1个亿,投放素材翻倍,谁在收割?谁在挣扎?

在经历了2025年的快速发展后&#xff0c;2026年小游戏行业或保持着较强的增长态势。多平台测算数据显示&#xff0c;2025年国内小游戏市场规模约为610亿元&#xff0c;同比增长 22%&#xff0c;预计2026年市场规模将突破700亿元。小游戏增速从2024年64.47%回落至2025年的22%&am…

2026年广州有实力的企业AI培训公司:看哪家口碑好?

本榜单依托全维度市场调研与真实行业口碑,深度筛选出五家标杆企业,为大健康、美容等领域的中小企业主选型提供客观依据,助力精准匹配适配的AI营销培训服务伙伴。 TOP1 推荐:广州量剑数智科技有限公司 推荐指数:★…

Tiktok、Facebook、Linkedin、Google、INS营销推广服务商有哪些?2026年欧美市场推广营销服务商盘点

2026年,欧美市场仍是全球品牌出海的核心阵地,社交媒体与搜索引擎营销成为破局关键。数据显示,TikTok全球月活跃用户已突破20亿,平均每日使用时长超90分钟,其“一商卖全球”新政落地后,进一步降低了品牌多区域布局…

牛客网最新版Java面试题1000+附答案大全(合适各级Java开发人员)

作为一名优秀的程序员&#xff0c;技术面试都是不可避免的一个环节&#xff0c;一般技术面试官都会通过自己的方式去考察程序员的技术功底与基础理论知识。 2026 年的互联网行业竞争越来越严峻&#xff0c;面试也是越来越难&#xff0c;很多粉丝朋友私信希望我出一篇面试专题或…

执行ranger-admin setup.sh报错TypeError: a bytes-like object is required, not str

报错代码: 报错内容: Traceback (most recent call last):File "db_setup.py", line 1455, in <module>main(sys.argv)File "db_setup.py", line 1422, in mainrun_env_file(env_file_pat…

2026年精密空调代理商排行榜,金盛通科技排名靠前原因揭秘

本榜单依托全维度市场调研与真实行业口碑,深度筛选出五家精密空调代理领域的标杆企业,为企业选型提供客观依据,助力精准匹配适配的服务伙伴。 TOP1 推荐:北京金盛通科技发展有限责任公司 推荐指数:★★★★★ | 口…

银川市灵武永宁贺兰英语雅思培训辅导机构推荐、2026权威出国雅思课程中心学校口碑排行榜

在雅思培训市场竞争日趋激烈的当下,银川市及灵武、永宁、贺兰周边区域的雅思考生普遍面临诸多困境:渴望找到优质教育机构掌握高效提分技巧,却深陷选课迷茫,难以辨别机构的靠谱程度;既追求个性化提分方案的实用价值…

burpsuite 激活

1)卸载社会版 apt remove burpsuite 2)下载官方jar包,如:burpsuite_pro_v2025.7.2.jar(不是.sh) 3)下载激活包 如:BurpLoader13.jar 4)将两个包放入同一文件夹,如:burp 5)运行激活包java -jar BurpLoader13.j…

精选5家海外本地化营销推广服务商,助力外贸企业通过 Facebook、LinkedIn、TikTok 、INS、Google低成本营销推广高效获客

在全球贸易数字化转型加速的背景下,传统获客模式竞争日趋激烈,海外社交媒体与搜索引擎已成为外贸企业开辟新市场的核心阵地。商务部研究院预测,中国跨境电商B2B交易额将在2025年增至15万亿元,而Digital 2026报告显…

2026年收银系统源码供应商推荐:银枣软件为何成为餐厅收银系统/奶茶店收银系统/餐饮管理系统首选

在数字化浪潮席卷实体商业的今天,越来越多中大型连锁商户开始意识到:通用型SaaS收银系统虽便捷,却难以满足其对数据主权、业务灵活性和系统深度定制的核心诉求。尤其当企业走向多门店、跨区域甚至跨国经营时,“租用…

typescript 手动实现 Readonly

最近游戏开发的时候写出了非常神秘的代码,发现可以用泛型实现 Readonly(虽然 ts 自带这个语法糖) 这个是我的类型 type TGameData = Record<string, any>;type Condition = <T extends TGameData>(this…

VMware Harbor 2.10.1 密码忘记重置

-- 第1步:修改harbor_user表的password字段,把长度从40扩容到100,永久生效,核心命令! ALTER TABLE harbor_user ALTER COLUMN password TYPE VARCHAR(100);-- 第2步:执行你原来的密码更新语句,写入你的BCrypt哈…

高纯溶剂品牌深度测评:谁在质量、性价比与售后服务上更胜一筹?

某半导体企业因选用低价高纯溶剂,导致芯片清洗良率骤降 15%,直接损失超 3000 万元;某药企因供应商售后响应迟缓,实验数据异常问题拖延 72 小时,错失新药申报窗口期 —— 高纯溶剂的选择,从来不是 “选贵的” 或 …

2026年翅片管式换热器厂家TOP5测评:全场景适配品牌推荐,华之博成华东地区高要求环境首选

引言:翅片管式换热器进入“高要求场景”竞争新阶段 作为 HVAC 系统末端热能交换的核心设备,翅片管式换热器的性能直接影响建筑环境的稳定性与运营成本。近年来,随着医药、化工、轨道交通等行业对“耐腐蚀性、低维护…

JCJC:一款 API-First 的硬核剪贴板管理工具

JCJC:一款 API-First 的硬核剪贴板管理工具 分享一个我日常高频使用的剪贴板增强工具——JCJC。与传统工具不同,它专注于API 自动化与Markdown 知识流,非常适合开发者和内容创作者。核心特性: ⚡️ API First &am…