一般應用程序都部署在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