当我们运行java程序时,发现程序不动,但又不知道是哪里出问题时,可能是OutOfMemoryError,内存不足;内存泄露;锁争用(LockContention);Java进程消耗CPU过高;死循环、线程阻塞、死锁等问题时,java自带的工具可以帮助找到一些问题。
jps主要用来输出JVM中运行的进程状态信息。语法格式如下:
jps [options] [hostid]
如果不指定hostid就默认为当前主机或服务器。 命令行参数选项说明如下:
-q 不输出类名、Jar名和传入main方法的参数
-m 输出传入main方法的参数
-l 输出main类或Jar的全限名
-v 输出传入JVM的参数
是用于监视虚拟机各种运行状态信息的命令行工具。它可以显示本地或远程虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据,在没有GUI图形界面,只是提供了纯文本控制台环境的服务器上,它将是运行期定位虚拟机性能问题的首选工具。
jstat命令格式:jstat [option vmid [ interval[s|ms] [count] ] ]
对于命令格式中的VMID与LVMID需要也别说明一下:如果是本地虚拟机进程,VMID与LVMID是一致的。如果是远程虚拟机进程,那VMID的格式应当是:
[protocol:] [//] lvmid [@hostname [:port]/servername]
参数interval和count代表查询间隔和次数,如果省略这两个参数,说明只查询一次。假设需要每250毫秒查询一次进程ID为2764的垃圾收集状况,一共查询20次,那命令应当是:
jstat –gc 2764 250 20
选项option代表着用户希望查询的虚拟机信息,主要分为3类:类装载、垃圾收集、运行期编译状况,具体选项作用请参考以下表格描述:
选项
选项
作用
-class 监视类装载,卸载数量、总空间以及类装载所耗费的时间
-gc 监视Java堆情况,包括Eden区、两个survivor区、老年代、永久代等的容量、已用空间、GC时间合计等信息
-gccapacity 监视内容与-gc基本相同,但输出主要关注Java堆各个区域使用到的最大、最小空间
-gcutil 监视内容与-gc基本相同,但输出主要关注已使用空间占总空间的百分比
-gccause 与-gcutil功能一样,但是会额外输出导致上一次GC产生的原因
-gcnew 监视新生代GC情况
-gcnewcapacity 监视内容与-gcnew基本相同,输出主要关注使用到的最大、最小空间
-gcold 监视老年代GC状况
-gcoldcapacity 监视内容与-gcold基本相同,输出主要关注使用到的最大、最小空间
-gcpermcapacity 输出永久代使用到的最大、最小空间
-compiler 输出JIT编译器编译过的方法、耗时等信息
-printcompilation 输出已经被JIT编译的方法
jstat执行样例:
[root@WC01 bin 17:59 #35]$ jstat -gcutil 3850
S0 S1 E O P YGC YGCT FGC FGCT GCT
0.00 50.00 71.32 42.89 50.56 639 1.727 5 0.327 2.054
S0、S1表示Survivor1、Survivor2,分别使用了0%和50%的空间;
E表示Eden区,使用了71.32%的空间;
O表示老年代Old区,使用了42.89%的空间;
P表示永久代Pernament区,使用了50.56的空间;
YGC表示执行Minor GC的次数,一共执行了639次;
YGCT表示执行Minor GC的总耗时为1.727秒
FGC表示执行Full GC的次数,一共执行了5次;
FGCT表示执行Full GC的总耗时为0.327秒;
GCT表示所有GC总耗时为2.054秒。
jinfo(Configuration Info for Java)的作用是实时地查看和调整虚拟机各项参数。
jinfo命令格式:jinfo [option] pid
其中option选项可参考一下描述:
选项
作用
-flag 输出指定虚拟机参数,如jinfo -flag MaxHeapSize pid
-sysprops 输出虚拟机进程的System.getProperties()的内容
-flag[+|-] name 修改虚拟机参数值
-flag nam=value 同上
注:JDK1.6中,jinfo对于Windows平台功能仍然有较大的限制,只提供最基本的-flag选择。
jinfo执行样例:
[root@WC01 bin 18:21 #47]$ jinfo -flag MaxHeapSize 3850
-XX:MaxHeapSize=492830720
jmap用来查看堆内存使用状况,一般结合jhat使用。 jmap语法格式如下:
jmap [option] pid
jmap [option] executable core
jmap [option] [server-id@]remote-hostname-or-ip
如果运行在64位JVM上,可能需要指定-J-d64命令选项参数。
jmap -permstat pid打印进程的类加载器和类加载器加载的持久代对象信息,输出:类加载器名称、对象是否存活(不可靠)、对象地址、父类加载器、已加载的类大小等信息
jmap -heap pid 查看进程堆内存使用情况,包括使用的GC算法、堆配置参数和各代中堆内存使用情况
jmap -heap 21711
使用jmap -histo[:live] pid查看堆内存中的对象数目、大小统计直方图,如果带上live则只统计活对象,如下:
jmap -histo:live 21711 | more
jstack主要用来查看某个Java进程内的线程堆栈信息。语法格式如下:
jstack [option] pid
jstack [option] executable core
jstack [option] [server-id@]remote-hostname-or-ip
命令行参数选项说明如下:
-l long listings,会打印出额外的锁信息,在发生死锁时可以用jstack -l pid来观察锁持有情况
-m mixed mode,不仅会输出Java堆栈信息,还会输出C/C++堆栈信息(比如Native方法)
jstack可以定位到线程堆栈,用到的命令有ps、top、printf、jstack、grep。
windows环境下:
打开cmd,输入jps命令,jps很简单可以直接显示java进程的pid,假设 xxxx
接下来:jstack xxxx 就可以了,nid就是线程的ID
Jstack -l PID >> 123.txt 表示 输出到123这个文件下面
在cmd控制台输入pslist,如果命令不被识别,则表示当前电脑上没有安装pslist这个工具,可以到windows官方网站: https://technet.microsoft.com/en-us/sysinternals/bb896682.aspx 下载,下载完成后将其解压到C:\Windows\System32路径下即可使用,或者将其配置到环境变量中亦可。
pslist -dmx 8848 > 8848_pslist.txt
Linux环境下:假设应用名称xxx
root@ubuntu:/# ps -ef | grep xxx | grep -v grep
root 21452 1 1 14:47 pts/3 00:02:10 java -jar xxx.jar
得到进程ID为21452,第二步找出该进程内最耗费CPU的线程,可以使用ps -Lfp pid或者ps -mp pid -o THREAD, tid, time或者top -Hp pid
printf "%x\n" 21742
得到21742的十六进制值为54ee,然后去定位最费CPU的线程
root@ubuntu:/# jstack 21452 | grep 54ee
这两个工具都是JDK自带的监控java程序的工具,可以监控本地进程和远程进程。jvisualvm提供的信息更多一点。 直接在cmd控制台输入jconsole和jvisualvm就可以调出这两个工具。
网上找到这个程序 ,解压 打开运行 ,找到正在执行的pid 查看,即可看到哪个线程消耗的内存多。 将CPU利用率高的线程ID 10728(10进制)转换为0x29E8(16进制)
导出dump文件命令:
jstack 8148 >> d://123.txt
然后 去123.txt文件下面去找0x29E8 0x3094相关内容
"ContainerBackgroundProcessor[StandardEngine[Catalina]]" #14 daemon prio=5 os_prio=0 tid=0x000000001a655800 nid=0x29e8 waiting on condition [0x000000001c28f000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1509)
at java.lang.Thread.run(Thread.java:745)
Locked ownable synchronizers:
- None
"VM Periodic Task Thread" os_prio=2 tid=0x0000000018e1c000 nid=0x3094 waiting on condition
Wait on condition的常见情况是该线程在 sleep,等待 sleep的时间到了时候,将被唤醒。
0x29e8 这个线程通过proess explorer跟踪发现每隔10秒进行一次,估计是个定时任务。占用CPU比较高。 0x3094这个线程通过proess explorer跟踪发现 一直存在。