java虚拟机监控

来源:互联网 发布:淘宝外卖不能分口袋吗 编辑:程序博客网 时间:2024/05/16 20:29

以下是这些工具的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大小-Xmxjava heap最大值-Xmnyoung 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-collection
2. Performance tuning Java: Tuning stepsleizhimin 51cto技术博客http://h21007.www2.hp.com/dspp/tech/tech_TechDocumentDetailPage_IDX/1 ,1701,1604,00.html
3. 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时间,很显然,这时系统性能瓶颈真正所在可能是内存。