一、JDK自带的调试工具
jdk自带调试工具,在产线环境恶劣的情况下,比如内网隔离,传输信息困难,难以拿到本地调试,没有window环境,初步检查系统的情况下使用。基本工具有:
- jps
- jinfo
- jstat(常用,初步查看内存状态)
- jmap(常用,看java堆情况,解决内存溢出)
- jhat
- jstack(常用,看线程池情况)
jps
jsp查看java虚拟机的列表。和ps -ef类似
使用:
- jps -l
jinfo
jinfo查看java虚拟机的参数配置。
使用:
- jinfo pid
jstat
jstat查看gc情况和内存中类的信息
使用:
- jstat -gc pid 5000 1000
C表示总数,U表示used,单位KB
其中S0表示survivor 0,S1表示survivor 1,E表示eden,O表示old老年代,P表示Perm,YGC表示younggc的次数,YGCT表示younggc的总耗时,FGC表示fullgc的次数,FGCT表示fullgc总耗时,GCT表示gc的总耗时。 - jstat -gcutil pid 5000 1000
gcutil和gc差不多,只不过不是具体的内存数值,而是占比,内涵和gc类似 - jstack -class pid 5000 1000
class展示类的加载信息
jmap
jmap是一个重要的工具,查看内存详细信息,可以dump到文件中
使用:
- jmap [-F] -dump:live,format=b,file=/tmp/a pid
-F 表示强制执行,live表示收集存活的对象,file存储到某个文件。dump文件下来后,可以使用工具来分析堆内存,包括jmap -histo、mat等 - jmap [-F] -histo pid
查看堆内存的情况,按照对象数和对象占用的内存排队,可以初步定位到是哪个对象占用过多内存,内存泄漏的地方。后面使用mat工具能分析到哪个来存储的这个对象,也就是GCroot在哪 - jmap [-F] heap pid
heap能查看当前使用的垃圾收集器是什么和一些参数策略,还有具体的内存分布,一般用不到。参数可以用jinfo,内存分布可以用jstat
jhat
jhat会分析一个dump文件,然后把结果发布到一个html服务器上,有一定的用途,html也是主要看histogram。和我们的jmap -histo功能类似,所以楼主觉得用处不大。
使用:
- jhat file
返回访问127.0.0.1:7000 查看histogram
jstack
jstack是比较有用的一个命令,查看线程的情况,包含锁,俗称javacore
使用:
- jstack [-F] [-l] pid
-l包含锁信息
二、外部工具
除了jdk自带命令工具,我们还可以使用外部界面调试,jconsole和jvisualvm也是jdk自带的。
- jconsole
- jvisualvm
- mat
jconsole
查看jvm的内存,cpu信息,线程,参数,类信息
jvisualvm
是一个比较好用的工具,界面功能更强大,界面更友好。
也是监控内存,cpu,线程,类信息和参数的。还可以执行dump和javacore的生成。
如果产线允许的话,可以直接连接到产线发现解决问题。设置远程ip和jmx端口。当然产线的java启动需要设置jmx配置:
-Dcom.sun.management.jmxremote=true
-Dcom.sun.management.jmxremote.port=18080
mat
mat是一个比较强大的分析堆溢出的工具。把之前dump文件导入到工具中。
首先看overview。
有几个比较重要的信息。
1、图中列出的大对象
左击list object->with outgoing references,查看次大对象是哪个GCroot。
shallow heap为本对象大小,retained heap为实际包含的对象的总大小。主要看retained heap,一层一层展开,能够看到哪个类中存在存储大对象。
2、histogram
和jmap -histo和jhat中的类似。
3、dominator tree
查看各个对象的GCroot,和第一个点类似
4、leak suspects
内存泄漏疑点报告,会把可能的内存泄漏点展示,再查看detail,就能看到具体信息。