深入理解java虚拟机第二版虚拟机性能监控与故障处理工具
Posted xyzshm
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入理解java虚拟机第二版虚拟机性能监控与故障处理工具相关的知识,希望对你有一定的参考价值。
JDK的命令行工具(jps:虚拟机进程状况工具,jstat:虚拟机统计信息监视工具,jinfo:Java配置信息工具,jmap:Java内存映像工具,jhat:虚拟机堆转储快照分析工具,jstack:Java堆栈跟踪工具);可视化工具(JConsole,VisualVM)
一. JDK的命令行工具
- jps:JVM Process Status Tool,显示指定系统内所有的HotSpot虚拟机进程
- jstat:JVM Statistics Monitoring Tool,用户收集HotSpot虚拟机各方面的运行数据
- jinfo:Configuration Info for Java,显示虚拟机配置信息
- jmap:Memory Map for java,生成虚拟机的内存转储快照
- jhat,JVM Heap Dump Browser,用户分析heapdump文件,它会建立一个HTTP/html服务器,让用户可以在浏览器上查看分析结果
- jstack, Stack Trace for Java,显示虚拟机的线程快照
1 jps:虚拟机进程状况工具
jsp命令格式:
jps [options] [hostid]
jps执行样例:
D:DevelopJavajdk1.6.0_21in>jps-l
2388 D:Developglassfishin..modulesadmin-cli.jar
2764 com.sun.enterprise.glassfish.bootstrap.ASMain
3788 sun.tools.jps.Jps
2 jstat:虚拟机统计信息监视工具
jstat命令格式为:
jstat [option vmid[interval[s|ms][count]]]
参数interval和count代表查询间隔和次数,如果省略这两个参数,说明只查询一次。假设需要每250毫秒查询一次进程2764垃圾收集状况,一共查询20次,那命令应当是:
jstat -gc 2764 250 20
jstat执行样例: jstat -gcutil 2764
S0 S1 E O P YGC YGCT FGC FGCT GCT
0.00 0.00 6.20 41.42 47.20 16 0. 105 3 0.472 0.577
查询结果表明:这台服务器的新生代Eden区(E,表示Eden)使用了6.2%的空间,两个
Survivor区(S0、S1,表示Survivor0、Survivor1)里面都是空的,老年代(O,表示Old)和
永久代(P,表示Permanent)则分别使用了41.42%和47.20%的空间。程序运行以来共发生
Minor GC(YGC,表示Young GC)16次,总耗时0.105秒,发生Full GC(FGC,表示Full
GC)3次,Full GC总耗时(FGCT,表示Full GC Time)为0.472秒,所有GC总耗时(GCT,
表示GC Time)为0.577秒
3 jinfo:Java配置信息工具
jinfo命令格式:
jinfo [option] pid
执行样例:查询CMSInitiatingOccupancyFraction参数值。
C:>jinfo-flag CMSInitiatingOccupancyFraction 1444
-XX:CMSInitiatingOccupancyFraction=85
4 jmap:Java内存映像工具
jmap命令格式:
jmap [option] vmid
使用jmap生成dump文件
C:UsersIcyFenix>jmap-dump:format=b,file=eclipse.bin 3500
Dumping heap to C:UsersIcyFenixeclipse.bin……
Heap dump file created
5 jhat:虚拟机堆转储快照分析工具
使用jhat分析dump文件
C:UsersIcyFenix>jhat eclipse.bin Reading from eclipse.bin…… Dump file created Fri Nov 19 22:07:21 CST 2010 Snapshot read,resolving…… Resolving 1225951 objects…… Chasing references,expect 245 dots…… Eliminating duplicate references…… Snapshot resolved. Started HTTP server on port 7000 Server is ready.
用户在浏览器中键入http://localhost:7000/就可以看到分析结果
6 jstack:Java堆栈跟踪工具
jstack命令格式:
jstack[option]vmid
二. JDK的可视化工具
JDK中除了提供大量的命令行工具外,还有两个功能强大的可视化工具:JConsole和VisualVM
1 JConsole:Java监视与管理控制台
1.1 启动JConsole
通过JDK/bin目录下的“jconsole.exe”启动
1.2 内存监控
JConsole监视代码
/** * 内存占位符对象,一个OOMObject对象大约占64kb * -Xms 100m -Xmx 100m -XX:+UseSerialGC */ public class OOMObject { public byte[] placeholder = new byte[64*1024]; }
public class OOMObjectTest1 { public static void fillHeap(int num) throws InterruptedException { List<OOMObject> list = new ArrayList<OOMObject>(); for (int i = 0; i < num; i++) { Thread.sleep(100); list.add(new OOMObject()); } System.gc(); } public static void main(String[] args) throws InterruptedException { fillHeap(1000); } }
程序运行后,在“内存”页签中可以看到内存池Eden区的运行趋势呈现折线状,并且从柱状图可以看出,在1000次循环执行结束,运行了System.gc()后,虽然整个新生代Eden和Survivor区都基本被清空了,但是代表老年代的柱状图仍然保持峰值状态,说明被填充进堆中的数据在System.gc()方法执行之后仍然存活
1.3 线程监控
线程等待演示代码
public class OOMObjectTest2 { /** *线程死循环演示 */ public static void createBusyThread(){ Thread thread=new Thread(new Runnable(){ public void run(){ while(true)//第41行 ; } },"testBusyThread"); thread.start(); } /** *线程锁等待演示 */ public static void createLockThread(final Object lock){ Thread thread=new Thread(new Runnable(){ public void run(){ synchronized(lock){ try{ lock.wait(); }catch(InterruptedException e){ e.printStackTrace(); } } } },"testLockThread"); thread.start(); } public static void main(String[]args)throws Exception{ BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); br.readLine(); createBusyThread(); br.readLine(); Object obj=new Object(); createLockThread(obj); } }
程序运行后,首先在“线程”页签中选择main线程,堆栈追踪显示BufferedReader在readBytes方法中等待System.in的键盘输入, 这时线程为Runnable状态,Runnable状态的线程会被分配运行时间,但readBytes方法检查到流没有更新时会立刻归还执行令牌,这种等待只消耗很小的CPU资源。
键盘输入值后,接着监控testBusyThread线程,线程一直在执行空循环,从堆栈追踪中看到一直在MonitoringTest.java代码的41行停留,41行为:while(true)。这时候线程为Runnable状态,而且没有归还线程执行令牌的动作,会在空循环上用尽全部执行时间直到线程切换,这种等待会消耗较多的CPU资源
testLockThread线程在等待着lock对象的notify或notifyAll方法的出现,线程这时候处于WAITING状态,在被唤醒前不会被分配执行时间
死锁代码样例
public class SynAddRunalbe implements Runnable { int a,b; public SynAddRunalbe(int a,int b){ this.a=a; this.b=b; } public void run(){ synchronized(Integer.valueOf(a)){ synchronized(Integer.valueOf(b)){ System.out.println(a+b); } } } }
public class OOMObjectTest3 { public static void main(String[]args){ for(int i=0;i<100;i++){ new Thread(new SynAddRunalbe(1,2)).start(); new Thread(new SynAddRunalbe(2,1)).start(); } } }
出现线程死锁之后,点击JConsole线程面板的“检测到死锁”按钮,将出现一个新的“死锁”页签
2 VisualVM:多合一故障处理工具
2.1 启动JConsole
通过JDK/bin目录下的“jvisualvm.exe”启动
2.2 插件下载
“工具”→“插件”→“已下载”菜单,然后在弹出的对话框中指定nbm包路径便可进行安装,插件安装后存放在JDK_HOME/lib/visualvm/visualvm中
插件中心地址:http://Visualvm java.net/pluginscenters.html。
声明:本文是个人学习笔记,内容来自《深入理解Java虚拟机·JVM高级特性与最佳实践》周志明 与网络文章
以上是关于深入理解java虚拟机第二版虚拟机性能监控与故障处理工具的主要内容,如果未能解决你的问题,请参考以下文章