性能文章>记一次使用VJMap排查频繁YGC的经历>

记一次使用VJMap排查频繁YGC的经历原创

3年前
774236

VJMap概述

分代版的jmap(新生代,存活区,老生代),是排查内存缓慢泄露,老生代增长过快原因的利器。因为jmap -histo PID 打印的是整个Heap的对象统计信息,而为了定位上面的问题,我们需要专门查看OldGen对象,和Survivor区大龄对象的工具。

注意事项

  • 只支持CMS和ParallelGC,不支持G1。
  • vjmap在执行过程中,会完全停止应用一段时间,必须摘流量执行!!!!
  • vjmap使用的java为JAVA_HOME/bin/java, 需要至少JDK7,且与目标应用的JVM使用相同的JDK大版本。
  • vjmap需要依赖JAVA_HOME/lib/sa-jdi.jar
  • 需要root权限 (sudo -E vjmap.sh …,),权限与jmap -heap pid相同.如果无法联通进程时,可尝试执行jstack -F pid, jmap -heap pid 自行比对。如果在容器中运行,需要打开ptrace权限。

频繁YGC排查实践

现在有一个目标进程,一直在频繁的ygc,我们尝试使用VJmap来排查具体的问题原因,现象如下所示。
1.png

1.借助XPocket来使用VJMap

2.png

2.查看年轻代的内存使用情况,使用vjmap -sur PID以及vjmap -all PID来一起排查

多次查看sur区的占用情况,如下所示。
3.png

多次查看整个堆内存以及分代统计后的内存占用情况,如下所示
4.png

2.分析结论

根据VJMap,我们很容易就能注意到一个异常情况,一直存在char数组的内存分配,不管是否存在问题,我们可以带着疑问来进行进一步的分析

3.结合PerfMa的HeapDump社区产品进行dump文件分析

3.1 使用jmap -dump:format=b,file=fileName pid 的方式dump目标进程,得到dump文件。

3.2 将dump文件上传至社区产品Xelephant进行离线分析,得出结果,我们可以很直观的看见,在对象视图中,char数组的自身大小明显存在异常,如下图所示。
5.png

3.3 查看对象被引用,得出char数组在哪一个对象内进行分配,如下图所示。
6.png

3.4 查看源码,即可很直观的发现问题,程序内存在频繁分配对象的情况,存在一个死循环在不断的分配对象,对象内部又会分配一个char数组,至此,问题根源已经付出水面,如下图所示。
7.png
8.png

4.官方最佳实践

https://mp.weixin.qq.com/s/6cJ5JuEgEWmMBzJFBDsSMg

点赞收藏
小邋遢

持续进步

请先登录,查看3条精彩评论吧
快去登录吧,你将获得
  • 浏览更多精彩评论
  • 和开发者讨论交流,共同进步
6
3