记录一次sharingjdbc引起的fullgc频繁问题,总结一下fullgc频繁解决的方案

本文描述了一个由于SharingJDBC在执行SQL时未进行参数判断,导致大量对象创建并引发FullGC的问题。通过调整本地缓存配置及使用jmap命令,最终定位并修复了问题。

背景:最近做了个需求,为了优化效率所以做了本地缓存和redis缓存,这个跟实际问题没有很大关系,但在排查问题时造成了一定的干扰,导致排查时间变长了,这个问题的现象是上线后cpu急剧增高,fullgc次数比younggc次数多,而且每次fullgc回收的内存很少,fullgc频繁。
1.问题现象图:
在这里插入图片描述
在这里插入图片描述
2.分析:通过gc的情况可以看出一直在进行fullgc而没有进行younggc,这种情况猜测是有大对象执行进入了老年代,而且在老年代回收时没有被回收掉,正好代码里也使用的本地缓存,在上之前是有计算本地缓存会占多大内存的,通过计算是不可能成为大对象,但出问题了也只能试试了,下面是解决问题的思路。
2.1把本地缓存减小,上一版之后观察了半小时没出问题,以为改好了,但过了一段时间又出现了。
2.2把本地缓存都去掉,上一台服务器之后观察了一下午没出问题,此时认为终于可以了,全量之后不久出问题。
2.3到此时就很头痛了,不知道从何下手,因为服务器的内存有14G,使用jmap命令dump下来文件过大,在本地分析不了内存情况,幸好此时同事提供一个命令:jmap -histo:live pid | head -n 100 // 查询前100个内存使用过高的java类,使用此命令一看才发现真正的问题所在:
在这里插入图片描述
这个SQLIgnoreExpression说明sharingjdbc在执行sql报错了,在报错之后不停的在创建这个对象。然后再通过打印sql发现in里面有个空list。查看代码:

<think>好的,用户问的是如何分析JVM的Full GC频繁问题。我需要先回忆一下JVM的相关知识,特别是GC机制和调优方法。首先,用户可能是一个Java开发者或者运维人员,遇到了应用性能问题,导致Full GC频繁触发,影响系统稳定性。他们需要知道具体的排查步骤和工具使用方法。 首先,我应该从常见的原因入手,比如堆内存不足、老年代对象过多、内存泄漏等。然后,介绍常用的诊断工具,如jstat、jmap、MAT等。需要详细说明每个工具的使用方法和输出结果的解读。例如,jstat可以用来监控GC状态,查看各个区域的内存使用情况;jmap生成堆转储文件,用MAT分析对象分布,找出内存泄漏点。 接下来,可能需要分步骤说明分析流程:监控指标、定位原因、优化配置、验证效果。每个步骤下给出具体的操作建议,比如如何调整堆大小、选择合适的GC算法等。同时,要提到一些常见的优化参数,比如-Xmx、-XX:+UseG1GC等,并解释这些参数的作用。 还要注意用户可能的误区,比如盲目增加堆内存而没有解决根本问题,或者忽视元空间和直接内存的溢出。另外,需要提醒用户在分析时结合应用的具体业务场景,比如是否有大量临时对象生成,或者缓存机制设计不合理。 最后,要确保回答结构清晰,步骤明确,工具使用示例具体,并且给出相关问题供用户进一步思考。这样用户不仅能解决当前的问题,还能深入理解JVM的GC机制,预防未来出现类似问题。 </think>分析 JVM Full GC 频繁问题需结合监控工具与日志分析,以下是系统化排查步骤: --- ### **1. 监控 GC 状态** **工具**:`jstat -gc <pid>`(实时监控) ```bash # 示例:每秒输出一次 GC 状态 jstat -gc 12345 1000 ``` **关键指标**: - **老年代使用率**(`OC` 列):接近 `OL` 时触发 Full GC - **Full GC 次数**(`FGC` 列):单位时间频繁增长 - **Full GC 停顿时间**(`FGCT` 列):单次停顿过长(>1s) --- ### **2. 定位 Full GC 原因** #### **(1) 老年代空间不足** - **现象**:`OC` 接近 `OL`,`FGC` 次数激增 - **解决**: - **扩大堆内存**:`-Xmx` 和 `-Xms` 调整为合理值(如 8GB) - **优化对象晋升**:减少年轻代到老年代的对象迁移(如增大 Survivor 区:`-XX:SurvivorRatio=8`) #### **(2) 元空间(Metaspace)不足** - **现象**:`Metaspace` 使用率接近上限(`jstat -gccapacity` 查看) - **解决**: ```bash -XX:MaxMetaspaceSize=512m # 设置元空间上限 ``` #### **(3) 直接内存溢出** - **现象**:`OutOfMemoryError: Direct buffer memory` - **解决**: ```bash -XX:MaxDirectMemorySize=512m # 限制直接内存大小 ``` #### **(4) 内存泄漏** - **现象**:老年代对象持续增长,GC 无法回收 - **排查步骤**: 1. **生成堆快照**:`jmap -dump:format=b,file=heap.bin <pid>` 2. **分析工具**:使用 MAT(Memory Analyzer)查看支配树(Dominator Tree) 3. **典型泄漏点**: - **静态集合类**(如 `static List` 未清理) - **监听器/缓存未注销**(如 `ServletContextListener`) - **线程池未关闭**(线程对象持续累积) --- ### **3. 优化 GC 策略** #### **(1) 选择合适的 GC 器** - **低延迟场景**:G1(`-XX:+UseG1GC`)或 ZGC(Java 11+) - **高吞吐场景**:Parallel Scavenge(`-XX:+UseParallelGC`) - **避免 CMS**(已废弃):易产生内存碎片,需手动配置 `CMSInitiatingOccupancyFraction` #### **(2) 调整 GC 参数** ```bash # G1 示例配置 -XX:+UseG1GC \ -XX:MaxGCPauseMillis=200 \ # 控制最大停顿时间 -XX:G1HeapRegionSize=4M \ # 区域大小(默认 0,自动计算) -XX:InitiatingHeapOccupancyPercent=45 # 触发并发标记的堆占用比例 ``` --- ### **4. 验证优化效果** - **对比监控数据**:使用 `jstat` 或可视化工具(如 JConsole、VisualVM) - **压测验证**:通过 `JMeter` 模拟高负载,观察 GC 行为是否稳定 - **长期观测**:部署后持续监控 GC 日志(`-Xlog:gc*:file=gc.log:time`) --- ### **5. 典型案例分析** #### **案例1:老年代频繁 Full GC** - **原因**:短期任务频繁生成大对象(如 `String` 拼接) - **解决方案**: - 优化代码逻辑,减少大对象创建 - 增大老年代大小(`-XX:NewRatio=3` 调整年轻代/老年代比例) #### **案例2:元空间溢出** - **原因**:动态加载类过多(如热部署场景) - **解决方案**: - 设置元空间上限(`-XX:MaxMetaspaceSize=1g`) - 使用类卸载(`-XX:+ClassUnloadingWithConcurrentMark`) ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值