排查Java应用程序占用的内存出现了泄露的迹象,那么我们一般采用下面的步骤分析:
- 把Java应用程序使用的heap dump下来
- 使用Java heap分析工具,找出内存占用超出预期(一般是因为数量太多)的嫌疑对象
- 必要时,需要分析嫌疑对象和其他对象的引用关系。
- 查看程序的源代码,找出嫌疑对象数量过多的原因
-
Linux命令
ps ----------: 查看进程:ps -ef | grep java 查看进程下的所有线程:ps -T -p [pid] top查看java进程的内存和cpu占用情况 top -p [pid]的命令来查看指定进程占用系统资源的情况 top -H -p 2813 (top -Hp 2813)查看进程下所有的子线程status s表示休眠 pmap ----------: pmap查看进程内存: pmap PID 第一列:内存块起始地址 第二列:内存占用大小 第三列:权限 第四列:内存名称, 其中【anon】表示动态分配的内存,【stack】表示栈内存 另外最后一行会显示内存占用总量,不过是虚拟内存大小,物理内存通过top看 cat ----------: cat /proc/{pid}/status 这个status文件存放了关于当前进程所有相关的信息
-
调用java自带工具
dump heapjmap ----------: 通过jmap可以查看某个Java进程中每一个对象的有多少实例,占用多少内存 jmap -histo PID 第一列:序号,不用管 第二列:对象实例数量 第三列:对象实例占用总内存数,单位字节 第四列:对象实例名称 最后一行,总实例数量与内存占用总数 jmap -histo pid |more 来看看那些对象大量存在回收不掉。 除此之外,也有可能是某些资源链接问题,比如缓存连接,数据库连接 耗尽,导致应用等待 jmap -histo:live [pid] 来查看进程下各种类型的对象创建了多少个,以及每种对象占用内存的情况; 通过仔细观察上面的输出结果,不难看出,哪一种类型的对象占用内存较多,结合业务应用系统,不难排查问题出处 可以通过jmap命令生成dump文件,使用eclipse的分析插件来分析此文件,查看更多详情信息; 可以通过jhat命令来创建一个http服务,通过浏览器来访问服务器查看dump文件详情 jmap -dump:format=b,file=heap.bin <pid> format=b的含义是,dump出来的文件时二进制格式。 file-heap.bin的含义是,dump出来的文件名是heap.bin。 <pid>就是JVM的进程号。 (在linux下)先执行ps aux | grep java,找到JVM的pid;然后再执行jmap -dump:format=b,file=heap.bin <pid>,得到heap dump文件 jps ----------: jps #显示所有java程序和线程ID jps -m #输出main method的参数 jps -l #输出完全的包名,应用主类名,jar的完全路径名 jps -v #输出jvm参数 jstack ----------: jstack pid |grep tid -A 30 jstack pid 查看该线程堆栈信息,看看线程是不是都堵住了,可以轻松定位到函数 pid 是进程ID tid 是线程ID -A 30 表示显示最后30行 jstack -l pid 查看为pid的堆栈信息快照, jstack -l pid > info.txt 输出txt文件 more info.txt grep 'extracme' info.txt 在info.txt文件中查找“extracme” jstat查看GC ----------: jstat -gcutil pid 1000 查看GC的情况,每隔1秒钟输出一次;如果发现是因为大量FULL GC造成程序执行缓慢的话,就要接着查看到底是程序的哪些部分占用的 S0 -Heap上的Survivor space 0区已使用空间的百分比 S1 -Heap上的Survivor space 1区已使用空间的百分比 E -Heap上Eden space区已使用空间的百分比 O -Heap上的Old space区已使用空间的百分比,达到100%,就是内存溢出了 P -Perm space区已使用空间的百分比,达到100%,就是内存溢出了 YGC -从应用程序启动到采样时发生Yang GC 的次数 YGCT -从应用程序启动到采样时Yang GC所用的时间【单位秒】 FGC -从应用程序启动到采样时Full GC的次数 FGCT -从应用程序启动到采样时Full GC所用的时间 GCT -从应用程序启动到采样时用于垃圾回收的总时间【单位秒】 ps -mp pid -o THREAD,tid,time 查询所有线程列表
-
其他工具
JVM参数调优
(1)设置堆内存最大最小值相同,-Xmx与-Xms值相同,这样可以避免堆收缩提升效率
(2)设置年轻代与老年代的内存占用比例-PremRadio参数为1:2,也可以针对年轻代设置,比如将-Newsize与-MaxNewsize设置相同的值,也是为了避免堆收缩
(3)如果服务器物理内存资源充足,可以尝试设置回收方式,默认是Serio,可以设置为-UseParalleOldGC,提升回收并行度