一般对于内存泄漏导致OOM的,可以通过MAT在OOM时生成的dump中查看老年代贡献最大的对象,定位问题代码。
但对于老年代缓慢增长FGC又能被回收的,排查会相对麻烦,可以按如下方式进行尝试。
1. 添加GC参数,打出对象分布
-XX:+PrintTenuringDistribution
2022-03-31T19:54:17.891+0800: 7446.946: [GC (Allocation Failure) 2022-03-31T19:54:17.892+0800: 7446.946: [ParNew Desired survivor size 751599616 bytes, new threshold 10 (max 10) - age 1: 20029920 bytes, 20029920 total - age 2: 3097184 bytes, 23127104 total - age 3: 4769904 bytes, 27897008 total - age 4: 2000296 bytes, 29897304 total - age 5: 5371680 bytes, 35268984 total - age 6: 732136 bytes, 36001120 total - age 7: 2503944 bytes, 38505064 total - age 8: 1614288 bytes, 40119352 total - age 9: 726808 bytes, 40846160 total - age 10: 1219032 bytes, 42065192 total : 11804946K->61651K(13212096K), 0.1111841 secs] 18153507K->6410815K(25795008K), 0.1119925 secs] [Times: user=1.25 sys=0.01, real=0.11 secs]
2. 根据"new threshold" 关键词查看是否有提前晋升到老年代的
本case中没有,都是与MaxTenuringThreshold=10相同的, 故没有大对象都是按照常规流程多次YGC后晋升到老年代的。
3. 查看age=10(10为自定义或默认的 MaxTenuringThreshold)中的对象(这些都是即将晋升到老年代的)
可以使用工具 vjmap 查看( https://github.com/vipshop/vjtools/tree/master/vjmap )
./vjmap.sh -sur:age=10 <PID> > /tmp/histo-sur-10_0331_1015.log
4. 定位问题的代码位置
在上述文件中找排在前面的业务代码相关的类,如上述case中的 io.dropwizard.metrics5.WeightedSnapshot$WeightedSample,com.xxx.soa.caravan.ribbon.Server,credis.java.client.pool.impl.CRedisJedis
再在代码中梳理相关逻辑,看看哪里会产生这些对象,评估可能的点。