微信号:gh_5d09761c59df

介绍:开测是以技术开放的心态,提供给中小开发者一个快捷完整的自动测试系统。

一次JVM内存泄漏排查过程

2019-06-14 12:05 opentest

背景

近期发现一个java进程内存占用久高不下,重启后恢复,一段时间后又复现。

排查过程

1.通过top命令找到内存占用最高进程的ID;

2.通过ps命令找到程序启动命令行:

java
-Xms1024m
-Xmx1024m
-XX:NewSize=256m
-XX:MaxNewSize=256m
-XX:PermSize=64m

// 设置持久代最大值
-XX:MaxPermSize=128m

// 使用CMS内存收集
-XX:+UseConcMarkSweepGC

// 降低标记停顿
-XX:+CMSParallelRemarkEnabled

// 在FULL GC的时候, 对年老代的压缩, CMS是不会移动内存的,
// 因此, 这个非常容易产生碎片, 导致内存不够用, 所以, 内存的压缩这个时候就会被启用。
// 增加这个参数是个好习惯。可能会影响性能,但是可以消除碎片
-XX:+UseCMSCompactAtFullCollection

// 内存页的大小不可设置过大, 会影响Perm的大小
-XX:LargePageSizeInBytes=128m

// 原始类型的快速优化
-XX:+UseFastAccessorMethods

// 使用手动定义初始化定义开始CMS收集,禁止hostspot自行触发CMS GC
-XX:+UseCMSInitiatingOccupancyOnly

// 使用cms作为垃圾回收使用70%后开始CMS收集
-XX:CMSInitiatingOccupancyFraction=70

// 调试使用,gc日志输出的相关参数
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-XX:+PrintHeapAtGC
-Xloggc:gc.log
-server -jar XXXXX-jar-with-dependencies.jar production

3.在命令行中加上gc日志输出的参数(如上图中橙色部分)

4.通过gc日志,查看GC效果,每个代的内存变化规律:

前期Minor GC较为频繁,老年代和永久带内存占用不断增加,直到触发CMS,且老年代与永久代的内存占用没有明显的减少。


初步诊断:

有对象没有正常被回收。

5. 通过jmap命令,查看进程堆栈中对象的分布:

/**

 * 3296是进程id

 * > test-jmap.txt 将jmap命令的结果重定向至test-jmap.txt

 * 

 * 找出进程所有对象

 */

jmap -histo 3296 > test-jmap.txt

/**

 * 找出进程中目前还live的对象

 */

jmap -histo:live 3296 > test-jmap.txt

如图中显示:包名pdown的对象大量出现,怀疑是该包内某个对象内存泄漏;

pdown是第三方提供的jar包,通过jd-gui反编译工具,排查代码发现其中一个Task对象在每次创建后放入队列,只有在unInit时,才会移除,且该队列属于一个常量对象,所以基本判定是由于jar包使用过程中未调用该api导致本次内存泄漏,从而GC频繁。

6. 修改程序代码,加上pdown 的 unInit后,该问题解决。


总结

1. 什么样的java对象可以被回收?

java使用可达性分析的方式,从GC root开始,根据引用关系遍历,所经过的路径形成一棵引用树,没有挂在这棵树上的对象,为不可达对象,可以被回收。

GC root包括

2. CMS(Concurrent Mark Sweep)收集器

—— ——特点—— ——
●针对老年代
●标记-清除算法 (不进行压缩操作,产生内存碎片)

●并发

●多线程

●收集过程中不需要暂停用户线程

●以获取最短回收停顿时间为目标


应用场景:

ParNew + CMS + Serial Old(Concurrent Mode Failure后备预案)与用户交互较多的场景。

例如:互联网或者B/S系统的服务端

参数:

-XX:+UseConcMarkSweepGC:使用CMS收集器

-XX:+ UseCMSCompactAtFullCollection:Full GC后,进行一次碎片整理;整理过程是独占的,会引起停顿时间变长

-XX:+CMSFullGCsBeforeCompaction:设置进行几次Full GC后,进行一次碎片整理

-XX:ParallelCMSThreads:设定CMS的线程数量(一般情况约等于可用CPU数量)

缺点:

对CPU资源非常敏感

浮动垃圾

"Concurrent Mode Failure"失败

内存碎片

诚聘精英

JOIN US

想加入我们吗?点击下方蓝色字体进行了解

高级测试开发工程师

高级服务端测试工程师

测试开发工程师 - AI算法工程师







长按二维码,关注官方微信公众号!


360开测

QQ交流群

保存二维码

再用QQ扫描哟

温馨提示

如果你喜欢本文,请分享到朋友圈,想要获得更多信息,请关注我。




 
开测 更多文章 Scrcpy工具码流格式化 基于Bert迁移学习点击未知弹框 Web服务端推送技术介绍 智能音箱语音交互系统简介与测试初探 360开测-兼容性测试正式上线啦!!!
猜您喜欢 JSPatch更新:完善开发功能模块的能力 国内首家"物联网云医院"上线 “看病难"或将成过去式! 上次是程序员春联,这回是灯谜了 代码整洁之所以重要的七个理由 干货 | Docker容器:如何根据监听端口号查找到对应容器?