五、JVM調優指令

一般應用程序都部署在Linux服務器上,當然我們可以使用界面化的調優工具例如jconsole、VisualVM等進行遠程連接來進行監控和性能分析,但歸根結底,工具只是將指令執行的結果進行友好的展示而已,而且工具的使用終究還是有各種限制,所以我們必須掌握JVM的調優指令。

JVM的調優指令在安裝JDK的bin目錄下,如圖:

這裏寫圖片描述

這裏主要介紹jps/jstat/jmap/jstack/jinfo這幾個常用的指令,每個指令都可通過man來查看如何使用。

jps


jps [option] [hostid]

option參數可輸也可不輸。

-l: 輸出主類全名或jar路徑
-q: 只輸出LVMID
-m: 輸出JVM啓動時傳遞給main()的參數
-v: 輸出JVM啓動時顯示指定的JVM參數

如圖:
這裏寫圖片描述

jstat


jstat [option] vmid [interval] [count]

參數:

option: 操作參數
vmid: 本地虛擬機進程ID
interval: 連續輸出的時間間隔
count: 連續輸出的次數
Option Displays
class class loader的行爲統計。Statistics on the behavior of the class loader.
compiler HotSpt JIT編譯器行爲統計。Statistics of the behavior of the HotSpot Just-in-Time compiler.
gc 垃圾回收堆的行爲統計。Statistics of the behavior of the garbage collected heap.
gccapacity 各個垃圾回收代容量(young,old,perm)和他們相應的空間統計。Statistics of the capacities of the generations and their corresponding spaces.
gcutil 垃圾回收統計概述。Summary of garbage collection statistics.
gccause 垃圾收集統計概述(同-gcutil),附加最近兩次垃圾回收事件的原因。Summary of garbage collection statistics (same as -gcutil), with the cause of the last and
gcnew 新生代行爲統計。Statistics of the behavior of the new generation.
gcnewcapacity 新生代與其相應的內存空間的統計。Statistics of the sizes of the new generations and its corresponding spaces.
gcold 年老代和永生代行爲統計。Statistics of the behavior of the old and permanent generations.
gcoldcapacity 年老代行爲統計。Statistics of the sizes of the old generation.
gcpermcapacity 永生代行爲統計。Statistics of the sizes of the permanent generation.
printcompilation HotSpot編譯方法統計。HotSpot compilation method statistics.

下面是對一些常用的option參數的解釋,注意92203是通過jps -l指令執行過程中得到的id,即我本地運行的Tomcat的id:

-compiler


jstat -compiler 92203

這裏寫圖片描述

Compiled : 編譯數量
Failed : 編譯失敗數量
Invalid : 無效數量
Time : 編譯耗時
FailedType : 失敗類型
FailedMethod : 失敗方法的全限定名

-class


jstat -class 92203

這裏寫圖片描述

Loaded : 加載class的數量
Bytes : class字節大小
Unloaded : 未加載class的數量
Bytes : 未加載class的字節大小
Time : 加載時間

-gc


jstat -gc 92203

這裏寫圖片描述

S0C : survivor0區的總容量
S1C : survivor1區的總容量
S0U : survivor0區已使用的容量
S1C : survivor1區已使用的容量
EC : Eden區的總容量
EU : Eden區已使用的容量
OC : Old區的總容量
OU : Old區已使用的容量
PC : 當前perm的容量 (KB)
PU : perm的使用 (KB)
YGC : 新生代垃圾回收次數
YGCT : 新生代垃圾回收時間
FGC : 老年代垃圾回收次數
FGCT : 老年代垃圾回收時間
GCT : 垃圾回收總消耗時間

-gcutil


jstat -gcutil 92203

這裏寫圖片描述

S0 : survivor0區的總容量
S1 : survivor1區的總容量
E : Eden區的總容量
O : Old區的總容量
OU : Old區已使用的容量
YGC : 新生代垃圾回收次數
YGCT : 新生代垃圾回收時間
FGC : 老年代垃圾回收次數
FGCT : 老年代垃圾回收時間
GCT : 垃圾回收總消耗時間

-gccause


jstat -gccause 92203

這裏寫圖片描述

LGCC:最近垃圾回收的原因
GCC:當前垃圾回收的原因

-gccapacity


jstat -gccause 92203

這裏寫圖片描述

NGCMN : 新生代佔用的最小空間
NGCMX : 新生代佔用的最大空間
OGCMN : 老年代佔用的最小空間
OGCMX : 老年代佔用的最大空間
OGC:當前年老代的容量 (KB)
OC:當前年老代的空間 (KB)
PGCMN : perm佔用的最小空間
PGCMX : perm佔用的最大空間

jmap


jmap [option] vmid

jmap(JVM Memory Map)命令用於生成heap dump文件,如果不使用這個命令,還可以使用-XX:+HeapDumpOnOutOfMemoryError參數來讓虛擬機出現OOM時自動生成dump文件。jmap不僅能生成dump文件,還能查詢finalize執行隊列、Java堆和永久代的詳細信息,如當前使用率、當前使用的是哪種收集器等。
參數:

dump : 生成堆轉儲快照
finalizerinfo : 顯示在F-Queue隊列等待Finalizer線程執行finalizer方法的對象
heap : 顯示Java堆詳細信息
histo : 顯示堆中對象的統計信息
permstat : to print permanent generation statistics
F : 當-dump沒有響應時,強制生成dump快照
Attaching to process ID 94358, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.79-b02

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

Heap Configuration: //堆內存初始化配置
   MinHeapFreeRatio = 0 //jvm參數-XX:MinHeapFreeRatio設置JVM堆最小空閒比率(default 40)
   MaxHeapFreeRatio = 100 //jvm參數 -XX:MaxHeapFreeRatio設置JVM堆最大空閒比率(default 70)
   MaxHeapSize      = 1073741824 (1024.0MB) //jvm參數-XX:MaxHeapSize=設置JVM堆的最大大小
   NewSize          = 536870912 (512.0MB)//jvm參數-XX:NewSize=設置JVM堆的‘新生代’的默認大小
   MaxNewSize       = 536870912 (512.0MB)//jvm參數-XX:MaxNewSize=設置JVM堆的‘新生代’的最大大小
   OldSize          = 5439488 (5.1875MB) //參數-XX:OldSize=<value>:設置JVM堆的‘老生代’的大小
   NewRatio         = 2 //參數-XX:NewRatio=:‘新生代’和‘老生代’的大小比率
   SurvivorRatio    = 8 //參數-XX:SurvivorRatio=設置年輕代中Eden區與Survivor區的大小比值
   PermSize         = 536870912 (512.0MB) //參數-XX:PermSize=<value>:設置JVM堆的‘永生代’的初始大小
   MaxPermSize      = 1073741824 (1024.0MB)//參數-XX:MaxPermSize=<value>:設置JVM堆的‘永生代’的最大大小
   G1HeapRegionSize = 0 (0.0MB)

Heap Usage: //堆內存使用情況
PS Young Generation
Eden Space:
   capacity = 300417024 (286.5MB) //總容量
   used     = 231151904 (220.44363403320312MB) //已使用
   free     = 69265120 (66.05636596679688MB)//剩餘容量
   76.94367680041994% used //Eden區使用比率
From Space: // S0 內存使用情況
   capacity = 120586240 (115.0MB)
   used     = 53528904 (51.04914093017578MB)
   free     = 67057336 (63.95085906982422MB)
   44.39055733058763% used
To Space:  // S1 內存使用情況
   capacity = 115867648 (110.5MB)
   used     = 0 (0.0MB)
   free     = 115867648 (110.5MB)
   0.0% used
PS Old Generation // Old區使用情況
   capacity = 536870912 (512.0MB)
   used     = 241598968 (230.40673065185547MB)
   free     = 295271944 (281.59326934814453MB)
   45.00131458044052% used
PS Perm Generation // 永久代使用情況
   capacity = 536870912 (512.0MB)
   used     = 143245904 (136.6099395751953MB)
   free     = 393625008 (375.3900604248047MB)
   26.681628823280334% used

18942 interned Strings occupying 2284376 bytes.

也可以使用dump參數,將dump文件保存到本地,然後再通過工具來分析。

-dump::live,format=b,file=<filename> pid
$ ./jmap -dump:live,format=b,file=/tmp/myDump.hprof 94358
Dumping heap to /private/tmp/myDump.hprof ...
Heap dump file created

jhat


jhat [dumpfile]

jhat(JVM Heap Analysis Tool)命令是與jmap搭配使用,用來分析jmap生成的dump,jhat內置了一個微型的HTTP/HTML服務器,生成dump的分析結果後,可以在瀏覽器中查看。在此要注意,一般不會直接在服務器上進行分析,因爲jhat是一個耗時並且耗費硬件資源的過程,一般把服務器生成的dump文件複製到本地或其他機器上進行分析。

-stack false|true  關閉對象分配調用棧跟蹤(tracking object allocation call stack)。 如果分配位置信息在堆轉儲中不可用. 則必須將此標誌設置爲 false. 默認值爲 true.>
-refs false|true   關閉對象引用跟蹤(tracking of references to objects)。 默認值爲 true. 默認情況下, 返回的指針是指向其他特定對象的對象,如反向鏈接或輸入引用(referrers or incoming references), 會統計/計算堆中的所有對象。>
-port port-number  設置 jhat HTTP server 的端口號. 默認值 7000.>
-exclude exclude-file    指定對象查詢時需要排除的數據成員列表文件(a file that lists data members that should be excluded from the reachable objects query)。 例如, 如果文件列列出了 java.lang.String.value , 那麼當從某個特定對象 Object o 計算可達的對象列表時, 引用路徑涉及 java.lang.String.value 的都會被排除。>
-baseline exclude-file   指定一個基準堆轉儲(baseline heap dump)。 在兩個 heap dumps 中有相同 object ID 的對象會被標記爲不是新的(marked as not being new). 其他對象被標記爲新的(new). 在比較兩個不同的堆轉儲時很有用.>
-debug int   設置 debug 級別. 0 表示不輸出調試信息。 值越大則表示輸出更詳細的 debug 信息.>
-version     啓動後只顯示版本信息就退出>
-J< flag >   因爲 jhat 命令實際上會啓動一個JVM來執行, 通過 -J 可以在啓動JVM時傳入一些啓動參數. 例如, -J-Xmx512m 則指定運行 jhat 的Java虛擬機使用的最大堆內存爲 512 MB. 如果需要使用多個JVM啓動參數,則傳入多個 -Jxxxxxx.

示例:

這裏寫圖片描述

中間的-J-Xmx1024m是在dump快照很大的情況下分配512M內存去啓動HTTP服務器,運行完之後就可在瀏覽器打開Http://localhost:7000進行快照分析 堆快照分析主要在最後面的Heap Histogram裏,裏面根據class列出了dump的時候所有存活對象。

這裏寫圖片描述

jstat


jstat [dumpfile]

jstack主要用於生成JVM當前時刻的線程快照。線程快照就是指JVM內每一條線程正在執行的方法堆棧的集合,生成線程快照的主要目的是定位線程出現長時間停頓的原因,如線程間死鎖、死循環、請求外部資源導致的長時間等待等。 線程出現停頓的時候通過jstack來查看各個線程的調用堆棧,就可以知道沒有響應的線程到底在後臺做什麼事情,或者等待什麼資源。 如果java程序崩潰生成core文件,jstack工具可以用來獲得core文件的java stack和native stack的信息,從而可以輕鬆地知道java程序是如何崩潰和在程序何處發生問題。另外,jstack工具還可以附屬到正在運行的java程序中,看到當時運行的java程序的java stack和native stack的信息, 如果現在運行的java程序呈現掛起的狀態,jstack是非常有用的。

-F : 當正常輸出請求不被響應時,強制輸出線程堆棧
-l : 除堆棧外,顯示關於鎖的附加信息
-m : 如果調用到本地方法的話,可以顯示C/C++的堆棧

示例:

這裏寫圖片描述

詳細分析可看下這篇文章:Java命令學習系列(二)——Jstack

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章