jstatd
启动jvm监控服 务。它是一个基于rmi的应用,向远程机器提供本机jvm应用程序的信息。默认端口1099。
实例:jstatd -J-Djava.security.policy=my.policy
my.policy文件需要自己建立,内如如下:
grant codebase "file:$JAVA_HOME/lib/tools.jar" {
permission java.security.AllPermission;
};
这是安全策略文件,因为jdk对jvm做了jaas的安全检测,所以我们 必须设置一些策略,使得jstatd被允许作网络操作
jps
列出所有的jvm实例
实 例:
jps
列出本机所有的jvm实例
jps 192.168.0.77
列出远程服务器192.168.0.77 机器所有的jvm实例,采用rmi协议,默认连接端口为1099
(前提是远程服务器提供jstatd服务)
输出内容如下:
jones@jones:~/data/ebook/java/j2se/jdk_gc$ jps
6286 Jps
6174 Jstat
jconsole
一个图形化界面,可以观察到java进程的 gc,class,内存等信息。虽然比较直观,但是个人还是比较倾向于使用jstat命令(在最后一部分会对jstat作详细的介绍)。
jinfo(linux下特有)
观 察运行中的java程序的运行环境参数:参数包括Java System属性和JVM命令行参数
实例:jinfo 2083
其中2083 就是java进程id号,可以用jps得到这个id号。
输出内容太多了,不在这里一一列举,大家可以自己尝试这个命令。
jstack(linux下特有)
可 以观察到jvm中当前所有线程的运行情况和线程当前状态
jstack 2083
jmap(linux下特有,也是很常用 的一个命令)
观察运行中的jvm物理内存的占用情况。
参数如下:
-heap:打印jvm heap的情况
-histo:打印jvm heap的直方图。其输出信息包括类名,对象数量,对象占用大小。
-histo:live :同上,但是只答应存活对象的情况
-permstat:打印permanent generation heap情况
命令使用:
jmap -heap 2083
可以观察到New Generation(Eden Space,From Space,To Space),tenured generation,Perm Generation的内存使用情况
jmap -histo 2083 | jmap -histo:live 2083
可以观察heap中所有对象的情况(heap中所有生存的对 象的情况)。包括对象数量和所占空间大小。
写个脚本,可以很快把占用heap最大的对象找出来,对付内存泄漏特别有效。
jstat
最后要重点介绍下这个 命令。
这是jdk命令中比较重要,也是相当实用的一个命令,可以观察到classloader,compiler,gc相关信息
具体参数 如下:
-class:统计class loader行为信息
-compile:统计编译行为信息
-gc:统计jdk gc时heap信息
-gccapacity:统计不同的generations(不知道怎么翻译好,包括新生区,老年区,permanent区) 相应的heap容量情况
-gccause:统计gc的情况,(同-gcutil)和引起gc的事件
-gcnew:统计gc时,新生代的情 况
-gcnewcapacity:统计gc时,新生代heap容量
-gcold:统计gc时,老年区的情况
-gcoldcapacity: 统计gc时,老年区heap容量
-gcpermcapacity:统计gc时,permanent区heap容量
-gcutil:统计 gc时,heap情况
-printcompilation:不知道干什么的,一直没用过。
一般比较常用的几个参数是:
jstat -class 2083 1000 10 (每隔1秒监控一次,一共做10次)
输出内容含义如下:
Loaded | Number of classes loaded. |
Bytes | Number of Kbytes loaded. |
Unloaded | Number of classes unloaded. |
Bytes | Number of Kbytes unloaded. |
Time | Time spent performing class load and unload operations. |
jstat -gc 2083 2000 20(每隔2秒监控一次,共做10)
输出内容含义如下:
S0C | Current survivor(存活的) space 0 capacity (KB). |
EC | Current eden space capacity (KB). |
EU | Eden space utilization (KB). |
OC | Current old space capacity (KB). |
OU | Old space utilization (KB). |
PC | Current permanent space capacity (KB). |
PU | Permanent space utilization (KB). |
YGC | Number of young generation GC Events. |
YGCT | Young generation garbage collection time. |
FGC | Number of full GC events. |
FGCT | Full garbage collection time. |
GCT | Total garbage collection time. |
监控内存使用情况 参数 (查看内存溢出相对有用)
jstat -gccause 2083 5000 (每隔5秒监控一次)
输出内容含义如下:
S0 | Survivor space 0 utilization as a percentage of the space's current capacity. |
S1 | Survivor space 1 utilization as a percentage of the space's current capacity. |
E | Eden space utilization as a percentage of the space's current capacity. |
O | Old space utilization as a percentage of the space's current capacity. |
P | Permanent space utilization as a percentage of the space's current capacity. |
YGC | Number of young generation GC events. |
YGCT | Young generation garbage collection time. |
FGC | Number of full GC events. |
FGCT | Full garbage collection time. |
GCT | Total garbage collection time. |
LGCC | Cause of last Garbage Collection. |
GCC | Cause of current Garbage Collection. |
除了jconsole, oracle接管java后,提供了一个更强大的工具:jvisualvm
类似于jconsole,但是提供的信息更多,而且可以实时查看dump。强烈推荐。
但是这里有一个权限问题,当在linux上面用jvisualvm时,如果JVM运行的用户跟当前jvisualvm用的用户不是同一个,可能不能sample memory和导dump,所以一定要确保jvisualvm和监视的jvm用的是相同的JVM和相同的用户启动。最好都是root。
如果发现不能连接,尝试修改jboss/jvm参数:
然后把loggmanager跟mbean的包加入到classpath中JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.port=9999 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false"
JAVA_OPTS="$JAVA_OPTS -Djboss.platform.mbeanserver"
JAVA_OPTS="$JAVA_OPTS -Djavax.management.builder.initial=org.jboss.system.server.jmx.MBeanServerBuilderImpl"
JAVA_OPTS="$JAVA_OPTS -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
JAVA_OPTS="$JAVA_OPTS -Dorg.jboss.logging.Logger.pluginClass=org.jboss.logging.logmanager.LoggerPluginImpl"
JBOSS_CLASSPATH="$JBOSS_CLASSPATH:$JBOSS_HOME/lib/jboss-logmanager.jar:$JBOSS_HOME%/lib/jboss-mbeanserver.jar"
jvisualVM可以实时的监视和导dump,但有时还需要手动,那么用命令:
jmap -F -dump:live,format=b,file=/var/tmp/java_<pid>_<time>.bin <pid>
导出dump文件后,可以用eclipse memory analyzer来分析它。
-- Peak 结果可以直接帮你看到哪一块是有问题的;
-- Histogram 可以直观的看到内存中各个Obeject的数目和实际retained heap.
-- DominatorTree可以看到各个对象的引用关系,在其中任何一个条目上可以右键去选ListObject或ShowObject by outgoing reference(内部引用外面)或 by incoming reference (外部引用该对象)
里面有两个概念:
Shallow -- 表示该对象里面指针及引用所占大小
Retained Heap -- 表示该对象里实际占用虚拟内存大小
如果看到shallow 是1,而实际内存又很大,可以点进去分析,多半会发现都是null在占空间。