一次线上服务fullGC原因排查


一、现象
早上九点多又收到了fullGC次数过高的应用监控告警{P1}{故障}JVM Old GC all(#3) full_gc_count  >5}{当前值:28},通过公司使用的监控平台可以观察到服务器在这个时间段内确实出现了一些异常情况:

1.负载突然增加

2.fullgc频率显著增加,每次时间渐渐增长

3.老年代内存使用率增长很快(大量对象直接进入老年带),可以看到Survivor区一直被打满(Survivor功效丧失,大量新生代对象不能及时回收越过Survivor直接进入年老代)




二、工具排查

线上日志dump

使用jmap -dump:live,format=b,file=xxx [pid]

工具介绍

市面上提供了很多种工具比如visualVM、JMAT、Jprofile和ha等工具,都可以进行内存堆快照文件分析

1、Jprofile

使用Jprofile需要先将文件后缀修改为hprof,用Jprofile可以一目了然的看出是大量对象,而且可以看到具体的方法一级classloader信息


2、ha

使用ha工具需要将dump文件后缀修改为jvmdump结尾,通过ha.jar工具查看可以看到大对象数量为66万多和38万多,分别占用了300多兆和65多兆堆内存


3、JMAT

JMAT也是很好用的工具,建议安装了eclipse的使用

4、visualVM

这里不建议用visualVM分析,一个需要设置出展示具体的方法或者对象(没研究出来),而且默认的内存空间比较小,要看大对象需要修改参数
经过试验后,对于dump文件分析最好是用Jprofile或者ibm出的ha.jar这个工具或者进行分析效果较好
 

三、排查结果分析

1、分析结果验证

根据工具分析结果,对照着监控中的异常可以看到9点11分时候三次long-SQL中查询返回了大量对象发现结果和时间都是吻合的,于是进一步排查代码

2、代码排查

排查过程中发现项目中并没有类似分类服务调用及SQL查询,是由于依赖的jar包中的方法有查询数据库,用的是本地缓存的形式,有个定时器类会从lion配置定时读取信息,
缓存过期时间设置的是3600000s,
查到原因这个服务没有人重新发布部署过,所以经过四十一天后缓存过期后,再初始化缓存时会重新读数据库获取所有分类和城市的数据,两次查询分别获取了六十多万分类与城市对应关系的对象,由于数量多,申请堆空间过大,所以大量对象直接进入了老年代,触发了fullGC
 

四、解决

这个方法是老的架构组件中方法并且已经很久没人维护,后续这类商区服务的实现方式需要重构,去掉了本地缓存和直接读取数据库的方法,改为分页调用不是直接查缓存
<think>嗯,用户想了解如何使用jstat在线排查JVM性能问题和错误日志。首先,我得回顾一下jstat的基本用法和常见参数。jstat是JDK自带的一个监控工具,主要用于查看JVM的堆内存、垃圾回收情况等实时数据。用户可能遇到了内存泄漏或者GC问题,需要快速定位问题。 接下来,用户提到的引用中,有OutOfMemoryError和GC相关的问题,所以需要结合这些引用内容来回答。引用3提到了GC调优和内存泄漏的处理,可能需要引导用户查阅之前的文章,但当前问题是如何使用jstat进行排查,所以重点应放在jstat命令的具体使用上。 需要分步骤说明如何使用jstat,包括常用参数如-gc、-gcutil,以及如何解读输出结果。例如,检查各个内存区域的使用情况,Young GC和Full GC的频率及耗时,这些指标如何反映潜在问题。比如,如果老年代内存持续增长,可能提示内存泄漏;如果Full GC频繁,可能内存不足或存在对象晋升问题。 还要考虑用户可能遇到的错误场景,比如内存溢出,这时候jstat可以帮助实时监控内存变化,观察GC是否能有效回收内存。此外,结合引用2中的系统负载和阈值问题,可能需要指导用户在高负载时持续监控,对比正常和异常时的数据差异。 需要注意用户的线上环境,可能没有图形化工具,所以命令行工具jstat更实用。同时,提醒用户结合其他工具如jstack、内存分析工具进行综合排查,如引用4提到的其他排查技术。 最后,生成的相关问题要围绕JVM性能调优、内存泄漏处理、其他监控工具使用等,帮助用户扩展知识。确保回答结构清晰,步骤明确,用户能一步步跟着操作,同时引用相关的参考资料,如引用3和4,增强可信度。</think>### 如何使用 jstat 在线排查 JVM 性能问题及错误日志 #### 1. **jstat 核心功能与常用参数** jstat 是 JDK 自带的 JVM 监控工具,通过实时统计堆内存、类加载、垃圾回收(GC)等数据,帮助定位性能瓶颈。常用命令格式: ```bash jstat -<option> <vmid> [interval] [count] ``` - **关键参数**: - `-gc`:堆内存与 GC 详情 - `-gcutil`:堆内存使用百分比 - `-class`:类加载与卸载统计 - `-gccause`:最近一次 GC 原因 #### 2. **排查内存泄漏与 GC 问题** **场景示例**:若出现 `java.lang.OutOfMemoryError`[^1],可通过以下步骤分析: ```bash # 每 2 秒输出一次 GC 统计,持续 10 次 jstat -gcutil <pid> 2000 10 ``` 输出字段解析: - `S0`/`S1`:Survivor 区使用率 - `E`:Eden 区使用率 - `O`:老年代使用率(若持续增长,可能内存泄漏[^3]) - `FGC`/`FGCT`:Full GC 次数与耗时(频繁 Full GC 需警惕) **典型问题判断**: - **内存泄漏**:`O` 区使用率持续上升且 Full GC 后不下降 - **Young GC 频繁**:`E` 区快速填满,可能因对象分配速率过高或 Survivor 区过小 #### 3. **结合日志定位异常** 若系统出现 CPU 负载高且 JVM 内存堆积[^2],需综合 `jstat` 与 GC 日志: 1. 启用 GC 日志: ```bash -Xloggc:/path/to/gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps ``` 2. 通过 `jstat -gccause <pid>` 查看最近 GC 触发原因(如 `System.gc()` 调用) #### 4. **实战案例:老年代内存溢出** **现象**:`O` 区使用率 99%,Full GC 后仍无释放 **排查步骤**: 1. 通过 `jstat -gc <pid> 1000` 监控各分区对象变化 2. 若 `OU`(老年代已用内存)持续增长,结合 `jmap -histo:live <pid>` 查看存活对象分布 3. 定位到可疑类后,使用内存分析工具(如 MAT)进一步诊断 #### 5. **注意事项** - **避免误判**:瞬时高峰可能触发 Full GC,需持续监控至少 5 分钟 - **结合其他工具**:`jstack` 分析线程阻塞,`jmap` 生成堆转储[^4] - **调优参考**:根据 `jstat` 数据调整新生代/老年代比例(`-XX:NewRatio`)或 Survivor 区比例(`-XX:SurvivorRatio`) ```bash # 示例:输出进程 12345 的 GC 统计,每秒 1 次 jstat -gc 12345 1000 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值