1. 程式人生 > >jvm第五節-效能調優工具使用

jvm第五節-效能調優工具使用

B.jmap -permstat pid     列印程序的類載入器和類載入器載入的持久代物件資訊,輸出:類載入器名稱、物件是否存活(不可靠)、物件地址、父類載入器、已載入的類大小等資訊,如下:
[[email protected] bin]# ./jmap -permstat 568
Attaching to process ID 568, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 20.45-b01
16140 intern Strings occupying 1783912 bytes.
finding class loader instances ..Finding object size using Printezis bits and skipping over...
Finding object size using Printezis bits and skipping over...
Finding object size using Printezis bits and skipping over...
Finding object size using Printezis bits and skipping over...
done.
computing per loader stat ..done.
please wait.. computing liveness............................liveness analysis may be inaccurate ...
class_loader	classes	bytes	parent_loader	alive?	type

<bootstrap>	2493	14855744	  null  	live	<internal>
0x00000000e0773800	1	1944	0x00000000e01c99b8	dead	sun/reflect/
[email protected]
total = 207 7595 48487296 N/A alive=26, dead=181 N/A
 C.使用jmap -heap pid檢視程序堆記憶體使用情況,包括使用的GC演算法、堆配置引數和各代中堆記憶體使用情況。比如下面的例子:
[[email protected] bin]# ./jmap -heap 568
Attaching to process ID 568, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 20.45-b01

using thread-local object allocation.
Parallel GC with 4 thread(s)

Heap Configuration:
   MinHeapFreeRatio = 40
   MaxHeapFreeRatio = 70
   MaxHeapSize      = 536870912 (512.0MB)
   NewSize          = 1310720 (1.25MB)
   MaxNewSize       = 268435456 (256.0MB)
   OldSize          = 5439488 (5.1875MB)
   NewRatio         = 2
   SurvivorRatio    = 8
   PermSize         = 67108864 (64.0MB)
   MaxPermSize      = 134217728 (128.0MB)

Heap Usage:
PS Young Generation
Eden Space:
   capacity = 88145920 (84.0625MB)
   used     = 1621408 (1.546295166015625MB)
   free     = 86524512 (82.51620483398438MB)
   1.8394589335501859% used
From Space:
   capacity = 327680 (0.3125MB)
   used     = 0 (0.0MB)
   free     = 327680 (0.3125MB)
   0.0% used
To Space:
   capacity = 655360 (0.625MB)
   used     = 0 (0.0MB)
   free     = 655360 (0.625MB)
   0.0% used
PS Old Generation
   capacity = 178978816 (170.6875MB)
   used     = 15780800 (15.04974365234375MB)
   free     = 163198016 (155.63775634765625MB)
   8.817132861131453% used
PS Perm Generation
   capacity = 67371008 (64.25MB)
   used     = 48657272 (46.40319061279297MB)
   free     = 18713736 (17.84680938720703MB)
   72.22286476699294% used
[
[email protected]
bin]#
  D.使用jmap -histo[:live] pid檢視堆記憶體中的物件數目、大小統計直方圖,如果帶上live則只統計活物件,如下:
[[email protected] bin]# ./jmap -histo:live  568 | more

 num     #instances         #bytes  class name
----------------------------------------------
   1:         66979       10485224  <constMethodKlass>
   2:         66979        9119528  <methodKlass>
   3:          6324        7213368  <constantPoolKlass>
   4:        106075        6052696  <symbolKlass>
   5:         44944        5260600  [C
   6:          6324        4773896  <instanceKlassKlass>
   7:          5526        4452336  <constantPoolCacheKlass>
   8:          9718        3255512  [B
   9:         49626        1588032  java.lang.String
  10:          1985        1329544  <methodDataKlass>
  11:          6876         715104  java.lang.Class
  12:          8684         615896  [S
  13:          6854         603264  [Ljava.util.HashMap$Entry;
  14:         18715         598880  java.util.HashMap$Entry
  15:         10192         507944  [[I
  16:          6619         467656  [I
  17:          5120         450560  java.lang.reflect.Method
  18:          8701         434216  [Ljava.lang.Object;
  19:         10402         416080  java.util.LinkedHashMap$Entry
  20:          7728         309120  java.util.concurrent.ConcurrentHashMap$Segment
  21:           523         305432  <objArrayKlassKlass>
  22:          7921         253472  java.util.concurrent.locks.ReentrantLock$NonfairSync
  23:          7728         242408  [Ljava.util.concurrent.ConcurrentHashMap$HashEntry;
  24:          5494         219760  java.lang.ref.SoftReference
  25:          3660         175680  java.util.HashMap
  26:          4740         151680  java.lang.ref.WeakReference
  27:          4728         148752  [Ljava.lang.String;
  28:          2662         127776  org.apache.catalina.loader.ResourceEntry
  29:          5275         126600  java.util.ArrayList
  30:          1407         101304  java.lang.reflect.Constructor
  E.用jmap把程序記憶體使用情況dump到檔案中,再用jhat分析檢視。jmap進行dump命令格式如下: jmap -dump:format=b,file=dumpFileName pid ./jmap -dump:format=b,file=/usr/local/my.bin

[[email protected] ~]#./ jmap -dump:format=b,file=my.bin  568

Dumping heap to /root/my.bin ...

Heap dump file created

jhat -port 9998 /usr/local/my.bin,埠預設是7000

5.jhat

jhat是sun提供的dump分析工具,上面講過分析dump的工具還有MAT( Eclipse Memory Analyzer tool)、IBM HeapAnalyzer等,一般這個命令不太用到,是因為分析dump是個既耗時又耗機器資源的過程,第二個原因是這個工具比較簡陋,沒有MAT( Eclipse Memory Analyzer tool)、IBM HeapAnalyzer這些專業和強大。

命令格式:

jhat file

使用樣例:

防止影響服務,所以在本地windows下使用,先匯出dump檔案

./jmap -dump:format=b,file=my.bin 568

Dumping heap to my.bin ...

Heap dump file created

然後分析:

./jhat my.bin

Reading from my.bin...

Dump file created Thu Feb 18 16:20:49 CST 2016

Snapshot read, resolving...

Resolving 2532914 objects..

Chasing references, expect 1 dots.

Eliminating duplicate references.

Snapshot resolved.

Started HTTP server on port 7000

Server is ready.

載在瀏覽器中輸入localhost:7000檢視結果,如下圖



 

6.jstack

jstack用於打印出給定的java程序ID或core file或遠端除錯服務的Java堆疊資訊,如果是在64位機器上,需要指定選項"-J-d64",Windows的jstack使用方式只支援以下的這種方式:

如果java程式崩潰生成core檔案,jstack工具可以用來獲得core檔案的java stack和native stack的資訊,從而可以輕鬆地知道java程式是如何崩潰和在程式何處發生問題。另外,jstack工具還可以附屬到正在執行的java程式中,看到當時執行的java程式的java stack和native stack的資訊, 如果現在執行的java程式呈現hung的狀態,jstack是非常有用的。 

命令格式 :

jstack [ option ] pid

引數說明:

-F當’jstack [-l] pid’沒有相應的時候強制列印棧資訊

-l長列表. 列印關於鎖的附加資訊,例如屬於java.util.concurrent的ownable synchronizers列表.

-m列印java和native c/c++框架的所有棧資訊.

使用樣例:

[[email protected] ~]# jstack -l 21742

[email protected] bin]# printf "%x\n" 21742

238

[[email protected] bin]# ./jstack 21742|grep 238

- waiting on <0x00000000e085f238> (a java.lang.ref.ReferenceQueue$Lock)

- locked <0x00000000e085f238> (a java.lang.ref.ReferenceQueue$Lock)

[[email protected] bin]# printf "%x\n" 568

 jstack主要用來檢視某個Java程序內的執行緒堆疊資訊。語法格式如下:

jstack [option] pid

jstack [option] executable core

jstack [option] [[email protected]]remote-hostname-or-ip

    命令列引數選項說明如下:

-l long listings,會打印出額外的鎖資訊,在發生死鎖時可以用jstack -l pid來觀察鎖持有情況

-m mixed mode,不僅會輸出Java堆疊資訊,還會輸出C/C++堆疊資訊(比如Native方法)

    jstack可以定位到執行緒堆疊,根據堆疊資訊我們可以定位到具體程式碼,所以它在JVM效能調優中使用得非常多。下面我們來一個例項找出某個Java程序中最耗費CPU的Java執行緒並定位堆疊資訊,用到的命令有ps、top、printf、jstack、grep。

    第一步先找出Java程序ID,我部署在伺服器上的Java應用名稱為my:

得到程序ID為21711,第二步找出該程序內最耗費CPU的執行緒,可以使用ps -Lfp pid或者ps -mp pid -o THREAD, tid, time或者top -Hp pid,我這裡用第三個,輸出如下

 TIME列就是各個Java執行緒耗費的CPU時間,CPU時間最長的是執行緒ID為21742的執行緒,用

printf "%x\n" 21742

    得到21742的十六進位制值為54ee,下面會用到。    

    OK,下一步終於輪到jstack上場了,它用來輸出程序21711的堆疊資訊,然後根據執行緒ID的十六進位制值grep,如下:

./jstack 21711 | grep 54ee

"PollIntervalRetrySchedulerThread" prio=10 tid=0x00007f950043e000 nid=0x54ee in Object.wait()

死鎖程式碼如下:

// 執行緒處於無線等待中
getLog().info("Thread [" + getName() + "] is idle waiting...");
schedulerThreadState = PollTaskSchedulerThreadState.IdleWaiting;
long now = System.currentTimeMillis();
long waitTime = now + getIdleWaitTime();
long timeUntilContinue = waitTime - now;
synchronized(sigLock) {
    try {
        if(!halted.get()) {
            sigLock.wait(timeUntilContinue);
        }
    } 
    catch (InterruptedException ignore) {
    }
}