java虚拟机监控

时间:2022-12-26 17:15:46

以下是这些工具的SUN官方说明: 
jps:http://java.sun.com/j2se/1.5.0/docs/tooldocs/share/jps.html 
jstat:http://java.sun.com/j2se/1.5.0/docs/tooldocs/share/jstat.html 
jmap:http://java.sun.com/j2se/1.5.0/docs/tooldocs/share/jmap.html 
jconsole:http://java.sun.com/j2se/1.5.0/docs/guide/management/jconsole.html

JSTAT:工具说明--一个极强的监视VM内存工具。可以用来监视VM内存内的各种堆和非堆的大小及其内存使用量

接下来是jstat,我之所以这次调优Liferay portal是因为,liferay在默认的情况下,并发用户一多就会产生perm out of momery异常。虽然很开就解决了,但发现对VM内存使用量监控的重要性。通过google,很快的发现了jstat这个工具。 
jstat工具特别强大,有众多的可选项,详细查看堆内各个部分的使用量,以及加载类的数量。使用时,需加上查看进程的进程id,和所选参数。以下详细介绍各个参数的意义。 
jstat -class (KBytes ) pid:显示加载class的数量,及所占空间等信息。 
jstat -compiler pid:显示VM实时编译的数量等信息。 
jstat -gc pid((KB)): 可以显示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每三行显示一下标题。

jmap(jmap -heap pid可以看jvm参数使用状况)

观察运行中的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中所有生存的对象的情况)。包括对象数量和所占空间大小。
输出内容:



jinfo:(看英文文档好像已经不怎么支持了)

的用处比较简单,就是能输出并修改运行时的java进程的运行参数。用法是jinfo -opt  pid 如:查看2788的MaxPerm大小可以用  jinfo -flag MaxPermSize 2788。 

jconsole

是一个用java写的GUI程序,用来监控VM,并可监控远程的VM,非常易用,而且功能非常强。由于是GUI程序,这里就不详细介绍了,不会的地方可以参考SUN的官方文档。 
使用方法:命令行里打 jconsole,选则进程就可以了。下面是远程jconsole配置,在tomcat下加入

  • catalina.bat: (windows 有set)

set JAVA_OPTS=%JAVA_OPTS% -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port="9004" -Dcom.sun.management.jmxremote.authenticate="false" -Dcom.sun.management.jmxremote.ssl="false"

  • catalina.sh:(linux没有set)

JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9004 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false"

 2)本机上使用jconsole连接远程的8999端口
报连接失败,检查网络情况,8999端口有在监听等待,本地机器能够连接上对端机器的8999端口。切换了一台linux机器,情况依旧。

3)去网上找了一把,发现一个网友一年多前也在为此苦恼,所不同的是网友用的是JDK1.5,我用的是JDK 1.6。该网文链接如下:
http://svr.wjworld.net/soft/P1558/I7132389.shtml

4)尝试抓包分析,发现是RMI的二进制协议,无法解读,报文中有127.0.0.1等字眼,从关键字判断是RMI下载的STUB文件。

5) 继续查找,发现了一篇有价值的文章谈到这个问题,是服务器端解释机器名的问题,如果服务器端hostname -i被定向到127.0.0.1则会出现连接失败的问题。修改/etc/hosts文件,使hostname -i 指向正确的IP,JConsole终于可以正常连接。
这篇文章链接如下:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6209663

6)可能的问题原因分析:JCONSOLE连接上监控的进程,从监控进程下载了RMI远程调用的STUB文件?该STUB访问服务器的进程,

服务器端的地址可能是通过hostname -i类似机制获得。

英文地址:
http://java.sun.com/javase/6/docs/technotes/tools/share/jstack.html

 

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实例
列出本机所有的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

 

 

 

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服务



以下是这些工具的SUN官方说明: 
jps:http://java.sun.com/j2se/1.5.0/docs/tooldocs/share/jps.html 
jstat:http://java.sun.com/j2se/1.5.0/docs/tooldocs/share/jstat.html 
jmap:http://java.sun.com/j2se/1.5.0/docs/tooldocs/share/jmap.html 
jconsole:http://java.sun.com/j2se/1.5.0/docs/guide/management/jconsole.html 

附加:windows查看进程号,由于任务管理器默认的情况下是不显示进程id号的,所以可以通过如下方法加上。ctrl+alt+del打开任务管理器,选择‘进程’选项卡,点‘查看’->'选择列'->加上'PID',就可以了。

-----------------------------------------------------------------

JVM内存的设置的原理 
  
默认的java虚拟机的大小比较小,在对大数据进行处理时java就会报错:java.lang.OutOfMemoryError。
设置jvm内存的方法,对于单独的.class,可以用下面的方法对Test运行时的jvm内存进行设置。
java -Xms64m -Xmx256m Test
-Xms是设置内存初始化的大小
-Xmx是设置最大能够使用内存的大小(最好不要超过物理内存大小)
在weblogic中,可以在startweblogic.cmd中对每个domain虚拟内存的大小进行设置,默认的设置是在commEnv.cmd里面。

 

本文引用地址: http://cnpoint.com/framwwork/2006/1109/content_4563.htm

JVM内存的调优

1. Heap设定与垃圾回收 Java Heap分为3个区,Young,Old和Permanent。Young保存刚实例化的对象。当该区被填满时,GC会将对象移到Old区。Permanent区则负责保存反射对象,本文不讨论该区。 JVM的Heap分配可以使用-X参数设定,

 

-Xms 初始Heap大小
-Xmx java heap最大值
-Xmn young generation的heap大小
JVM有2个GC线程。第一个线程负责回收Heap的Young区。第二个线程在Heap不足时,遍历Heap,将Young 区升级为Older区。Older区的大小等于-Xmx减去-Xmn,不能将-Xms的值设的过大,因为第二个线程*运行会降低JVM的性能。 为什么一些程序频繁发生GC?有如下原因: l         程序内调用了System.gc()或Runtime.gc()。 l         一些中间件软件调用自己的GC方法,此时需要设置参数禁止这些GC。 l         Java的Heap太小,一般默认的Heap值都很小。 l         频繁实例化对象,Release对象。此时尽量保存并重用对象,例如使用StringBuffer()和String()。          如果你发现每次GC后,Heap的剩余空间会是总空间的50%,这表示你的Heap处于健康状态。许多Server端的Java程序每次GC后最好能有65%的剩余空间。 经验之谈: 1  Server  JVM 最好将 -Xms  -Xmx 设为相同值。为了优化 GC ,最好让 -Xmn 值约等于 -Xmx  1/3[2]  2 .一个 GUI 程序最好是每 10  20 秒间运行一次 GC ,每次在半秒之内完成 [2]  注意: 1.增加Heap的大小虽然会降低GC的频率,但也增加了每次GC的时间。并且GC运行时,所有的用户线程将暂停,也就是GC期间,Java应用程序不做任何工作。 2.Heap大小并不决定进程的内存使用量。进程的内存使用量要大于-Xmx定义的值,因为Java为其他任务分配内存,例如每个线程的Stack等。 2.Stack的设定 每个线程都有他自己的Stack。

 

-Xss 每个线程的 Stack 大小
Stack的大小限制着线程的数量。如果Stack过大就好导致内存溢漏。-Xss参数决定Stack大小,例如-Xss1024K。如果Stack太小,也会导致Stack溢漏。 3.硬件环境 硬件环境也影响GC的效率,例如机器的种类,内存,swap空间,和CPU的数量。 如果你的程序需要频繁创建很多transient对象,会导致JVM频繁GC。这种情况你可以增加机器的内存,来减少Swap空间的使用[2]。 4.4种GC 第一种为单线程GC,也是默认的GC。,该GC适用于单CPU机器。 第二种为Throughput GC,是多线程的GC,适用于多CPU,使用大量线程的程序。第二种GC与第一种GC相似,不同在于GC在收集Young区是多线程的,但在Old区和第一种一样,仍然采用单线程。-XX:+UseParallelGC参数启动该GC。 第三种为Concurrent Low Pause GC,类似于第一种,适用于多CPU,并要求缩短因GC造成程序停滞的时间。这种GC可以在Old区的回收同时,运行应用程序。-XX:+UseConcMarkSweepGC参数启动该GC。 第四种为Incremental Low Pause GC,适用于要求缩短因GC造成程序停滞的时间。这种GC可以在Young区回收的同时,回收一部分Old区对象。-Xincgc参数启动该GC。 4种GC的具体描述参见[3]。   参考文章:1. JVM Tuning. http://www.caucho.com/resin-3.0/performance/jvm-tuning.xtp#garbage-collection2. Performance tuning Java: Tuning stepsleizhimin 51cto技术博客http://h21007.www2.hp.com/dspp/tech/tech_TechDocumentDetailPage_IDX/1 ,1701,1604,00.html3. Tuning Garbage Collection with the 1.4.2 JavaTM Virtual Machine .leizhimin 51cto技术博客 http://java.sun.com/docs/hotspot/gc1.4.2/ 原文地址:http://blog.csdn.net/tyrone1979/archive/2006/09/25/1274458.aspx   --------------------------------------------------------------------------------------------

当内存资源成为系统性能的瓶颈时,它有一些典型的症状: 

很高的换页率(high pageout rate):通常情况下,它只执行调入页面进入内存的操作,以让进程能够运行。只有操作系统觉得系统需要释放一些内存空间时,才会执行从内存调出页面的操作,而过高的调出页面操作说明内存缺乏; 
进 程进入不活动状态(process deactivation activity):当*的内存页面数量小于MINFREE时,很多进程将强制进入不活动状态,因为,any deactivation activity represents a condition in which normal paging is inadequate to handle the memory demands. 
*内存的数量很小,但活动的虚拟内存却很大(very small free memory and large active virtual memory) 
交换区所有磁盘的活动次数可高(high disk activity on swap devices) 
可高的全局系统CPU利用率(high global system CPU utilization): 
很长的运行进程队列,但CPU的空闲时间却很多(large run queue with idle CPU) 
内存不够出错(out of memory errors) 
CPU用于vhand和swapper两中守护进程的时间(CPU time to vhand and swapper) 
必须注意的是,有时候我们发现CPU很忙,这似乎是CPU资源成为系统性能的瓶颈,但如果进一步分析,发现vhand和swapper守护进程占用了大量的系统CPU时间,很显然,这时系统性能瓶颈真正所在可能是内存。