目录
虚拟机学习系列 - 1 - 运行时数据区域
虚拟机学习系列 - 2 - 垃圾收集概述
虚拟机学习系列 - 3 - 垃圾收集算法
虚拟机学习系列 - 4 - 垃圾收集器
虚拟机学习系列 - 5 - 内存分配与回收策略
虚拟机学习系列 - 6 - JDK工具
虚拟机学习系列 - 附 - 虚拟机参数
虚拟机学习系列 - 附 - OQL(对象查询语言)
JDK命令行工具
简单介绍下面6个
1.jps(JVM Process Status Tool)
2.jstat(JVM Statistics Monitoring Tool)
3.jinfo(Configuration Info for Java)
4.jmap(Memory Map for Java)
5.jhat(JVM Heap Dump Browser)
6.jstack(Stack Trace for Java)
1.jps
主要功能:可以列出正在运行的虚拟机进程
显示虚拟机执行主类(main函数所在的类)
这些进程的本地虚拟机唯一ID
部分选项:-q:只输出LVMID,省略主类的名称
-m:输出虚拟机进程启动时传给主类main()函数的参数
-l:输出主类的全类名,如果进程执行的是Jar包,输出Jar路径
-v:输出虚拟机进程启动时JVM参数
命令格式:jps [option] [hostid]
示例:
C:\Program Files\Java\jdk1.6.0_30\bin>jps -v
3972 Jps -Dapplication.home=C:\Program Files\Java\jdk1.6.0_30 -Xms8m
6012 -Xms128m -Xmx512m -XX:MaxPermSize=256m -Dosgi.requiredJavaVersion=1.5 [email protected]/Applica
[email protected]/Application Data/XMind/configuration-cathy
692 -Dosgi.requiredJavaVersion=1.5 -Xms512m -Xmx512m -Xmn256m -Xverify=none -XX:PermSize=96m -XX:MaxPermSize=256m
2.jstat
主要功能:可以显示本地或远程虚拟机进程中类装载、内存、垃圾收集、JIT编译等运行数据(显示远程虚拟机信息需要远程主机提供RMI支持)
部分选项:-class:监视类装载、卸载数量、总空间及类装载所耗费的时间
-gc:监听Java堆状况,包括Eden区、两个Survivor区、老年代、永久代等的容量,以用空间、GC时间合计等信息
-gccapacity:监视内容与-gc基本相同,但输出主要关注java堆各个区域使用到的最大和最小空间
-gcutil:监视内容与-gc基本相同,但输出主要关注已使用空间占总空间的百分比
-gccause:与-gcutil功能一样,但是会额外输出导致上一次GC产生的原因
-gcnew:监视新生代GC状况
-gcnewcapacity:监视内同与-gcnew基本相同,输出主要关注使用到的最大和最小空间
-gcold:监视老年代GC情况
-gcoldcapacity:监视内同与-gcold基本相同,输出主要关注使用到的最大和最小空间
-gcpermcapacity:输出永久代使用到最大和最小空间
-compiler:输出JIT编译器编译过的方法、耗时等信息
-printcompilation:输出已经被JIT编译的方法
命令格式:jstat [option vmid [interval[s|ms] [count]] ]
对命令格式中VMID和LVMID特别说明:如果是本地虚拟机进程,VMID和LVMID是一致的,如果是远程虚拟机进程,那么VMID格式是:[protocol:][//]lvmid[@hostname[:port]/servername],如果省略interval和count,则只查询一次
示例:
C:\Program Files\Java\jdk1.6.0_30\bin>jstat -gc 6012 500 5
S0C S1C S0U S1U EC EU OC OU PC PU YGC YGCT FGC FGCT GCT
4352.0 4352.0 0.0 66.8 35072.0 33768.3 87424.0 72125.8 24320.0 24313.0 47 0.600 2 0.272 0.871
4352.0 4352.0 0.0 66.8 35072.0 33768.3 87424.0 72125.8 24320.0 24313.0 47 0.600 2 0.272 0.871
4352.0 4352.0 0.0 66.8 35072.0 33768.3 87424.0 72125.8 24320.0 24313.0 47 0.600 2 0.272 0.871
4352.0 4352.0 0.0 66.8 35072.0 33768.3 87424.0 72125.8 24320.0 24313.0 47 0.600 2 0.272 0.871
4352.0 4352.0 0.0 66.8 35072.0 33768.3 87424.0 72125.8 24320.0 24313.0 47 0.600 2 0.272 0.871
查询进程6012垃圾收集情况:0.5秒一次共五次
3.jinfo
主要功能:实时查看和调整虚拟机的各项参数(可以显示未被显示指定的参数的系统默认值,不少功能在windows受限)
部分选项:-flag:显示未被显示指定的参数的系统默认值
-sysprops:打印虚拟机进程的System.getProperties(),可以使用-flag [+|-]name或-flag name=value修改部分参数
命令格式:jinfo [option] pid
示例:
C:\Program Files\Java\jdk1.6.0_30\bin>jinfo -flag SurvivorRatio 6012
-XX:SurvivorRatio=8
4.jmap
主要功能:获取堆转储快照
查询finalize执行队列
查询java堆和永久代的详细信息(如空间使用率、当前使用的收集器)
部分选项:-dump:生成java堆转储快照
-finalizerinfo:显示在F-Queue中等待Finalizer线程执行finalize方法的对象(只在Linux/Solaris下有效)
-heap:显示java堆详细信息(只在Linux/Solaris下有效)
-histo:显示堆中对象统计信息
-permstat:以ClassLoader为统计口径显示永久代内存状态(只在Linux/Solaris下有效)
-F:当虚拟机进程对-dump选项没有响应时,可使用这个选项强制生成dump快照(只在Linux/Solaris下有效)
命令格式:jmap [option] vmid
示例:
C:\Program Files\Java\jdk1.6.0_30\bin>jmap -dump:format=b,file=d:xmind.hprof 6012
Dumping heap to D:\xmind.hprof ...
Heap dump file created
5.jhat
主要功能:jhat,用于分析heap dump文件(用mat代替此工具)
6jstack
主要功能:生成虚拟机的线程快照,threaddump或javacore文件(线程快照是虚拟机每一条线程正在执行的方法,目的是定位线程出现长时间停顿的原因)
部分选项:-F:当正常输出的请求不被响应时,强制输出线程堆栈
-l:除堆栈外,显示关于锁的附加信息
-m:如果调用到本地方法的话,可以显示C/C++的堆栈
命令格式:jstack [option] vmid
示例:
C:\Program Files\Java\jdk1.6.0_30\bin>jstack -l 6012
2012-05-13 11:57:35
Full thread dump Java HotSpot(TM) Client VM (20.5-b03 mixed mode, sharing):
"Java2D Disposer" daemon prio=10 tid=0x39cc9c00 nid=0x146c in Object.wait() [0x079af000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x12f94a08> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(Unknown Source)
- locked <0x12f94a08> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(Unknown Source)
at sun.java2d.Disposer.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Locked ownable synchronizers:
- None
"XMind: Auto Save Temporary Workbooks" daemon prio=2 tid=0x05610400 nid=0xaf8 waiting on condition [0x0758f000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at org.xmind.ui.internal.editor.WorkbookRefManager$AutoHibernateJob.run(WorkbookRefManager.java:221)
at java.lang.Thread.run(Unknown Source)
Locked ownable synchronizers:
- None
"Worker-2" prio=6 tid=0x055c8000 nid=0x14cc in Object.wait() [0x073bf000]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x1291e468> (a org.eclipse.core.internal.jobs.WorkerPool)
at org.eclipse.core.internal.jobs.WorkerPool.sleep(WorkerPool.java:185)
- locked <0x1291e468> (a org.eclipse.core.internal.jobs.WorkerPool)
at org.eclipse.core.internal.jobs.WorkerPool.startJob(WorkerPool.java:217)
at org.eclipse.core.internal.jobs.Worker.run(Worker.java:51)
Locked ownable synchronizers:
- None
……
JDK可视化工具
1.JConsole(Java Monitoring and Management Console)
2.VisualVM(All-in-One Java Toubleshooting Tool)
内存页
线程页
下面是书中几个示例(线程死循环,线程锁等待)
public static void createBusyThread(){ new Thread("testBusyThread"){ public void run(){ while(true);//11行 } }.start(); } public static void createLockThread(final Object lock){ new Thread("testLockThread"){ public void run(){ synchronized (lock) { try { lock.wait();//21行 } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); } public static void main(String[] args) throws IOException { BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in)); bufferedReader.readLine();//32行 Main.createBusyThread(); bufferedReader.readLine(); Main.createLockThread(new Object()); }
在线程页中查看
堆栈追踪:
java.io.FileInputStream.readBytes(Native Method)
java.io.FileInputStream.read(Unknown Source)
java.io.BufferedInputStream.read1(Unknown Source)
java.io.BufferedInputStream.read(Unknown Source)
- 已锁定 java.io.BufferedInputStream@1c293f8
sun.nio.cs.StreamDecoder.readBytes(Unknown Source)
sun.nio.cs.StreamDecoder.implRead(Unknown Source)
sun.nio.cs.StreamDecoder.read(Unknown Source)
- 已锁定 java.io.InputStreamReader@180a8b7
java.io.InputStreamReader.read(Unknown Source)
java.io.BufferedReader.fill(Unknown Source)
java.io.BufferedReader.readLine(Unknown Source)
- 已锁定 java.io.InputStreamReader@180a8b7
java.io.BufferedReader.readLine(Unknown Source)
jvmTest.Main.main(Main.java:32)
运行过bufferedReader.readLine();之后可以看到testBusyThread的信息,现在右侧选中线程testBusyThread
名称: testBusyThread
状态: RUNNABLE
阻塞总数:0 等待总数: 0
堆栈追踪:
jvmTest.Main$1.run(Main.java:11)
testLockThread也一样
名称: testLockThread
状态:WAITING 在 java.lang.Object@1921360 上
阻塞总数:0 等待总数: 1
堆栈追踪:
java.lang.Object.wait(Native Method)
java.lang.Object.wait(Object.java:485)
jvmTest.Main$2.run(Main.java:21)
死锁的测试我们用多线程学习系列 - 1 - Single Threaded Execution Pattern 中的代码来测试吧
public class ThreadTest { public static class Tool{ private final String name; public Tool(String name){ this.name = name; } public String toString(){ return "[" + name + "]"; } } public static class EaterThread extends Thread{ private String name; private Tool leftHand; private Tool rightHand; public EaterThread(String name, Tool leftHand, Tool rightHand){ super(name); this.name = name; this.leftHand = leftHand; this.rightHand = rightHand; } public void run(){ while(true){ eat();//30行 } } public void eat(){ synchronized (leftHand) { System.out.println(name + " takes up " + leftHand + "(left.)"); synchronized (rightHand) { System.out.println(name + " takes up " + rightHand + "(right.)"); System.out.println(name + " is eating now ,yam yam!"); System.out.println(name + " put down " + rightHand + "(right.)"); } System.out.println(name + " put down " + leftHand + "(left.)"); } } } public static void main(String[] args) { Tool spoon = new Tool("Spoon"); Tool fork = new Tool("Fork"); new EaterThread("Alice", spoon, fork).start(); new EaterThread("Bobby", fork, spoon).start(); } }
结果如下
名称: Alice
状态:BLOCKED 在 ThreadTest$Tool@1f31652 上,拥有者: Bobby
阻塞总数:1 等待总数: 0
堆栈追踪:
ThreadTest$EaterThread.eat(ThreadTest.java:38)
- 已锁定 ThreadTest$Tool@778255
ThreadTest$EaterThread.run(ThreadTest.java:30)
Bobby 的结果就不再列出了
就不再总结了
转贴请保留以下链接
本人blog地址
http://su1216.iteye.com/
http://blog.csdn.net/su1216/