一、JDK命令行工具简介
所有的java开发人员都知道JDK的bin目录下存放着编译java需要的javac,以及运行java程序需要的java这两个命令工具,但是很多人并没有注意到,其实除了这两个工具,该目录下还有很多工具,这些工具其实为我们提供了很多方便且强大的功能,windows7系统64位jdk1.7/bin目录下部分截图:
下面是命令行监控的主要工具和用途:
名称???? |
作用 |
jps |
JVM Process Status Tool,现实指定系统内所有的HotSpot虚拟机进程? |
jstat |
JVM Statistics Monitoring Tool,用于收集Hotspot虚拟机各个方面的运行参数? |
jinfo |
Configuration Info for Java,现实虚拟机配置信息 |
jmap |
Memory map for java,生成虚拟机的内存转储快照 |
jhat |
JVM heap Dunp Browser,用于分析heapdump文件,他会建立一个HTTP/HTML服务,让用户可通过浏览器查看? |
jstack |
Stack Track for java ,显示虚拟机线程快照 |
1、jps
? ? jps用来查看基于HotSpot的JVM里面中,所有具有访问权限的Java进程的具体状态, 包括进程ID,进程启动的路径及启动参数等等,与unix上的ps类似,只不过jps是用来显示java进程,可以把jps理解为ps的一个子集。?使用jps时,如果没有指定hostid,它只会显示本地环境中所有的Java进程;如果指定了hostid,它就会显示指定hostid上面的java进程,不过这需要远程服务上开启了jstatd服务,可以参看前面的jstatd章节来启动jstad服务。
命令格式 :jps [ options ] [ hostid ]?
参数说明 :
-q 忽略输出的类名、Jar名以及传递给main方法的参数,只输出pid。
-m 输出传递给main方法的参数,如果是内嵌的JVM则输出为null。
-l 输出应用程序主类的完整包名,或者是应用程序JAR文件的完整路径。
-v 输出传给JVM的参数。
-V 输出通过标记的文件传递给JVM的参数(.hotspotrc文件,或者是通过参数-XX:Flags=<filename>指定的文件)。
-J 用于传递jvm选项到由javac调用的java加载器中,例如,“-J-Xms48m”将把启动内存设置为48M,使用-J选项可以非常方便的向基于Java的开发的底层虚拟机应用程序传递参数。下面样例均在linux的jdk1.7下测试。
使用样例:
[root@tools138 ~]# jps
2897 Bootstrap
22558 Jps
[root@tools138 ~]# jps -l
2897 org.apache.catalina.startup.Bootstrap
22568 sun.tools.jps.Jps
[root@tools138 ~]# jps -v
2897 Bootstrap -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.endorsed.dirs=/usr/local/tomcat/endorsed -Dcatalina.base=/usr/local/tomcat -Dcatalina.home=/usr/local/tomcat -Djava.io.tmpdir=/usr/local/tomcat/temp
22578 Jps -Denv.class.path=/usr/java/jdk1.7.0/lib -Dapplication.home=/usr/java/jdk1.7.0 -Xms8m
?
2、jstat
Jstat用于监控基于HotSpot的JVM,对其堆的使用情况进行实时的命令行的统计,使用jstat我们可以对指定的JVM做如下监控:
- 类的加载及卸载情况
- 查看新生代、老生代及持久代的容量及使用情况
- 查看新生代、老生代及持久代的垃圾收集情况,包括垃圾回收的次数及垃圾回收所占用的时间
- 查看新生代中Eden区及Survior区中容量及分配情况等
jstat工具特别强大,它有众多的可选项,通过提供多种不同的监控维度,使我们可以从不同的维度来了解到当前JVM堆的使用情况。详细查看堆内各个部分的使用量,使用的时候必须加上待统计的Java进程号,可选的不同维度参数以及可选的统计频率参数。
命令格式:
jstat [ option vmid [interval][s|ms][count]]
option 参数如下面表格
interval 和count 代表查询次数和间隔。
使用样例:
[root@tools138 ~]# jstat -class 2897
Loaded ?Bytes ?Unloaded ?Bytes ? ? Time ?
?67431 113866.2 ? ?59850 98607.5 ? ?1884.07
?
[root@tools138 ~]# jstat -compiler ?2897
Compiled Failed Invalid ? Time ? FailedType FailedMethod
? ? 3782 ? ? ?1 ? ? ? 0 ? 507.88 ? ? ? ? ?1 org/apache/tomcat/util/IntrospectionUtils setProperty
?表示查询系统进程为2897的java程序gc,每100毫秒查询一次,一共查询十次,显示结果每列的含义如下:?
列名
说明
S0C |
新生代中Survivor space中S0当前容量的大小(KB) |
S1C |
新生代中Survivor space中S1当前容量的大小(KB) |
S0U |
新生代中Survivor space中S0容量使用的大小(KB) |
S1U |
新生代中Survivor space中S1容量使用的大小(KB) |
EC |
Eden space当前容量的大小(KB) |
EU |
Eden space容量使用的大小(KB) |
OC |
Old space当前容量的大小(KB) |
OU |
Old space使用容量的大小(KB) |
PC |
Permanent space当前容量的大小(KB) |
PU |
Permanent space使用容量的大小(KB) |
YGC |
从应用程序启动到采样时发生 Young GC 的次数 |
YGCT |
从应用程序启动到采样时 Young GC 所用的时间(秒) |
FGC |
从应用程序启动到采样时发生 Full GC 的次数 |
FGCT |
从应用程序启动到采样时 Full GC 所用的时间(秒) |
GCT |
T从应用程序启动到采样时用于垃圾回收的总时间(单位秒),它的值等于YGC+FGC |
其他以gc开始的结果列跟gc选项结果列基本一样,这里不一一列举了。
?
3、jinfo
jinfo可以输出并修改运行时的java 进程的opts。用处比较简单,用于输出JAVA系统参数及命令行参数。
命令格式:
jinfo [option] pid
使用样例:
[root@tools138 ~]# jinfo ?-flag ?MaxNewSize ?2897
-XX:MaxNewSize=18446744073709486080
?
4、jmap
jmap用于生成堆转储快照(一般称为heapdump或者dump文件)。当然也可其他方法比如加参数-XX:+HeapDumpOnOutOfMemoryError参数,在虚拟机OOM异常的之后自动生成dump文件,也可以通过-XX:+HeapDumpOnCtrlBreak参数则可以使用Ctrl+Break键让虚拟机生成dump文件。在前文《?JAVA虚拟机之3:CMS垃圾收集器》测试中就有生成。dump文件生成后可借助jha、MAT(?Eclipse Memory Analyzer tool)、IBM HeapAnalyzer来对dump分析。jmap不仅能获取dump还可以查询finalize执行队列,java堆和永久代详细信息,空间使用率,当前用的是什么收集器等。
jmap -J-d64 -heap pid
命令格式:
? ? ? ?jmap [ option ] pid
参数说明:
-dump:[live,]format=b,file=<filename> 使用hprof二进制形式,输出jvm的heap内容到文件=. live子选项是可选的,假如指定live选项,那么只输出活的对象到文件.
-finalizerinfo 打印正等候回收的对象的信息.
-heap 打印heap的概要信息,GC使用的算法,heap的配置及wise heap的使用情况.
-histo[:live] 打印每个class的实例数目,内存占用,类全名信息. VM的内部类名字开头会加上前缀”*”. 如果live子参数加上后,只统计活的对象数量.
-permstat 打印classload和jvm heap长久层的信息. 包含每个classloader的名字,活泼性,地址,父classloader和加载的class数量. 另外,内部String的数量和占用内存数也会打印出来.
-F 强迫.在pid没有相应的时候使用-dump或者-histo参数. 在这个模式下,live子参数无效.
使用样例:
jmap -dump:format=b,file=eclipse.bin
[root@tools138 ~]# jmap -dump:format=b,file=eclipse.bin ?2897
Dumping heap to /root/eclipse.bin ...
Heap dump file created
?
5、jhat
jhat是sun提供的dump分析工具,上面讲过分析dump的工具还有MAT(?Eclipse Memory Analyzer tool)、IBM HeapAnalyzer等,一般这个命令不太用到,是因为分析dump是个既耗时又耗机器资源的过程,第二个原因是这个工具比较简陋,没有MAT(?Eclipse Memory Analyzer tool)、IBM HeapAnalyzer这些专业和强大。
命令格式:
jhat file
使用样例:
防止影响服务,所以在本地windows下使用,先导出dump文件
C:\Users\hz>jmap?-dump:format=b,file=test.bin?5152
Dumping?heap?to?C:\Users\hz\test.bin?...
Heap?dump?file?created
然后分析:
C:\Users\hz>jhat?test.bin
Reading?from?test.bin...
Dump?file?created?Wed?Dec?30?13:29:19?CST?2015
Snapshot?read,?resolving...
Resolving?9692?objects...
Chasing?references,?expect?1?dots.
Eliminating?duplicate?references.
Snapshot?resolved.
Started?HTTP?server?on?port?7000
Server?is?ready.
载在浏览器中输入localhost:7000查看结果,如下图。
?
6、jstack
jstack用于打印出给定的java进程ID或core file或远程调试服务的Java堆栈信息,如果是在64位机器上,需要指定选项"-J-d64",Windows的jstack使用方式只支持以下的这种方式:
如果java程序崩溃生成core文件,jstack工具可以用来获得core文件的java stack和native stack的信息,从而可以轻松地知道java程序是如何崩溃和在程序何处发生问题。另外,jstack工具还可以附属到正在运行的java程序中,看到当时运行的java程序的java stack和native stack的信息, 如果现在运行的java程序呈现hung的状态,jstack是非常有用的。?
命令格式 :
jstack [ option ] pid
参数说明:
-F当’jstack [-l] pid’没有相应的时候强制打印栈信息
-l长列表. 打印关于锁的附加信息,例如属于java.util.concurrent的ownable synchronizers列表.
-m打印java和native c/c++框架的所有栈信息.
使用样例:
[root@tts217 ~]# jstack -l 29984
.....
?
"main" prio=10 tid=0x00007fe648009000 nid=0x7521 runnable [0x00007fe64e753000]
? ?java.lang.Thread.State: RUNNABLE
?at java.net.PlainSocketImpl.socketAccept(Native Method)
?at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:398)
?at java.net.ServerSocket.implAccept(ServerSocket.java:530)
?at java.net.ServerSocket.accept(ServerSocket.java:498)
?at org.apache.catalina.core.StandardServer.await(StandardServer.java:453)
?at org.apache.catalina.startup.Catalina.await(Catalina.java:777)
?at org.apache.catalina.startup.Catalina.start(Catalina.java:723)
?at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
?at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
?at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
?at java.lang.reflect.Method.invoke(Method.java:606)
?at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:321)
?at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:455)
?
? ?Locked ownable synchronizers:
?- None
?
"VM Thread" prio=10 tid=0x00007fe64806a800 nid=0x7522 runnable
?
"VM Periodic Task Thread" prio=10 tid=0x00007fe6480a5800 nid=0x7529 waiting on condition
?
JNI global references: 238
?
二、JDK可视化工具
1、jconsole
JConsole是一个基于JMX的GUI工具,用于连接正在运行的JVM,不过此JVM需要使用可管理的模式启动。如果要把一个应用以可管理的形式启动,可以在启动是设置com.sun.management.jmxremote。
jconsole可以选择本地连接,来查看本地java程序参数,也可以连接远程机器来使用,下面连接本地看:
a、概述:有关堆内存使用情况、线程、类加载和CPU使用情况的综述。如下图所示:
?b、内存:堆内存和其他内存。如下图所示:
?c、线程:峰值/活动线程,在此页面可以查看到各个线程的明细,也可以进行死锁检测。如下图所示:
?d、类:监控加载和卸载的类,这个需要综合其他工具进行具体的分析。
e、VM摘要:有关JVM的明细信息。
f、Mbean:当前Java程序的Mbean的操作。
在jconsole里主要可以用来监控内存和线程监控,内存监控相当于jstat,曲线可以选择
?可以手动执行gc。线程监控可用来检测死锁。
死锁代码如下:
package jvm;
/**
* 描述:
*
* @author alaric 2016年1月1日 上午12:43:23
*/
public class A implements Runnable {
int a, b;
public A(int a, int b) {
this.a = a;
this.b = b;
}
/*
* (non-Javadoc)
*
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
// 描述
synchronized (Integer.valueOf(a)) {
synchronized (Integer.valueOf(b)) {
System.out.println(" a + b = " + (a + b));
}
}
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(new A(1, 2)).start();
new Thread(new A(2, 1)).start();
}
}
}
多运行几次会出现死锁,程序会阻塞。然后用线程监控,点击检测死锁,发现Thread-199和Thread-198相互等待释放Integer.value(1)或者Integer.value(2)。因为在200次的代码执行中Integer.value()就返回了两个对象。
?
2、jvisualVM
jvisualVM所谓多合一虚拟机故障处理工具,有强大的插件扩展功能,通过安装插件扩展支持,jvisualVM可以做到:
a、显示虚拟机进程及进程的配置和环境信息(jps,jinfo);
b、监视应用程序CPU、GC、堆、方法区及线程的信息(jstat、jstack);
c、dump及分析堆转储快照(jmap、jhat);
d、方法级的程序性能分析,找出调用最多,运行时间最长的方法;
.....其它通过插件可以做到的;
概述里面可以看到虚拟机版本及配置的参数等。
?在监视里可以看cpu、堆、线程类的相关数据。可以执行垃圾回收和dump堆。
?在线程里可以看到所有线程,包括运行的、休眠的、等待的、驻留的等,包括运行时间。同时可以dump线程。
?在抽样器中可以监控到每个方法执行的时间,还可以对方法过滤。点击线程cpu时间,可以看到每个线程cpu时间。
?VisualGC这里可以看到虚拟机运行时每个区域的容量大小,已占用的大小,youngGC和fullGC的次数,以及编译时间、类加载数量和加载时间等。
?
三、总结:
jdk提供的vm故障处理工具都比较实用,常用的jps,jstat,jmap,jstack以及可视化工具visualvm,当然根据个人实际实用情况,可能还选用第三方的工具进行dump分析,如eclipse的MAT(Memory Analyzer Tool)等。灵活实用这些工具,可以给处理问题带来很大的便利。
JAVA虚拟机之六:虚拟机性能监控和故障处理工具
原文:http://alaric.iteye.com/blog/2268015