最近压力测试和调优Liferay
portal,所以需要找到一种工具,可以比较好的监测VM工具。本来想使用商用工具,但偶然间发现SUN
的JDK中新添了几个工具,并且非常好用。秉承着有免费,不用商用的原则。开始使用新的JDK工具,以下简单介绍一下这几种工具。(注:本文章下的所有工
具都存在JDK5.0以上版本的工具集里,同javac一样,不须特意安装)
我一共找到以下五个工具:
jinfo:可以输出并修
改运行时的java 进程的opts。
jps:与unix上的ps类似,用来显示本地的java进程,可以查看本地运行着几个java程序,并显
示他们的进程号。
jstat:一个极强的监视VM内存工具。可以用来监视VM内存内的各种堆和非堆的大小及其内存使用量。
jmap:打印
出某个java进程(使用pid)内存内的,所有‘对象’的情况(如:产生那些对象,及其数量)。
jconsole:一个java
GUI监视工具,可以以图表化的形式显示各种数据。并可通过远程连接监视远程的服务器VM。
接下来是对这些工具的详细介绍:
从
最简单的jstat工具开始:我想很多人都是用过unix系统里的ps命令,这个命令主要是用来显示当前系统的进程情况,有哪些进程,及其id。jps
也是一样,它的作用是显示当前系统的java进程情况,及其id号。我们可以通过它来查看我们到底启动了几个java进程(因为每一个java程序都会独
占一个java虚拟机实例),和他们的进程号(为下面几个程序做准备),并可通过opt来查看这些进程的详细启动参数。
使用方法:在当前命令行下
打 jps(需要JAVA_HOME,没有的话,到改程序的目录下打)
接下来是jstat,我之所以这次调优Liferay
portal是因为,liferay在默认的情况下,并发用户一多就会产生perm out of
momery异常。虽然很开就解决了,但发现对VM内存使用量监控的重要性。通过google,很快的发现了jstat这个工具。
jstat工具
特别强大,有众多的可选项,详细查看堆内各个部分的使用量,以及加载类的数量。使用时,需加上查看进程的进程id,和所选参数。以下详细介绍各个参数的意
义。
jstat -class pid:显示加载class的数量,及所占空间等信息。
jstat -compiler
pid:显示VM实时编译的数量等信息。
jstat -gc
pid:可以显示gc的信息,查看gc的次数,及时间。其中最后五项,分别是young gc的次数,young gc的时间,full
gc的次数,full gc的时间,gc的总时间。
jstat
-gccapacity:可以显示,VM内存中三代(young,old,perm)对象的使用和占用大小,如:PGCMN显示的是最小perm的内存使
用量,PGCMX显示的是perm的内存最大使用量,PGC是当前新生成的perm内存占用量,PC是但前perm内存占用量。其他的可以根据这个类推,
OC是old内纯的占用量。
jstat -gcnew pid:new对象的信息。
jstat -gcnewcapacity
pid:new对象的信息及其占用量。
jstat -gcold pid:old对象的信息。
jstat -gcoldcapacity
pid:old对象的信息及其占用量。
jstat -gcpermcapacity pid: perm对象的信息及其占用量。
jstat
-util pid:统计gc信息统计。
jstat -printcompilation pid:当前VM执行的信息。
除了以上一个
参数外,还可以同时加上 两个数字,如:jstat -printcompilation 3024 250
6是每250毫秒打印一次,一共打印6次,还可以加上-h3每三行显示一下标题。
jstat -gcutil 8908
S0:Heap上的 Survivor space 0 段已使用空间的百分比
S1:Heap上的 Survivor space 1 段已使用空间的百分比
E: Heap上的 Eden space 段已使用空间的百分比
O: Heap上的 Old space 段已使用空间的百分比
P: Perm space 已使用空间的百分比
YGC:从程序启动到采样时发生Young GC的次数
YGCT:Young GC所用的时间(单位秒)
FGC:从程序启动到采样时发生Full GC的次数
FGCT:Full GC所用的时间(单位秒)
GCT:用于垃圾回收的总时间(单位秒)
稍微说说垃圾收集GC的基本操作过程。
首先,GC把内存大体分成4块,分别是old
generation(年老代),eden(年轻代),以及survivor space1(ss1),survivor
space0(ss0).当声明变量的时候,首先是把变量声明在年轻代中,然后当年轻代被填满,则发生次要垃圾收集,将其中存活对象复制到SS1中,再将
年轻代清空。
继续在eden中声明对象,当eden再次填满,则再次发生次要垃圾收集,这次是把ss1的内容计算存活期,如果很长就复制到年老代,其余的存活的复制到ss0,然后将ss1清空,并对eden进行前述的次要垃圾收集。
当年老代也被填满,则产生一次主要垃圾收集,非常耗费时间。
PermGen space的全稱是Permanent Generation
space,是指記憶體的永久保存區域OutOfMemoryError: PermGen
space從表面上看就是記憶體益出,解決方法也一定是加大記憶體。說說為什麼會記憶體益出:這一部分用於存放Class和Meta的資訊,Class在
被 Load的時候被放入PermGen space區域,它和和存放Instance的Heap區域不同,GC(Garbage
Collection)不會在主程序運行期對PermGen
space進行清理,所以如果你的APP會LOAD很多CLASS的話,就很可能出現PermGen
space錯誤。這種錯誤常見在web伺服器對JSP進行pre compile的時候。
jmap是一个可以输出所有内存中对象的工具,甚至可以
将VM 中的heap,以二进制输出成文本。使用方法 jmap -histo pid。如果连用SHELL jmap -histo
pid>a.log可以将其保存到文本中去,在一段时间后,使用文本对比工具,可以对比出GC回收了哪些对象。jmap
-dump:format=b,file=String 3024可以将3024进程的内存heap输出出来到String文件里。
jinfo:
的用处比较简单,就是能输出并修改运行时的java进程的运行参数。用法是jinfo -opt pid
如:查看2788的MaxPerm大小可以用 jinfo -flag MaxPermSize 2788。
jconsole是一个用
java写的GUI程序,用来监控VM,并可监控远程的VM,非常易用,而且功能非常强。由于是GUI程序,这里就不详细介绍了,不会的地方可以参考
SUN的官方文档。
使用方法:命令行里打 jconsole,选则进程就可以了。
以下是这些工具的SUN官方说明:
jps:
jstat:
jmap:
jconsole:
附
加:windows查看进程号,由于任务管理器默认的情况下是不显示进程id号的,所以可以通过如下方法加上。ctrl+alt+del打开任务管理器,
选择‘进程’选项卡,点‘查看’->'选择列'->加上'PID',就可以了。
jinfo用来打印出给定的java进程或core文件或一个远程debug服务的java配置信息.
信息包括java系统属性和JVM启动时命令行中的参数. 假如进程是在64-bit下运行的vm,那么需要指定-J-d64参数.
在windows平台上,jinfo只支持-flag选项.
info的命令如下:
jinfo [option] pid
jinfo [option] executable core
jinfo [option] [server-id@]remote-hostname-or-ip
parameters
options
打印所有的命令行参数和系统属性的名和值.
-flag name
打印命令行中名为name的参数的名和值
-flag [+|-]name
设置命令行中名为name的bool值.
-flag name=value
设置命令行中名为name的值
-flags
打印所有命令行中的参数名和值
-sysprops
打印所有系统属性名和值
-h | -help
帮助信息
pid需要被打印配置信息的java进程id,可以用jps查询.
executable
Java executable from which the core dump was produced.
(可能是产生core dump的java可执行程序)
core将被打印信息的core dump文件
remote-hostname-or-IP 远程debug服务的主机名或ip
server-id 唯一id,假如一台主机上多个远程debug服务
jstack用来打印给定的jvm的线程的栈信息. 为每个java框架打印class全名,方法名,字节码地址,行号.
假如给定的jvm是运行在64位模式,那么你需要指定-J-d64参数,例如: jmap -J-d64 -heap pid
jstack在windows平台上,只能使用的形式如下:
jstack [-l] pid
jstack的命令形式:
jstack [ option ] pid
jstack [ option ] executable core
jstack [ option ] [server-id@]remote-hostname-or-IP
parameters
options
-F
当’jstack [-l] pid’没有相应的时候强制打印栈信息
-l
长列表. 打印关于锁的附加信息,例如属于java.util.concurrent的ownable synchronizers列表.
-m
打印java和native c/c++框架的所有栈信息.
-h | -help
打印帮助信息
pid
需要被打印配置信息的java进程id,可以用jps查询.
executable
Java executable from which the core dump was produced.
(可能是产生core dump的java可执行程序)
core
将被打印信息的core dump文件
remote-hostname-or-IP
远程debug服务的主机名或ip
server-id
唯一id,假如一台主机上多个远程debug服务
jhat可以解析java heap的dump文件,并且启动一个web server,这样你可以在浏览器中查看heap信息.
jhat支持query语句,叫做Object Query Langguage(OQL),类似与SQL. 可以在jhat的web
server启动后,查看帮助,如:
jhat的命令如下:
jhat [options] <heap-dump-file>
options
-stack false/true
关闭跟踪对象分配调用堆栈. 注意: 假如堆dump中无可用的分配位置信息,你应该设置这个标志为flase. 默认为true.
-refs false/true
关闭对象的引用跟踪. 默认是true. 默认情况下返回指针计算在堆中的所有对象.
-port port-number
设置jhat的http server端口. 默认是7000
-exclude exclude-file
指定一个文件,文件里罗列了不能OQL不能取到的数据成员. 例如,文件中罗列了java.lang.String.value,
那么得到的对象中,相关java.lang.String.value字段的引用路径将不会深入.
-baseline baseline-dump-file
指定一个特殊的堆dump文件. 在两个堆dumps中都出现的同一对象id不会被打上”new”的标记. 其他的都打上”new”.
这样对于比较不同的堆dump文件是相当有用的.
-debug int
设置jhat的debug等级. 0表示没有debug的输出. 更详细的模式,需要设置更高的值.
-version
输出jhat的版本信息
-h | -help
输出帮助信息
-J
传递给jhat运行时的jvm. 例如: -J-Xmx512m.
heap-dump-file
一个需要被jhat解析的二进制文件. 假如一个文件中包含多个堆dumps, 可以在文件名后跟上#来指定那个dump文件将被解析,
例如: “all.hprof#3″