学习笔记
JDK Tools是随JDK安装包一同发布的,安装JDK后其可执行文件在$JAVA_HOME/bin目录下。JDK Tools中有许多可用于Java程序的性能诊断,包括:jps,jinfo,jmap,jstack,jstat,jconsole等,本文将介绍这些Java自带的性能诊断工具的基本使用。
【注:以下内容以jdk1.6及以上版本为例】
jps
jps。如果把j去掉,则是ps命令,这在linux下是一个显示进程信息的命令,顾名思义,jps是显示计算机上当前用户的所有Java进程信息的命令,jps会打印出机器上所有当前用户的Java进程。
使用格式为:jps [ options ] [ hostid ]
jps的常用参数及其含义如下:
-q 只显示pid,不显示class名称、jar文件名和传递给main方法的参数
-m 输出传递给main 方法的参数,在嵌入式jvm上可能是null
-l 输出应用程序main class的完整package名 或者 应用程序的jar文件完整路径名
-v 输出传递给JVM的参数
参考资料:http://download.oracle.com/javase/6/docs/technotes/tools/share/jps.html
jinfo可打印出一个给定的Java进程、Java core文件或远程Debug服务器的Java配置信息,具体包括Java系统属性和JVM命令行参数。如果给定的进程在64位机器上运行,需要指定相应的配置项,如:jinfo -J-d64 -sysprops pid。
jinfo的使用格式为:
jinfo [ option ] pid
jinfo [ option ] executable core
jinfo [ option ] [server-id@]remote-hostname-or-IP
jinfo常用参数及其含义如下:
<默认>按“属性名=值”的方式打印Java系统配置信息和JVM命令行参数
-flag name 打印属性名为name的命令行参数
-flag [+/-] name设置命令行参数name的bool值
-flag name=value 设置命令行参数name的值为value
-flags 打印所有传递给JVM的命令行参数,与jps –v相似。
-sysprops打印所有Java系统配置信息,如JVM版本、JVM名称、用户语言、操作系统等。
参考资料:http://download.oracle.com/javase/6/docs/technotes/tools/share/jinfo.html
jmap打印给定pid、Java core文件或远程Debug服务器的共享对象的内容映射或堆内存细节。如果给定进程在64位机器上运行,需要指定相应选项:
jmap的使用格式为:
jmap [ option ] pid
jmap [ option ] executable core
jmap [ option ] [server-id@]remote-hostname-or-IP
jmap常用的参数及其含义如下:
<默认>未指定选项时,jmap打印共享对象的映射。对每个目标VM加载的共享对象,其起始地址、映射大小及共享对象文件的完整路径将被打印出来,这有点类似Solaris系统的pmap工具。
-heap打印堆情况的概要信息,包括堆配置,各堆空间的容量、已使用和空闲情况
-histo[:live]打印堆的历史情况。对每一个Java类,打印其对象数,所占字节数,完整类名。JVM内部类以'*'为前缀。如果加入了live选项,则只打印存活的对象。
-permstat打印堆中持久代类加载器相关统计信息。对每个类加载器,打印出它的名字、活跃度、内存地址、父加载器、该类加载器加载的类的数量和大小。
-dump:[live,]format=b,file=<filename>将Java堆信息用hprof二进制格式导出到(Dumps)文件中。 live选项是可选的,带live选项时只打印存活的对象。生成的文件可用jhat(Java Heap Analysis Tool)工具进行分析
-finalizerinfo打印等待调用finalize的对象的信息
-J <flag>给jmap所运行的JVM传递参数
-F 在Java进程没有反应时,强制打印其内存信息
参考资料:http://download.oracle.com/javase/6/docs/technotes/tools/share/jmap.html
jstack打印给定pid、Java core文件或远程Debug服务器的线程堆栈信息。对每一个Java框架,打印其类名、方法名、字节码地址 (byte code index)以及行号。
注:将来的jdk版本可能不再附带jstack工具!
jstack的使用格式为:
jstack [ option ] pid
jstack [ option ] executable core
jstack [ option ] [server-id@]remote-hostname-or-IP
jstack 常用的参数及含义如下
-F在Java进程没有响应时强制打印
-l长列表,打印每个Java线程所持有锁的附加信息
-m混合模式打印,打印包括c++的本地线程栈信息及Java栈信息。
参考资料:http://download.oracle.com/javase/6/docs/technotes/tools/share/jstack.html
jstat能够动态打印jvm(Java Virtual Machine Statistics Monitoring Tool)的相关统计信息。如young gc执行的次数、full gc执行的次数,各个内存分区的空间大小和可使用量等信息。
在认识jstat之前,先来认识一下JVM的内存结构,如下图所示:
JVM内存划分为年轻代(Young)和年老代(Tenured),Young GC是指是针对年轻代中的无用对象进行垃圾回收,而Full GC则会对年轻代和年老代中的无用对象均进行垃圾回收。上图中Virtual为可伸缩部分,即初始可以指定一个内存空间最大值和初始值,随着程序运行空间会进行增长。
Young:年轻代,具体包括Eden、Survivor0、Survivor1;
Eden:初始分配的对象最先存放到这里;
Survivor0和Survivor1:存放Eden中经过若干次Young GC仍存活的对象,Survivor0和Survivor1轮流被使用,当GC执行时,会从其中一个空间中拷贝存活对象到另一空间中。
Tenured:存放Survivor1中经过若干次Young GC仍存活的对象,这里的对象只有Full GC才可能回收;
Perm:存放Java类,常量等静态内容。
jstat的使用格式如下:
jstat [ generalOption | outputOptions vmid [interval[s|ms] [count]] ]
generalOption单一的命令行参数,如-help,-version等
outputOptions一个或多个输出选项,还可以加上-h,-t或-J
vmid JVM标识符,可以是单一的进程号,也可以是远程JVM标识,其通用语法为:
[protocol:][//]lvmid[@hostname[:port]/servername]
interval时间间隔,每两次打印信息之间的时间间隔
count打印次数,在屏幕上打印多少次信息
【注:jstat在将来的jdk版本中可能不被支持,目前的jdk版本中,在win98和windows me平台中不支持】
命令行选项及含义如下:
-help显示帮助信息
-version显示版本信息
-options显示统计信息所有输出选项
如果你没有指定命令行选项,则你可以指定输出内容选项,输出内容选项及其含义如下:
统计类装载器的行为 | |
统计HotSpot Just-in-Time 编译器的行为 | |
统计堆内存gc的行为 | |
统计各代的容易及对应空间 | |
统计垃圾回收信息, 以及引起垃圾回收事件的原因 | |
统计年轻代行为 | |
统计年轻代大小及其对应空间 | |
统计老年代和永久代行为 | |
统计老年代大小 | |
统计永久代大小 | |
垃圾回收情况统计 | |
HotSpot编译方法统计 |
-h n每相隔n行之后,打印一次表头
-t n在输出数据的第一列打印一个timestamp,这个timestamp标示目标JVM运行了多长时间。
-JjavaOption,将JVM参数传递给运行jstat的JVM
各选项的具体打印结果列如下表:
-class
类加载信息统计 | |
列名 | 描述 |
Loaded | 加载的类数量. |
Bytes | 加载的大小. |
Unloaded | 卸载的类数量. |
Bytes | 卸载的大小 |
Time | 类加载与卸载所占用的时间 |
HotSpot JIT 编译器统计 | |
列名 | 描述 |
Compiled | 编译任务数 |
Failed | 失败的编译任务数 |
Invalid | 无效的编译任务数 |
Time | 执行编译任务所占用的时间 |
FailedType | 最近一次编译失败的类型 |
FailedMethod | 最后一次编译失败的类及方法名 |
堆内存gc统计 | |
列名 | 描述 |
S0C | 当前survivor space 0 容量 (KB). |
S1C | 当前survivor space 1 容量 (KB). |
S0U | Survivor space 0 使用量 (KB). |
S1U | Survivor space 1 使用量 (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 | 年轻代GC次数. |
YGCT | 年轻代GC占用的时间 |
FGC | Full GC 次数. |
FGCT | Full GC占用的时间 |
GCT | 垃圾回收占用的总时间 |
内存池代及空间统计 | |
列名 | 描述 |
NGCMN | 年轻代最小容量 (KB). |
NGCMX | 年轻代最大容量(KB). |
NGC | 当前年轻代容量 (KB). |
S0C | 当前 survivor space 0 容量 (KB). |
S1C | 当前 survivor space 1 容量 (KB). |
EC | 当前 eden space 容量 (KB). |
OGCMN | 老年代(old generation)最小容量(KB). |
OGCMX | 老年代(old generation)最大容量(KB). |
OGC | 当前老年代( old generation)容量 (KB). |
OC | 当前 old space 容量 (KB). |
PGCMN | 最小永久代( permanent generation)容量 (KB). |
PGCMX | 最大永久代( Permanent generation)容量 (KB). |
PGC | 当前永久代( Permanent generation) 容量 (KB). |
PC | 当前 (Permanent space)容量 (KB). |
YGC | 年轻代GC次数. |
FGC | Full GC 次数. |
该选项与-gcutil 选项类似,不过多了下面两列信息:
GC统计, 包括GC事件 | |
列名 | 描述 |
LGCC | 最近一次进行GC事件的原因 |
GCC | 触发当前GC事件的原因 |
年轻代统计 | |
列名 | 描述 |
S0C | 当前 survivor space 0 容量 (KB). |
S1C | 当前survivor space 1容量(KB). |
S0U | Survivor space 0 使用量 (KB). |
S1U | Survivor space 1使用量(KB). |
TT | Tenuring 阈值. |
MTT | 最大 tenuring 阈值. |
DSS | Desired survivor size (KB). |
EC | 当前eden space 容量 (KB). |
EU | Eden space 使用量 (KB). |
YGC | young GC 次数. |
YGCT | young GC 用时 |
年轻代空间统计 | |
列名 | 描述 |
NGCMN | 最小 new generation 容量 (KB). |
NGCMX | 最大new generation容量(KB). |
NGC | 当前 new generation容量(KB). |
S0CMX | 最大survivor space 0容量(KB). |
S0C | 当前survivor space 0容量(KB). |
S1CMX | 最大survivor space 1容量(KB). |
S1C | 当前survivor space 1容量(KB). |
ECMX | 最大eden space容量(KB). |
EC | 当前eden space容量(KB). |
YGC | Young GC 次数. |
FGC | Full GC 次数. |
老年及永久代统计 | |
列名 | 描述 |
PC | 当前 permanent space 容量 (KB). |
PU | Permanent space 使用量 (KB). |
OC | 当前 old space 容量 (KB). |
OU | old space 使用量 (KB). |
YGC | Young GC 次数 |
FGC | Full GC 次数 |
FGCT | Full GC 用时. |
GCT | GC总用时 |
老年代统计 | |
列名 | 描述 |
OGCMN | 最小 old generation 容量 (KB). |
OGCMX | 最大 old generation 容量 (KB). |
OGC | 当前 old generation 容量 (KB). |
OC | 当前 old space 容量 (KB). |
YGC | Young GC 次数 |
FGC | Full GC 次数 |
FGCT | Full GC 用时. |
GCT | GC总用时 |
永久代统计 | |
列名 | 描述 |
PGCMN | 最小 permanent generation容量(KB). |
PGCMX | 最大 permanent generation容量(KB). |
PGC | 当前 permanent generation容量(KB). |
PC | 当前 permanent space容量(KB). |
YGC | Young GC 次数 |
FGC | Full GC 次数 |
FGCT | Full GC 用时. |
GCT | GC总用时 |
GC情况统计 | |
列名 | 描述 |
S0 | Survivor space 0占当前总空间大小的使用百分比. |
S1 | Survivor space 1占当前总空间大小的使用百分比. |
E | Eden space占当前总空间大小的使用百分比. |
O | Old space占当前总空间大小的使用百分比. |
P | Permanent space占当前总空间大小的使用百分比. |
YGC | 年轻代GC次数. |
YGCT | 年轻代GC占用的时间 |
FGC | Full GC 次数. |
FGCT | Full GC占用的时间 |
GCT | 垃圾回收占用的总时间 |
HotSpot编译器方法统计 | |
列名 | 描述 |
Compiled | 执行的编译任务数. |
Size | 方法的字节码大小 |
Type | 编译类型. |
Method | 类名和方法名唯一标识编译类型,类名用’/’代替’.’作为分隔符。方法名是给定类的方法名,这两个字段的格式取决于参数 HotSpot - XX:+PrintComplation option. |
参考资料:http://download.oracle.com/javase/6/docs/technotes/tools/share/jstat.html
jconsole
jconsole是一个基于JMX(Java Management Extensions,即Java管理扩展)图形化程序,它可以用来监控运行中的JVM情况,具体包括内存、线程、类、VM摘要等,同时还可以通过实时地改变JVM的配置来查看系统在不同参数下的情况。
在命令行中启动jconsole时,可以加入一些参数,其含义如下:
-interval=n 表示刷新时间间隔,默认为4,单位为s;
-notile 连接多个进程时窗口不折叠;
-pluginpath plugins 加载实现了com.sun.tools.jconsole.JConsolePlugin 的jconsole插件。
下面将分别介绍jconsole的启动及使用。
启动jconsole之后,可以看见连接进程的选择窗口,如图1所示:
图1 使用jconsole建立连接
图1可以看到,jconsole有两种连接方式:
(1)本地连接:在迚程列表中可以看到JAVA迚程的PID(这些迚程必须都是用JDK1.6的java.exe来启劢),选中幵连接即可。
(2)远程连接:可以使用<hostname>:<port>来连接进程服务器的Java远程进程(可以使用jps来查看正在运行的Java迚程port),还可以使用service:jmx:<protocol>:<sap>来连接JMXService(其中protocol为传输协议,sap是查找连接到服务器的地址位置),关于jmx路径的完整语法可以参考javax.management.remote.JMXServiceURL的官方API文档:http://www.gznc.edu.cn/yxsz/jjglxy/book/Java_api/javax/management/remote/class-use/JMXServiceURL.html。
jconsole连接了某一个进程之后,将会有六个标签页,它们分别是概述、内存、线程、类、VM摘要和MBean,如图2所示。其中概述页显示了内存、线程、类及VM摘要的最概略情况,内存、线程、类和VM摘要标签页详细展示了这四类信息。下面将分别介绍这些标签页的作用。
图2 概述
内存标签页显示了JVM的内存使用情况,可对需要查看的内存类型和时间进行选择,具体包括:堆/非堆内存、Eden Space、Survivor Space、Tenured Gen、Code Cache和Perm Gen使用情况,赶时间上可选择12小时、1天、7天、1个月等。在页面最下方,可以看到时刻的详细信息,页面右下方可以看到使用比例,页面的右上角执行GC按钮可点击进行手动执行GC。Code Cache是HotSpot JVM用来保存编译的本地代码(Native Code)的一块非堆内存区域。
图3 内存
线程标签页可以查看JVM中线程活动情况。红色线条显示线程峰值,蓝色线条显示的是活动线程数。左下角的列表显示了所有的活动线程名称,下方的输入框中可以输入线程名称过滤字符,输入过滤名称后,列表中只显示匹配的活动线程。点击线程名称,可查看线程的详细信息,包括线程名称、状态、阻塞总数、等待总数及堆栈追踪信息。
死锁:Java中的多线程使用synchronized关键字实现同步。为了避免线程中使用共享资源的冲突,当线程迚入synchronized的共享对象时,将为共享对象加上锁,阻止其他的线程迚入该共享对象.但是,正因为这样,当多线程访问多个共享对象时,如果线程锁定对象的顺序处理不当话就有可能线程间相互等待的情况,即常说的:死锁现象。
图4 线程
类标签页显示了当前装载的类,已装入的类总数及已卸载的类总数随时间变化的趋势图。如图4所示。
VM摘要标签页显示了所有JVM的基本信息,同时包括操作系统、处理器数目、虚拟内存及可交换空间等。如图5所示。
图5 VM摘要
MBean标签页允许查看及修改JVM中的一些配置信息(蓝色的属性代表可修改),实时触发一些操作(如GC)。在这里修改的属性,会与初始运行JVM时所传递给他的参数效果一样,可以立刻起效。MBean标签页如图5所示。
图6 MBean标签
如图6中设置了UsageThreshold属性之后,可以在内存标签页中立刻看到标记的阈值与当前使用量的比例。效果如图7所示。
图7 设置UsageThreshold后的效果图
更多关于JMX MBean的相关资料请参阅文档《JMX一步步来》
参考资料:http://download.oracle.com/javase/6/docs/technotes/tools/share/jconsole.html
资料:http://download.oracle.com/javase/6/docs/technotes/guides/management/jconsole.html