jconsole – jconsole是基于JavaManagementExtensions (JMX)的实时图形化监测工具,这个工具利用了内建到JVM里面的JMX指令来提供实时的性能和资源的监控,包括了Java程序的内存使用,Heap size, 线程的状态,类的分配状态和空间使用等等。Linux下设置环境变量如下:export DISPLAY=:0.0
jstatd–启动jvm监控服务。它是一个基于rmi的应用,向远程机器提供本机jvm应用程序的信息。默认端口1099。
-nr 当一个存在的RMI Registry没有找到时,不尝试创建一个内部的RMI Registry
-p port 端口号,默认为1099
-nrminame 默认为JStatRemoteHost;如果多个jstatd服务开始在同一台主机上,rminame唯一确定一个jstatd服务
-J jvm选项
$JAVA_HOME/jre/lib/security/java.policy文件中添加下面的代码:
grantcodebase "file:${java.home}/../lib/tools.jar" {
permission java.security.AllPermission;
};
默认端口为1099: jstatd -J-Djava.security.policy=jstatd.all.policy
指定hostname 指定端口: jstatd -J-Djava.rmi.server.hostname=192.168.8.7-J-Djava.security.policy=test/jstatd.all.policy -p 6001
启动JMX: jstatd -J-Djava.rmi.server.hostname=192.168.8.7-J-Djava.security.policy=test/jstatd.all.policy -J-Dcom.sun.management.jmxremote.port=6001 -J-Dcom.sun.management.jmxremote.ssl=false-J-Dcom.sun.management.jmxremote.authenticate=false -J -Djava.awt.headless=true
(java.NET.MalformedURLException:Local host name unknown: java.Net.UnknownHostException: a: a
原因是/etc/hosts文件里没有主机名为:a的,解决方法就是在hosts文件中加入a:
127.0.0.1 a localhost)
jps –jps是用来查看JVM里面所有进程的具体状态, 包括进程ID,进程启动的路径等等。
-m 输出传递给main方法的参数,如果是内嵌的JVM则输出为null。
-l 输出应用程序主类的完整包名,或者是应用程序JAR文件的完整路径。
-v 输出传给JVM的参数。
jstack -- jstack用于打印出给定的java进程ID或core file或远程调试服务的Java堆栈信息,如果是在64位机器上,需要指定选项"-J-d64",如果java程序崩溃生成core文件,jstack工具可以用来获得core文件的Java stack和nativestack的信息。Windows的jstack只支持-l.
-F当’jstack [-l] pid’没有相应的时候强制打印栈信息
-l长列表. 打印关于锁的附加信息,如属于java.util.concurrent的ownable synchronizers列表.
-m打印java和native c/c++框架的所有栈信息.
Jstackpid 显示jvm中当前所有线程的运行情况和线程当前状态
jinfo –可以输出并修改运行时的java 进程的opts。用处比较简单,用于输出JAVA系统参数及命令行参数。查看和修改运行中的java程序的运行环境参数。
jinfo-flag MaxPermSize 4084
jmap –jmap 可以从core文件或进程中获得内存的具体匹配情况,包括Heap size, Perm size等等,打印出某个java进程(使用pid)内存内的,所有‘对象’的情况。
-heap :打印jvm heap的情况
-histo: 打印jvm heap的直方图。其输出信息包括类名,对象数量,对象占用大小。
-histo:live : 同上,但是只输出存活对象的情况,会触发FULL GC
-permstat: 打印permanentgeneration heap情况
jmap-dump:format=b,file=outfile 3024可以将3024进程的内存heap输出出来到outfile文件里,再配合JHAT进行分析.
Jhat用于对JAVA heap进行离线分析的工具,他可以对不同虚拟机中导出的heap信息文件进行分析,如LINUX上导出的文件可以拿到WINDOWS上进行分析
jhat -J-Xmx512m
jstat – jstat利用了JVM内建的指令对Java应用程序的资源和性能进行实时的命令行的监控, 可以观察到classloader,compiler,gc相关信息,包括了对Heap size和垃圾回收状况的监控等等。
-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情况
-compiler:显示VM实时编译的数量等信息
-snap: 查看Java进程的jvmstat的各个monitor的值
jstat-gc [email protected]
java-verbose:class PID输出虚拟机装入的类的信息, 当虚拟机报告类找不到或类冲突时可用此参数来诊断来查看虚拟机从装入类的情况。
java –verbose:jni输出native方法调用的相关情况,一般用于诊断jni调用错误信息
常用JVM分析信息获取:
1、确认服务器上是否存在SUN JDK6,如果没有建议安装一个,我们需要使用里面的工具(jps、jmap、jstat、jconsole、jstack)
2、 获取MKEY的JAVA进程ID(后面简称PID)
a) 操作方法:进入SUN JDK的bin目录在命令行中输入jps,查看MKEY的进程ID
3、提取GC信息()
a) 操作方法:示例:jstat –gcPID 600000 43200 >> gc_20110909.log
4、 提取Heap区信息(间隔10分钟提取一次)
a) 操作方法:jmap -heap PID >>heap_20110909.log
5、提取对象信息(间隔10分钟提取一次)
a) 操作方法:jmap-histo PID > histo_*.log(文件较大,*按序号生成输入)
6、线程转储日志
a) jstack PID
b) 宕机日志(在domain目录,如果没有宕机,条件允许的情况下可使用 kill -3 PID(此操作会杀掉进程))
设置GC指令和方法:
1. JVM内存分配设置的参数有四个
-Xmx Java Heap最大值,默认值为物理内存的1/4;
-Xms Java Heap初始值,Server端JVM最好将-Xms和-Xmx设为相同值,开发测试机JVM可以保留默认值;
-Xmn Java Heap Young区大小,不熟悉最好保留默认值;
-Xss 每个线程的Stack大小,不熟悉最好保留默认值;
-XX:PermSize:设定内存的永久保存区域;-XX:MaxPermSize:设定最大内存的永久保存区域;
-XX:PermSize:设定内存的永久保存区域;
-XX:NewSize:设置JVM堆的‘新生代’的默认大小;
-XX:MaxNewSize:设置JVM堆的‘新生代’的最大大小;
2. 如何设置JVM的内存分配
(1)当在命令提示符下启动并使用JVM时(只对当前运行的类Test生效):
java -Xmx128m -Xms64m -Xmn32m -Xss16m Test
(2)当在集成开发环境下(如eclipse)启动并使用JVM时:
a. 在eclipse根目录下打开eclipse.ini,默认内容为(这里设置的是运行当前开发工具的JVM内存分配): -vmargs -Xms40m -Xmx256m -vmargs表示以下为虚拟机设置参数,可修改其中的参数值,也可添加-Xmn,-Xss,另外,eclipse.ini内还可以设置非 堆内存,如:-XX:PermSize=56m,-XX:MaxPermSize=128m。
b. 打开eclipse-窗口-首选项-Java-已安装的JRE(对在当前开发环境中运行的java程序皆生效) 编辑当前使用的JRE,在缺省VM参数中输入:-Xmx128m -Xms64m -Xmn32m –Xss16m。
c. 打开eclipse-运行-运行-Java应用程序(只对所设置的java类生效) 选定需设置内存分配的类-自变量,在VM自变量中输入:-Xmx128m -Xms64m -Xmn32m -Xss16m 注:如果在同一开发环境中同时进行了b和c设置,则b设置生效,c设置无效,如: 开发环境的设置为:-Xmx256m,而类Test的设置为:-Xmx128m -Xms64m,则运行Test时生效的设置为: -Xmx256m -Xms64m。
(3)当在服务器环境下(如Tomcat)启动并使用JVM时(对当前服务器环境下所以Java程序生效):
a. 设置环境变量: 变量名:CATALINA_OPTS 变量值:-Xmx128m -Xms64m -Xmn32m -Xss16m。(方法1)
b. 打开Tomcat根目录下的bin文件夹,编辑catalina.bat,将其中的%CATALINA_OPTS%(共有四处)替换为:-Xmx128m -Xms64m -Xmn32m -Xss16m(方法2)。
c. 若没有catalina.bat,只有tomcat.exe,tomcat6w.exe;则可以在启动tomcat6w.exe 后 右键配置--Java--java option 下面输入:
-Xmx256m –Xms64m
也可以找到注册表HKEY_LOCAL_MACHINE\SOFTWARE\Apache Software Foundation\TomcatService Manager\Tomcat6\Parameters\JavaOptions原值为 -Dcatalina.home="C:\ApacheGroup\Tomcat 6.0" -Djava.endorsed.dirs="C:\ApacheGroup\Tomcat 6.0\common\endorsed" -Xrs 加入 -Xms300m -Xmx350m (我的是加入-Xmx350m,tomcat才能启动,加入-Xms300m -Xmx350m反而tomcat都不能启动)重起tomcat服务,设置生效。
3. 查看JVM内存信息
Runtime.getRuntime().maxMemory(); //最大可用内存,对应-Xmx
Runtime.getRuntime().freeMemory(); //当前JVM空闲内存
Runtime.getRuntime().totalMemory(); //当前JVM占用的内存总数,其值相当于当前JVM已使用的内存及freeMemory()的总和
关于maxMemory(),freeMemory()和totalMemory():maxMemory()为JVM的最大可用内存,可通过-Xmx设置,默认值为物理内存的1/4,设置不能高于计算机物理内存; totalMemory()为当前JVM占用的内存总数,其值相当于当前JVM已使用的内存及freeMemory()的总和,会随着JVM使用内存的增加而增加; freeMemory()为当前JVM空闲内存,因为JVM只有在需要内存时才占用物理内存使用,所以freeMemory()的值一般情况下都很小,而JVM实际可用内存并不等于freeMemory(),而应该等于maxMemory()-totalMemory()+freeMemory()。
4. 实例,以下给出1G内存环境下java jvm 的参数设置参考
JAVA_OPTS="-server -Xms800m -Xmx800m -XX:PermSize=64M -XX:MaxNewSize=256m -XX:MaxPermSize=128m -Djava.awt.headless=true "
大型的web工程,用tomcat默认分配的内存空间无法启动,如果不是在myeclipse中启动tomcat可以对tomcat这样设置:
TOMCAT_HOME\bin\catalina.bat 中添加这样一句话:
set JAVA_OPTS= -Xmx1024M -Xms512M -XX:MaxPermSize=256m
如果要在myeclipse中启动,上述的修改就不起作用了,可如下设置:
Myeclipse->preferences->myeclipse->servers->tomcat->tomcat×.×->JDK面板中的
Optional Java VM arguments中添加:-Xmx1024M -Xms512M -XX:MaxPermSize=256m
对于单独的.class,可以用下面的方法对Test运行时的jvm内存进行设置。 java -Xms64m -Xmx256m Test -Xms是设置内存初始化的大小 -Xmx是设置最大能够使用内存的大小。
很好的经验:
1.Server端JVM最好将-Xms和-Xmx设为相同值。为了优化GC,最好让-Xmn值约等于-Xmx的1/3。
2.一个GUI程序最好是每10到20秒间运行一次GC,每次在半秒之内完成。
注意:
1.增加Heap的大小虽然会降低GC的频率,但也增加了每次GC的时间。并且GC运行时,所有的用户线程将暂停,也就是GC期间,Java应用程序不做任何工作。
2.Heap大小并不决定进程的内存使用量。进程的内存使用量要大于-Xmx定义的值,因为Java为其他任务分配内存,例如每个线程的Stac
为什么一些程序频繁发生GC?有如下原因:
1. 程序内调用了System.gc()或Runtime.gc()。
2. 一些中间件软件调用自己的GC方法,此时需要设置参数禁止这些GC。
3. Java的Heap太小,一般默认的Heap值都很小。
4. 频繁实例化对象,Release对象 此时尽量保存并重用对象,例如使用StringBuffer()和String()。
如果你发现每次GC后,Heap的剩余空间会是总空间的50%,这表示你的Heap处于健康状态许多Server端的Java程序每次GC后最好能有65%的剩余空间。