1.jstack介紹
如果java程序崩潰生成core文件,jstack工具可以用來獲得core文件的java stack和native stack的信息,從而可以輕松地知道java程序是如何崩潰和在程序何處發生問題。另外,jstack工具還可以附屬到正在運行的java程序中,看到當時運行的java程序的java stack和native stack的信息, 如果現在運行的java程序呈現hung的狀態,jstack是非常有用的。
命令格式
$jstack [ option ] pid
$jstack [ option ] executable core
$jstack [ option ] [server-id@]remote-hostname-or-IP
參數說明:
pid: java應用程序的進程號,一般可以通過jps來獲得;
executable:產生core dump的java可執行程序;
core:打印出的core文件;
remote-hostname-or-ip:遠程debug服務器的名稱或IP;
server-id: 唯一id,假如一台主機上多個遠程debug服務;
示例:
$jstack –l 23561
線程分析:
一般情況下,通過jstack輸出的線程信息主要包括:jvm自身線程、用戶線程等。其中jvm線程會在jvm啟動時就會存在。對於用戶線程則是在用戶訪問時才會生成。
l jvm線程:
在線程中,有一些 JVM內部的后台線程,來執行譬如垃圾回收,或者低內存的檢測等等任務,這些線程往往在JVM初始化的時候就存在,如下所示:
"Attach Listener" daemon prio=10 tid=0x0000000052fb8000 nid=0xb8f waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers: - None destroyJavaVM" prio=10 tid=0x00002aaac1225800 nid=0x7208 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers: - None |
l 用戶級別的線程
還有一類線程是用戶級別的,它會根據用戶請求的不同而發生變化。該類線程的運行情況往往是我們所關注的重點。而且這一部分也是最容易產生死鎖的地方。
"qtp496432309-42" prio=10 tid=0x00002aaaba2a1800 nid=0x7580 waiting on condition [0x00000000425e9000] java.lang.Thread.State: TIMED_WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x0000000788cfb020> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:198) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2025) at org.eclipse.jetty.util.BlockingArrayQueue.poll(BlockingArrayQueue.java:320) at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:479) at java.lang.Thread.run(Thread.java:662)
Locked ownable synchronizers: - None |
從上述的代碼示例中我們可以看到該用戶線程的以下幾類信息:
Ø 線程的狀態:waiting on condition(等待條件發生)
Ø 線程的調用情況;
Ø 線程對資源的鎖定情況;
線程的狀態分析:
正如我們剛看到的那樣,線程的狀態是一個重要的指標,它會顯示在線程每行結尾的地方。那么線程常見的有哪些狀態呢?線程在什么樣的情況下會進入這種狀態呢?我們能從中發現什么線索?
l Runnable
該狀態表示線程具備所有運行條件,在運行隊列中准備操作系統的調度,或者正在運行。
l Waiton condition
該狀態出現在線程等待某個條件的發生。具體是什么原因,可以結合stacktrace來分析。最常見的情況是線程在等待網絡的讀寫,比如當網絡數據沒有准備好讀時,線程處於這種等待狀態,而一旦有數據准備好讀之后,線程會重新激活,讀取並處理數據。在 Java引入 NIO之前,對於每個網絡連接,都有一個對應的線程來處理網絡的讀寫操作,即使沒有可讀寫的數據,線程仍然阻塞在讀寫操作上,這樣有可能造成資源浪費,而且給操作系統的線程調度也帶來壓力。在 NIO里采用了新的機制,編寫的服務器程序的性能和可擴展性都得到提高。
如果發現有大量的線程都在處在 Wait on condition,從線程 stack看, 正等待網絡讀寫,這可能是一個網絡瓶頸的征兆。因為網絡阻塞導致線程無法執行。一種情況是網絡非常忙,幾乎消耗了所有的帶寬,仍然有大量數據等待網絡讀寫;另一種情況也可能是網絡空閑,但由於路由等問題,導致包無法正常的到達。所以要結合系統的一些性能觀察工具來綜合分析,比如 netstat統計單位時間的發送包的數目,如果很明顯超過了所在網絡帶寬的限制 ; 觀察 cpu的利用率,如果系統態的 CPU時間,相對於用戶態的 CPU時間比例較高;如果程序運行在 Solaris 10平台上,可以用 dtrace工具看系統調用的情況,如果觀察到 read/write的系統調用的次數或者運行時間遙遙領先;這些都指向由於網絡帶寬所限導致的網絡瓶頸。
另外一種出現 Wait on condition的常見情況是該線程在 sleep,等待 sleep的時間到了時候,將被喚醒。
l Waitingfor monitor entry 和 in Object.wait()
在多線程的 JAVA程序中,實現線程之間的同步,就要說說Monitor。Monitor是Java中用以實現線程之間的互斥與協作的主要手段,它可以看成是對象或者 Class的鎖。每一個對象都有,也僅有一個 monitor。下面這個圖,描述了線程和 Monitor之間關系,以及線程的狀態轉換圖:
從圖中可以看出,每個 Monitor在某個時刻,只能被一個線程擁有,該線程就是 “Active Thread”,而其它線程都是 “Waiting Thread”,分別在兩個隊列 “ Entry Set”和 “Wait Set”里面等候。在 “Entry Set”中等待的線程狀態是 “Waiting for monitorentry”,而在 “Wait Set”中等待的線程狀態是“in Object.wait()”。
先看 “Entry Set”里面的線程。我們稱被 synchronized保護起來的代碼段為臨界區。當一個線程申請進入臨界區時,它就進入了 “Entry Set”隊列。對應的 code就像:
synchronized(obj){
.........
}
這時有兩種可能性:
該 monitor不被其它線程擁有,Entry Set里面也沒有其它等待線程。本線程即成為相應類或者對象的 Monitor的 Owner,執行臨界區的代碼 。此時線程將處於Runnable狀態;
該 monitor被其它線程擁有,本線程在 Entry Set隊列中等待。此時dump的信息顯示“waiting for monitor entry”。
"Thread-0" prio=10 tid=0x08222eb0 nid=0x9 waiting for monitor entry [0xf927b000..0xf927bdb8] at testthread.WaitThread.run(WaitThread.java:39) |
臨界區的設置,是為了保證其內部的代碼執行的原子性和完整性。但是因為臨界區在任何時間只允許線程串行通過,這和我們多線程的程序的初衷是相反的。如果在多線程的程序中,大量使用 synchronized,或者不適當的使用了它,會造成大量線程在臨界區的入口等待,造成系統的性能大幅下降。如果在線程 DUMP中發現了這個情況,應該審查源碼,改進程序。
現在我們再來看現在線程為什么會進入 “Wait Set”。當線程獲得了 Monitor,進入了臨界區之后,如果發現線程繼續運行的條件沒有滿足,它則調用對象(一般就是被 synchronized 的對象)的 wait() 方法,放棄了 Monitor,進入 “Wait Set”隊列。只有當別的線程在該對象上調用了 notify() 或者 notifyAll() , “ Wait Set”隊列中線程才得到機會去競爭,但是只有一個線程獲得對象的Monitor,恢復到運行態。在 “Wait Set”中的線程, DUMP中表現為: in Object.wait(),類似於:
"Thread-1" prio=10 tid=0x08223250 nid=0xa in Object.wait() [0xef47a000..0xef47aa38] at java.lang.Object.wait(Native Method) - waiting on <0xef63beb8> (a java.util.ArrayList) at java.lang.Object.wait(Object.java:474) at testthread.MyWaitThread.run(MyWaitThread.java:40) - locked <0xef63beb8> (a java.util.ArrayList) at java.lang.Thread.run(Thread.java:595) |
仔細觀察上面的 DUMP信息,你會發現它有以下兩行:
² locked <0xef63beb8> (ajava.util.ArrayList)
² waiting on <0xef63beb8> (ajava.util.ArrayList)
這里需要解釋一下,為什么先 lock了這個對象,然后又 waiting on同一個對象呢?讓我們看看這個線程對應的代碼:
synchronized(obj){
.........
obj.wait();
.........
}
線程的執行中,先用 synchronized 獲得了這個對象的 Monitor(對應於 locked <0xef63beb8> )。當執行到 obj.wait(), 線程即放棄了 Monitor的所有權,進入 “wait set”隊列(對應於 waiting on<0xef63beb8> )。
往在你的程序中,會出現多個類似的線程,他們都有相似的 dump也可能是正常的。比如,在程序中有多個服務線程,設計成從一個隊列里面讀取請求數據。這個隊列就是 lock以及 waiting on的對象。當隊列為空的時候,這些線程都會在這個隊列上等待,直到隊列有了數據,這些線程被notify,當然只有一個線程獲得了 lock,繼續執行,而其它線程繼續等待。
2.jmap
Jmap是一個可以輸出所有內存中對象的工具,甚至可以將VM 中的heap,以二進制輸出成文本。打印出某個Java進程(使用pid)內存內的,所有‘對象’的情況(如:產生那些對象,及其數量)。
使用方法 jmap -histo pid。如果使用SHELL ,可采用jmap -histo pid>a.log日志將其保存到文件中,在一段時間后,使用文本對比工具,可以對比出GC回收了哪些對象。jmap -dump:format=b,file=outfile 3024可以將3024進程的內存heap輸出出來到outfile文件里,再配合MAT(內存分析工具)。
命令格式
l jmap [ option ] pid
l jmap [ option ] executable core
l jmap [ option ] [server-id@]remote-hostname-or-IP
1)、options:
l executable :產生core dump的java可執行程序;
l core 將被打印信息的core dump文件;
l remote-hostname-or-IP 遠程debug服務的主機名或ip;
l server-id 唯一id,假如一台主機上多個遠程debug服務;
2)、基本參數:
Ø -dump:[live,]format=b,file=<filename> 使用hprof二進制形式,輸出jvm的heap內容到文件=. live子選項是可選的,假如指定live選項,那么只輸出活的對象到文件.
$jmap–dump:live,format=b,file=aaa.bin 3772
Ø -finalizerinfo 打印正等候回收的對象的信息
$jmap -finalizerinfo 3772
Attaching to process ID 3772, please wait... Debugger attached successfully. Server compiler detected. JVM version is 20.0-b11 Number of objects pending for finalization: 0 (等候回收的對象為0個) |
Ø -heap 打印heap的概要信息,GC使用的算法,heap的配置及wise heap的使用情況.
$jmap –heap 3772
using parallel threads in the new generation. ##新生代采用的是並行線程處理方式 using thread-local object allocation. Concurrent Mark-Sweep GC ##同步並行垃圾回收
Heap Configuration: ##堆配置情況 MinHeapFreeRatio = 40 ##最小堆使用比例 MaxHeapFreeRatio = 70 ##最大堆可用比例 MaxHeapSize = 2147483648 (2048.0MB) ##最大堆空間大小 NewSize = 268435456 (256.0MB) ##新生代分配大小 MaxNewSize = 268435456 (256.0MB) ##最大可新生代分配大小 OldSize = 5439488 (5.1875MB) ##老生代大小 NewRatio = 2 ##新生代比例 SurvivorRatio = 8 ##新生代與suvivor的比例 PermSize = 134217728 (128.0MB) ##perm區大小 MaxPermSize = 134217728 (128.0MB) ##最大可分配perm區大小
Heap Usage: ##堆使用情況 New Generation (Eden + 1 Survivor Space): ##新生代(伊甸區 + survior空間) capacity = 241631232 (230.4375MB) ##伊甸區容量 used = 77776272 (74.17323303222656MB) ##已經使用大小 free = 163854960 (156.26426696777344MB) ##剩余容量 32.188004570534986% used ##使用比例 Eden Space: ##伊甸區 capacity = 214827008 (204.875MB) ##伊甸區容量 used = 74442288 (70.99369812011719MB) ##伊甸區使用 free = 140384720 (133.8813018798828MB) ##伊甸區當前剩余容量 34.65220164496263% used ##伊甸區使用情況 From Space: ##survior1區 capacity = 26804224 (25.5625MB) ##survior1區容量 used = 3333984 (3.179534912109375MB) ##surviror1區已使用情況 free = 23470240 (22.382965087890625MB) ##surviror1區剩余容量 12.43827838477995% used ##survior1區使用比例 To Space: ##survior2 區 capacity = 26804224 (25.5625MB) ##survior2區容量 used = 0 (0.0MB) ##survior2區已使用情況 free = 26804224 (25.5625MB) ##survior2區剩余容量 0.0% used ## survior2區使用比例 concurrent mark-sweep generation: ##老生代使用情況 capacity = 1879048192 (1792.0MB) ##老生代容量 used = 30847928 (29.41887664794922MB) ##老生代已使用容量 free = 1848200264 (1762.5811233520508MB) ##老生代剩余容量 1.6416783843721663% used ##老生代使用比例 Perm Generation: ##perm區使用情況 capacity = 134217728 (128.0MB) ##perm區容量 used = 47303016 (45.111671447753906MB) ##perm區已使用容量 free = 86914712 (82.8883285522461MB) ##perm區剩余容量 35.24349331855774% used ##perm區使用比例 |
Ø -histo[:live] 打印每個class的實例數目,內存占用,類全名信息. VM的內部類名字開頭會加上前綴”*”. 如果live子參數加上后,只統計活的對象數量.
$jmap–histo:live 3772
num #instances #bytes class name ---------------------------------------------- 1: 65220 9755240 <constMethodKlass> 2: 65220 8880384 <methodKlass> 3: 11721 8252112 [B 4: 6300 6784040 <constantPoolKlass> 5: 75224 6218208 [C 6: 93969 5163280 <symbolKlass> 7: 6300 4854440 <instanceKlassKlass> 8: 5482 4203152 <constantPoolCacheKlass> 9: 72097 2307104 java.lang.String 10: 15102 2289912 [I 11: 4089 2227728 <methodDataKlass> 12: 28887 1386576 org.apache.velocity.runtime.parser.Token 13: 6792 706368 java.lang.Class 14: 7445 638312 [Ljava.util.HashMap$Entry; 15: 8770 607040 [S 16: 17802 569664 java.lang.ref.WeakReference 17: 9538 472688 [[I 18: 8439 470440 [Ljava.lang.Object; 19: 5168 454784 java.lang.reflect.Method 20: 12559 401888 java.util.HashMap$Entry 21: 3730 358080 org.apache.velocity.runtime.parser.node.ASTReference 22: 4373 279872 org.apache.velocity.runtime.parser.node.ASTText 23: 463 270392 <objArrayKlassKlass> 24: 6695 267800 java.lang.ref.SoftReference 25: 5198 249504 java.util.HashMap 26: 2871 206712 org.apache.velocity.runtime.parser.node.ASTIdentifier 27: 7526 180624 org.apache.velocity.util.introspection.Info 28: 4441 177640 java.util.LinkedHashMap$Entry 29: 5550 177600 java.util.concurrent.locks.ReentrantLock$NonfairSync 30: 5723 175272 [Lorg.apache.velocity.runtime.parser.node.Node; 31: 4473 156904 [Ljava.lang.String; 32: 2773 155288 java.beans.MethodDescriptor 33: 6264 150336 java.util.ArrayList |
Ø -permstat 打印classload和jvm heap長久層的信息. 包含每個classloader的名字,活潑性,地址,父classloader和加載的class數量. 另外,內部String的數量和占用內存數也會打印出來.
$jmap -permstat 3772
class_loader classes bytes parent_loader alive? type
<bootstrap> 2172 13144040 null live <internal> 0x00000007882d7ab8 0 0 0x0000000788106c00 dead java/util/ResourceBundle$RBClassLoader@0x00000007f83b0388 0x0000000788c15ca8 1 3136 0x00000007880213d8 dead sun/reflect/DelegatingClassLoader@0x00000007f80686e0 0x0000000788fb1718 1 1968 0x00000007880213d8 dead sun/reflect/DelegatingClassLoader@0x00000007f80686e0 0x00000007882d0f08 1 2008 0x00000007880213d8 dead sun/reflect/DelegatingClassLoader@0x00000007f80686e0 0x0000000788176c60 1 3112 0x00000007880213d8 dead sun/reflect/DelegatingClassLoader@0x00000007f80686e0 0x0000000788a7e018 1 3144 0x00000007880213d8 dead sun/reflect/DelegatingClassLoader@0x00000007f80686e0 0x0000000788f515d0 1 1984 0x00000007880213d8 dead sun/reflect/DelegatingClassLoader@0x00000007f80686e0 0x000000078829a2c8 1 3112 0x00000007880213d8 dead sun/reflect/DelegatingClassLoader@0x00000007f80686e0 0x0000000788fab478 1 3128 null dead sun/reflect/DelegatingClassLoader@0x00000007f80686e0 0x0000000788030fd8 1 3112 0x00000007880213d8 dead sun/reflect/DelegatingClassLoader@0x00000007f80686e0 0x0000000788d46048 1 3144 0x00000007880213d8 dead sun/reflect/DelegatingClassLoader@0x00000007f80686e0 0x000000078816f6f0 1 3144 null dead sun/reflect/DelegatingClassLoader@0x00000007f80686e0 0x0000000788c18850 1 3112 0x00000007880213d8 dead sun/reflect/DelegatingClassLoader@0x00000007f80686e0 |
Ø -F 強迫.在pid沒有相應的時候使用-dump或者-histo參數. 在這個模式下,live子參數無效.
Ø -h | -help 打印輔助信息
Ø -J 傳遞參數給jmap啟動的jvm.
3.Jstat
Jstat是JDK自帶的一個輕量級小工具。全稱“Java Virtual Machine statistics monitoring tool”,它位於Java的bin目錄下,主要利用JVM內建的指令對Java應用程序的資源和性能進行實時的命令行的監控,包括了對Heap size和垃圾回收狀況的監控。可見,Jstat是輕量級的、專門針對JVM的工具,非常適用。
jstat工具特別強大,有眾多的可選項,詳細查看堆內各個部分的使用量,以及加載類的數量。使用時,需加上查看進程的進程id,和所選參數。參考格式如下:
jstat -options
可以列出當前JVM版本支持的選項,常見的有
- l class (類加載器)
- l compiler (JIT)
- l gc (GC堆狀態)
- l gccapacity (各區大小)
- l gccause (最近一次GC統計和原因)
- l gcnew (新區統計)
- l gcnewcapacity (新區大小)
- l gcold (老區統計)
- l gcoldcapacity (老區大小)
- l gcpermcapacity (永久區大小)
- l gcutil (GC統計匯總)
- l printcompilation (HotSpot編譯統計)
1、jstat –class<pid> : 顯示加載class的數量,及所占空間等信息。
顯示列名 |
具體描述 |
Loaded |
裝載的類的數量 |
Bytes |
裝載類所占用的字節數 |
Unloaded |
卸載類的數量 |
Bytes |
卸載類的字節數 |
Time |
裝載和卸載類所花費的時間 |
2、jstat -compiler <pid>顯示VM實時編譯的數量等信息。
顯示列名 |
具體描述 |
Compiled |
編譯任務執行數量 |
Failed |
編譯任務執行失敗數量 |
Invalid |
編譯任務執行失效數量 |
Time |
編譯任務消耗時間 |
FailedType |
最后一個編譯失敗任務的類型 |
FailedMethod |
最后一個編譯失敗任務所在的類及方法 |
3、jstat -gc <pid>: 可以顯示gc的信息,查看gc的次數,及時間。
顯示列名 |
具體描述 |
S0C |
年輕代中第一個survivor(幸存區)的容量 (字節) |
S1C |
年輕代中第二個survivor(幸存區)的容量 (字節) |
S0U |
年輕代中第一個survivor(幸存區)目前已使用空間 (字節) |
S1U |
年輕代中第二個survivor(幸存區)目前已使用空間 (字節) |
EC |
年輕代中Eden(伊甸園)的容量 (字節) |
EU |
年輕代中Eden(伊甸園)目前已使用空間 (字節) |
OC |
Old代的容量 (字節) |
OU |
Old代目前已使用空間 (字節) |
PC |
Perm(持久代)的容量 (字節) |
PU |
Perm(持久代)目前已使用空間 (字節) |
YGC |
從應用程序啟動到采樣時年輕代中gc次數 |
YGCT |
從應用程序啟動到采樣時年輕代中gc所用時間(s) |
FGC |
從應用程序啟動到采樣時old代(全gc)gc次數 |
FGCT |
從應用程序啟動到采樣時old代(全gc)gc所用時間(s) |
GCT |
從應用程序啟動到采樣時gc用的總時間(s) |
4、jstat -gccapacity <pid>:可以顯示,VM內存中三代(young,old,perm)對象的使用和占用大小
顯示列名 |
具體描述 |
NGCMN |
年輕代(young)中初始化(最小)的大小(字節) |
NGCMX |
年輕代(young)的最大容量 (字節) |
NGC |
年輕代(young)中當前的容量 (字節) |
S0C |
年輕代中第一個survivor(幸存區)的容量 (字節) |
S1C |
年輕代中第二個survivor(幸存區)的容量 (字節) |
EC |
年輕代中Eden(伊甸園)的容量 (字節) |
OGCMN |
old代中初始化(最小)的大小 (字節) |
OGCMX |
old代的最大容量(字節) |
OGC |
old代當前新生成的容量 (字節) |
OC |
Old代的容量 (字節) |
PGCMN |
perm代中初始化(最小)的大小 (字節) |
PGCMX |
perm代的最大容量 (字節) |
PGC |
perm代當前新生成的容量 (字節) |
PC |
Perm(持久代)的容量 (字節) |
YGC |
從應用程序啟動到采樣時年輕代中gc次數 |
FGC |
從應用程序啟動到采樣時old代(全gc)gc次數 |
5、jstat -gcutil <pid>:統計gc信息
顯示列名 |
具體描述 |
S0 |
年輕代中第一個survivor(幸存區)已使用的占當前容量百分比 |
S1 |
年輕代中第二個survivor(幸存區)已使用的占當前容量百分比 |
E |
年輕代中Eden(伊甸園)已使用的占當前容量百分比 |
O |
old代已使用的占當前容量百分比 |
P |
perm代已使用的占當前容量百分比 |
YGC |
從應用程序啟動到采樣時年輕代中gc次數 |
YGCT |
從應用程序啟動到采樣時年輕代中gc所用時間(s) |
FGC |
從應用程序啟動到采樣時old代(全gc)gc次數 |
FGCT |
從應用程序啟動到采樣時old代(全gc)gc所用時間(s) |
GCT |
從應用程序啟動到采樣時gc用的總時間(s) |
6、jstat -gcnew <pid>:年輕代對象的信息。
顯示列名 |
具體描述 |
S0C |
年輕代中第一個survivor(幸存區)的容量 (字節) |
S1C |
年輕代中第二個survivor(幸存區)的容量 (字節) |
S0U |
年輕代中第一個survivor(幸存區)目前已使用空間 (字節) |
S1U |
年輕代中第二個survivor(幸存區)目前已使用空間 (字節) |
TT |
持有次數限制 |
MTT |
最大持有次數限制 |
EC |
年輕代中Eden(伊甸園)的容量 (字節) |
EU |
年輕代中Eden(伊甸園)目前已使用空間 (字節) |
YGC |
從應用程序啟動到采樣時年輕代中gc次數 |
YGCT |
從應用程序啟動到采樣時年輕代中gc所用時間(s) |
7、jstat -gcnewcapacity<pid>: 年輕代對象的信息及其占用量。
顯示列名 |
具體描述 |
NGCMN |
年輕代(young)中初始化(最小)的大小(字節) |
NGCMX |
年輕代(young)的最大容量 (字節) |
NGC |
年輕代(young)中當前的容量 (字節) |
S0CMX |
年輕代中第一個survivor(幸存區)的最大容量 (字節) |
S0C |
年輕代中第一個survivor(幸存區)的容量 (字節) |
S1CMX |
年輕代中第二個survivor(幸存區)的最大容量 (字節) |
S1C |
年輕代中第二個survivor(幸存區)的容量 (字節) |
ECMX |
年輕代中Eden(伊甸園)的最大容量 (字節) |
EC |
年輕代中Eden(伊甸園)的容量 (字節) |
YGC |
從應用程序啟動到采樣時年輕代中gc次數 |
FGC |
從應用程序啟動到采樣時old代(全gc)gc次數 |
8、jstat -gcold <pid>:old代對象的信息。
顯示列名 |
具體描述 |
PC |
Perm(持久代)的容量 (字節) |
PU |
Perm(持久代)目前已使用空間 (字節) |
OC |
Old代的容量 (字節) |
OU |
Old代目前已使用空間 (字節) |
YGC |
從應用程序啟動到采樣時年輕代中gc次數 |
FGC |
從應用程序啟動到采樣時old代(全gc)gc次數 |
FGCT |
從應用程序啟動到采樣時old代(全gc)gc所用時間(s) |
GCT |
從應用程序啟動到采樣時gc用的總時間(s) |
9、stat -gcoldcapacity <pid>: old代對象的信息及其占用量。
顯示列名 |
具體描述 |
OGCMN |
old代中初始化(最小)的大小 (字節) |
OGCMX |
old代的最大容量(字節) |
OGC |
old代當前新生成的容量 (字節) |
OC |
Old代的容量 (字節) |
YGC |
從應用程序啟動到采樣時年輕代中gc次數 |
FGC |
從應用程序啟動到采樣時old代(全gc)gc次數 |
FGCT |
從應用程序啟動到采樣時old代(全gc)gc所用時間(s) |
GCT |
從應用程序啟動到采樣時gc用的總時間(s) |
10、jstat -gcpermcapacity<pid>: perm對象的信息及其占用量。
顯示列名 |
具體描述 |
PGCMN |
perm代中初始化(最小)的大小 (字節) |
PGCMX |
perm代的最大容量 (字節) |
PGC |
perm代當前新生成的容量 (字節) |
PC |
Perm(持久代)的容量 (字節) |
YGC |
從應用程序啟動到采樣時年輕代中gc次數 |
FGC |
從應用程序啟動到采樣時old代(全gc)gc次數 |
FGCT |
從應用程序啟動到采樣時old代(全gc)gc所用時間(s) |
GCT |
從應用程序啟動到采樣時gc用的總時間(s) |
11、jstat -printcompilation <pid>:當前VM執行的信息。
顯示列名 |
具體描述 |
Compiled |
編譯任務的數目 |
Size |
方法生成的字節碼的大小 |
Type |
編譯類型 |
Method |
類名和方法名用來標識編譯的方法。類名使用/做為一個命名空間分隔符。方法名是給定類中的方法。上述格式是由-XX:+PrintComplation選項進行設置的 |