通过jstat工具来查看jvmstat monitor的值
接上之前发的几帖(1) (2) (3),再回过头来看看如果不是用Java API,有没有什么工具能直接看到某个Java进程的jvmstat的各个monitor的值。
Sun JDK自带的jstat工具其实就可以看到HotSpot支持的所有jvmstat信息,只不过官方文档上没把相关的隐藏参数写出来而已。
下面还是用例子来说明。这次的目标是查看一个跑在Windows XP SP3, Sun JDK 6 update 17上的Eclipse的状况。
首先用jps工具查出Eclipse进程的vmid:
D:\>jps1028 Jps1996 org.eclipse.equinox.launcher_1.0.201.R35x_v20090715.jar
好,目标就是ID为1996的进程。然后使用jstat,加上一个文档上没记录的-snap参数:
D:\>jstat -snap 1996java.ci.totalTime=11274276735java.cls.loadedClasses=15981java.cls.sharedLoadedClasses=0java.cls.sharedUnloadedClasses=0java.cls.unloadedClasses=53java.property.java.class.path="D:\editor\eclipse_jee\plugins/org.eclipse.equinox.launcher_1.0.201.R35x_v20090715.jar;lombok.jar"java.property.java.endorsed.dirs="C:\sdk\Java\jdk1.6.0_17\jre\lib\endorsed"java.property.java.ext.dirs="C:\sdk\Java\jdk1.6.0_17\jre\lib\ext;C:\WINDOWS\Sun\Java\lib\ext"java.property.java.home="C:\sdk\Java\jdk1.6.0_17\jre"java.property.java.library.path="C:\sdk\Java\jdk1.6.0_20\bin;.;C:\WINDOWS\Sun\Java\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\Perl\site\bin;C:\Perl\bin;D:\sdk\Python31\;D:\sdk\Ruby\bin;;C:\WINDOWS\System32\Wbem;C:\Program Files\ATI Technologies\ATI.ACE\Core-Static;C:\sdk\SlikSvn\bin\;C:\sdk\TortoiseSVN\bin;C:\sdk\TortoiseHg;C:\sdk\Git\cmd;D:\sdk\ChezScheme7.4d\bin\i3nt;C:\sdk\Graphviz2.26.3\bin;D:\sdk\GnuWin32\bin;C:\Program Files\Haskell\bin;D:\sdk\ghc-6.10.4\bin;D:\sdk\apache-maven-2.2.1\bin;D:\sdk\Python31\Scripts;D:\script;D:\sdk\apache-ant-1.7.1\bin"java.property.java.version="1.6.0_17"java.property.java.vm.info="mixed mode"java.property.java.vm.name="Java HotSpot(TM) Client VM"java.property.java.vm.specification.name="Java Virtual Machine Specification"java.property.java.vm.specification.vendor="Sun Microsystems Inc."java.property.java.vm.specification.version="1.0"java.property.java.vm.vendor="Sun Microsystems Inc."java.property.java.vm.version="14.3-b01"java.rt.vmArgs="-Dosgi.requiredJavaVersion=1.5 -Xms40m -Xmx512m -javaagent:lombok.jar -Xbootclasspath/a:lombok.jar -XX:MaxPermSize=256m"java.rt.vmFlags=""java.threads.daemon=18java.threads.live=23java.threads.livePeak=33java.threads.started=3743
这里已经可以看到很多信息,像是HotSpot的动态编译器用了多少时间,整个VM加载了多少个类卸载了多少个类,启动路径、参数,VM的版本等。不过前面一帖的列表里明明有更多的monitor,它们跑哪儿去了呢?
于是再多加一个-J-Djstat.showUnsupported=true参数来跑jstat:
D:\>jstat -J-Djstat.showUnsupported=true -snap 1996java.ci.totalTime=11274276735java.cls.loadedClasses=15981java.cls.sharedLoadedClasses=0java.cls.sharedUnloadedClasses=0java.cls.unloadedClasses=53java.property.java.class.path="D:\editor\eclipse_jee\plugins/org.eclipse.equinox.launcher_1.0.201.R35x_v20090715.jar;lombok.jar"java.property.java.endorsed.dirs="C:\sdk\Java\jdk1.6.0_17\jre\lib\endorsed"java.property.java.ext.dirs="C:\sdk\Java\jdk1.6.0_17\jre\lib\ext;C:\WINDOWS\Sun\Java\lib\ext"java.property.java.home="C:\sdk\Java\jdk1.6.0_17\jre"java.property.java.library.path="C:\sdk\Java\jdk1.6.0_20\bin;.;C:\WINDOWS\Sun\Java\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\Perl\site\bin;C:\Perl\bin;D:\sdk\Python31\;D:\sdk\Ruby\bin;;C:\WINDOWS\System32\Wbem;C:\Program Files\ATI Technologies\ATI.ACE\Core-Static;C:\sdk\SlikSvn\bin\;C:\sdk\TortoiseSVN\bin;C:\sdk\TortoiseHg;C:\sdk\Git\cmd;D:\sdk\ChezScheme7.4d\bin\i3nt;C:\sdk\Graphviz2.26.3\bin;D:\sdk\GnuWin32\bin;C:\Program Files\Haskell\bin;D:\sdk\ghc-6.10.4\bin;D:\sdk\apache-maven-2.2.1\bin;D:\sdk\Python31\Scripts;D:\script;D:\sdk\apache-ant-1.7.1\bin"java.property.java.version="1.6.0_17"java.property.java.vm.info="mixed mode"java.property.java.vm.name="Java HotSpot(TM) Client VM"java.property.java.vm.specification.name="Java Virtual Machine Specification"java.property.java.vm.specification.vendor="Sun Microsystems Inc."java.property.java.vm.specification.version="1.0"java.property.java.vm.vendor="Sun Microsystems Inc."java.property.java.vm.version="14.3-b01"java.rt.vmArgs="-Dosgi.requiredJavaVersion=1.5 -Xms40m -Xmx512m -javaagent:lombok.jar -Xbootclasspath/a:lombok.jar -XX:MaxPermSize=256m"java.rt.vmFlags=""java.threads.daemon=18java.threads.live=23java.threads.livePeak=33java.threads.started=3744sun.ci.compilerThread.0.compiles=6302sun.ci.compilerThread.0.method=""sun.ci.compilerThread.0.time=4923396sun.ci.compilerThread.0.type=1sun.ci.lastFailedMethod="org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor createTypeInfo"sun.ci.lastFailedType=1sun.ci.lastInvalidatedMethod=""sun.ci.lastInvalidatedType=0sun.ci.lastMethod="org/eclipse/ui/internal/layout/TrimArea computeWrappedTrim"sun.ci.lastSize=577sun.ci.lastType=1sun.ci.nmethodCodeSize=5622944sun.ci.nmethodSize=13224788sun.ci.osrBytes=16202sun.ci.osrCompiles=29sun.ci.osrTime=159843303sun.ci.standardBytes=1206710sun.ci.standardCompiles=6267sun.ci.standardTime=11114433432sun.ci.threads=1sun.ci.totalBailouts=6sun.ci.totalCompiles=6296sun.ci.totalInvalidates=0sun.cls.classInitTime=57799894653sun.cls.classLinkedTime=79687099728sun.cls.classVerifyTime=192186673173sun.cls.initializedClasses=11406sun.cls.isUnsyncloadClassSet=0sun.cls.jniDefineClassNoLockCalls=1sun.cls.jvmDefineClassNoLockCalls=106sun.cls.jvmFindLoadedClassNoLockCalls=0sun.cls.linkedClasses=13248sun.cls.loadInstanceClassFailRate=0sun.cls.loadedBytes=20912352sun.cls.methodBytes=13457952sun.cls.nonSystemLoaderLockContentionRate=62sun.cls.sharedLoadedBytes=0sun.cls.sharedUnloadedBytes=0sun.cls.systemLoaderLockContentionRate=0sun.cls.time=96533747082sun.cls.unloadedBytes=47848sun.cls.unsafeDefineClassCalls=106sun.gc.cause="No GC"sun.gc.collector.0.invocations=1035sun.gc.collector.0.lastEntryTime=340630839536481sun.gc.collector.0.lastExitTime=340630849279881sun.gc.collector.0.name="Copy"sun.gc.collector.0.time=9872748234sun.gc.collector.1.invocations=2950sun.gc.collector.1.lastEntryTime=530223797079243sun.gc.collector.1.lastExitTime=530224765895475sun.gc.collector.1.name="MSC"sun.gc.collector.1.time=2813934945510sun.gc.generation.0.agetable.bytes.00=0sun.gc.generation.0.agetable.bytes.01=343736sun.gc.generation.0.agetable.bytes.02=0sun.gc.generation.0.agetable.bytes.03=0sun.gc.generation.0.agetable.bytes.04=0sun.gc.generation.0.agetable.bytes.05=0sun.gc.generation.0.agetable.bytes.06=0sun.gc.generation.0.agetable.bytes.07=0sun.gc.generation.0.agetable.bytes.08=0sun.gc.generation.0.agetable.bytes.09=0sun.gc.generation.0.agetable.bytes.10=0sun.gc.generation.0.agetable.bytes.11=0sun.gc.generation.0.agetable.bytes.12=0sun.gc.generation.0.agetable.bytes.13=0sun.gc.generation.0.agetable.bytes.14=0sun.gc.generation.0.agetable.bytes.15=0sun.gc.generation.0.agetable.size=16sun.gc.generation.0.capacity=7864320sun.gc.generation.0.maxCapacity=41287680sun.gc.generation.0.minCapacity=3211264sun.gc.generation.0.name="new"sun.gc.generation.0.space.0.capacity=6291456sun.gc.generation.0.space.0.initCapacity=0sun.gc.generation.0.space.0.maxCapacity=33030144sun.gc.generation.0.space.0.name="eden"sun.gc.generation.0.space.0.used=742104sun.gc.generation.0.space.1.capacity=786432sun.gc.generation.0.space.1.initCapacity=0sun.gc.generation.0.space.1.maxCapacity=4128768sun.gc.generation.0.space.1.name="s0"sun.gc.generation.0.space.1.used=0sun.gc.generation.0.space.2.capacity=786432sun.gc.generation.0.space.2.initCapacity=0sun.gc.generation.0.space.2.maxCapacity=4128768sun.gc.generation.0.space.2.name="s1"sun.gc.generation.0.space.2.used=0sun.gc.generation.0.spaces=3sun.gc.generation.1.capacity=93532160sun.gc.generation.1.maxCapacity=495583232sun.gc.generation.1.minCapacity=38731776sun.gc.generation.1.name="old"sun.gc.generation.1.space.0.capacity=93532160sun.gc.generation.1.space.0.initCapacity=38731776sun.gc.generation.1.space.0.maxCapacity=495583232sun.gc.generation.1.space.0.name="old"sun.gc.generation.1.space.0.used=51151056sun.gc.generation.1.spaces=1sun.gc.generation.2.capacity=86245376sun.gc.generation.2.maxCapacity=268435456sun.gc.generation.2.minCapacity=12582912sun.gc.generation.2.name="perm"sun.gc.generation.2.space.0.capacity=86245376sun.gc.generation.2.space.0.initCapacity=12582912sun.gc.generation.2.space.0.maxCapacity=268435456sun.gc.generation.2.space.0.name="perm"sun.gc.generation.2.space.0.used=86128864sun.gc.generation.2.spaces=1sun.gc.lastCause="System.gc()"sun.gc.policy.collectors=2sun.gc.policy.desiredSurvivorSize=393216sun.gc.policy.generations=3sun.gc.policy.maxTenuringThreshold=15sun.gc.policy.name="Copy:MSC"sun.gc.policy.tenuringThreshold=15sun.gc.tlab.alloc=40188sun.gc.tlab.allocThreads=7sun.gc.tlab.fastWaste=0sun.gc.tlab.fills=7sun.gc.tlab.gcWaste=36050sun.gc.tlab.maxFastWaste=0sun.gc.tlab.maxFills=1sun.gc.tlab.maxGcWaste=18546sun.gc.tlab.maxSlowAlloc=0sun.gc.tlab.maxSlowWaste=0sun.gc.tlab.slowAlloc=0sun.gc.tlab.slowWaste=0sun.os.hrt.frequency=2992520000sun.os.hrt.ticks=530286231578049sun.perfdata.majorVersion=2sun.perfdata.minorVersion=0sun.perfdata.overflow=0sun.perfdata.size=65536sun.perfdata.timestamp=2374418412sun.perfdata.used=14496sun.property.sun.boot.class.path="C:\sdk\Java\jdk1.6.0_17\jre\lib\resources.jar;C:\sdk\Java\jdk1.6.0_17\jre\lib\rt.jar;C:\sdk\Java\jdk1.6.0_17\jre\lib\sunrsasign.jar;C:\sdk\Java\jdk1.6.0_17\jre\lib\jsse.jar;C:\sdk\Java\jdk1.6.0_17\jre\lib\jce.jar;C:\sdk\Java\jdk1.6.0_17\jre\lib\charsets.jar;C:\sdk\Java\jdk1.6.0_17\jre\classes;lombok.jar"sun.property.sun.boot.library.path="C:\sdk\Java\jdk1.6.0_17\jre\bin"sun.rt._sync_ContendedLockAttempts=111725sun.rt._sync_Deflations=25166sun.rt._sync_EmptyNotifications=0sun.rt._sync_FailedSpins=0sun.rt._sync_FutileWakeups=3979sun.rt._sync_Inflations=25184sun.rt._sync_MonExtant=14336sun.rt._sync_MonInCirculation=0sun.rt._sync_MonScavenged=0sun.rt._sync_Notifications=101533sun.rt._sync_Parks=125094sun.rt._sync_PrivateA=0sun.rt._sync_PrivateB=0sun.rt._sync_SlowEnter=0sun.rt._sync_SlowExit=0sun.rt._sync_SlowNotify=0sun.rt._sync_SlowNotifyAll=0sun.rt._sync_SuccessfulSpins=0sun.rt.applicationTime=527384947891815sun.rt.createVmBeginTime=1288056340317sun.rt.createVmEndTime=1288056341110sun.rt.internalVersion="Java HotSpot(TM) Client VM (14.3-b01) for windows-x86 JRE (1.6.0_17-b04), built on Oct 11 2009 00:52:06 by "java_re" with MS VC++ 7.1"sun.rt.interruptedBeforeIO=0sun.rt.interruptedDuringIO=0sun.rt.javaCommand="D:\editor\eclipse_jee\plugins/org.eclipse.equinox.launcher_1.0.201.R35x_v20090715.jar -os win32 -ws win32 -arch x86 -showsplash -launcher D:\editor\eclipse_jee\eclipse.exe -name Eclipse --launcher.library D:\editor\eclipse_jee\plugins/org.eclipse.equinox.launcher.win32.win32.x86_1.0.200.v20090519\eclipse_1206.dll -startup D:\editor\eclipse_jee\plugins/org.eclipse.equinox.launcher_1.0.201.R35x_v20090715.jar -exitdata a0c_44 -product org.eclipse.epp.package.jee.product -vm C:/sdk/Java/jdk1.6.0_17/bin/javaw.exe -vmargs -Dosgi.requiredJavaVersion=1.5 -Xms40m -Xmx512m -javaagent:lombok.jar -Xbootclasspath/a:lombok.jar -XX:MaxPermSize=256m -jar D:\editor\eclipse_jee\plugins/org.eclipse.equinox.launcher_1.0.201.R35x_v20090715.jar"sun.rt.jvmCapabilities="1000000000000000000000000000000000000000000000000000000000000000"sun.rt.jvmVersion=235077633sun.rt.safepointSyncTime=971909442sun.rt.safepointTime=2837457553374sun.rt.safepoints=8467sun.rt.threadInterruptSignaled=0sun.rt.vmInitDoneTime=1288056340674sun.threads.vmOperationTime=2824580448243
嗯现在信息就全了不是?
HotSpot并不是没记录内部信息,只是还没什么特别好的工具把它们整理、显示出来而已。这点上JRockit Mission Control/Flight Recorder就强悍多了。
===========================================================
P.S. 有人问为什么VisualVM的VisualGC插件里的histogram面板有时候会显示不出东西。其实很简单:只是这功能不支持ParallelGC而已。
VisualGC需要通过jvmstat API来读取名为"sun.gc.generation.0.agetable.size"的PerfData计数器的值,在visualgc.jar里的com.sun.jvmstat.tools.visualgc.MonitoredVmModel.initialize_common()。
这个计数器是在全局的ageTable初始化时创建的。HotSpot VM里DefNew/ParNew/G1等涉及young GC的实现都用到了全局的ageTable,但ParallelScavange则没有。于是在使用UseParallelGC/UseParallelOldGC时,这个计数器就不存在,VisualGC就会认为目标JVM不支持显示histogram的功能。
(注:Windows 7上的话JDK7里的VisualVM的VisualGC插件的内容可以在%User%/AppData/Roaming/.visualvm/7/modules/com-sun-tools-visualvm-modules-visualgc.jar 以及 %User%/AppData/Roaming/.visualvm/7/modules/ext/visualgc.jar 找到。
VisualGC插件自身没开源,所以就不能指望从visualvm.java.net那边找到它的源码了)