jvm調優工具介紹

1.java自帶的調優工具

1.1 JPS (JVM Process Status Tool),查看當前機器上所有JVM進程的狀態和啓動參數

命令格式:jps [options] [hostid]

我們可以通過“jps --help”來查看相關幫助。如下爲允許使用的options:

1)-q:只列出JVM進程的id,不展示進程的其他信息。

Java代碼

jps -q -v
26582
26586
26301
27983
2)-m:輸出傳遞到main方法的參數列表。

3)-l:輸出此啓動此繼承的main方法所在的全package路徑、或者JAR的文件路徑。

Java代碼

jps -l
26582 org.apache.catalina.startup.Bootstrap
27991 sun.tools.jps.Jps
26586 org.jetbrains.jps.cmdline.Launcher
26301 org.jetbrains.plugins.scala.nailgun.NailgunRunner
4)-v:輸出JVM進程的系統參數,其中包括-D參數和JAVA_OPTS相關參數。

Java代碼

jps -v
18381 Bootstrap -Djava.util.logging.config.file=/opt/deploy/sample-tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Xms256m -Xmx256m -XX:NewSize=128m -XX:+DisableExplicitGC -Dlogs=/data/logs -Dcache=/opt/deploy/sample-tomcat/cache -verbose:gc -XX:+PrintGCDateStamps -XX:+PrintGCDetails -Xloggc:/opt/vipkid/homework/logs/gc.log -Djava.endorsed.dirs=/opt/tomcat/endorsed -Djava.io.tmpdir=/opt/deploy/sample-tomcat/temp
5)-V:輸出那些通過flag文件傳遞給JVM的參數(-XX:Flags=)。

整體來說,jps跟linux的“ps”指令很像,從整體查看當前機器上所有的JVM進程

1.2 jinfo
查看一個JVM進程的全部配置信息,包括系統變量、加載的lib、JAVA_OPTS信息、JDK(JVM)的版本情況等。可以修改flag值
1.3 jstat JVM Statistics Monitoring tool,JVM統計數據監控工具,可以用來查看JVM中GC、類加載等信息。

命令格式:jstat [generalOptions | outputOptions vimd [interval [s|ms] [count]]]

generalOptions沒有太大用,我們只需要知道使用“jstat -options”來查看可選參的列表,主要是outputOptions:

1)-class:有關classLoader的行爲統計

Java代碼

jstat -class 26582
Loaded Bytes Unloaded Bytes Time
13401 28013.1 381 574.4 23.57
loaded:已加載類的個數,bytes:已加載類的字節數,unloaded、bytes:已卸載類的個數和字節數,time:類加載和卸載耗時。

2)-compiler:統計Hotspot中JIT(just-in-time)編譯器的行爲。(比較少用)

3)-gc:堆GC的行爲統計,通過此指令我們能瞭解heap各個區域的內存使用情況。

Java代碼

jstat -gc 26582 2s 100
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
63488.0 10240.0 0.0 10080.0 520192.0 259699.6 1398272.0 1272911.1 92352.0 89826.6 9984.0 9458.4 1089 24.631 11 25.624 50.255
新生代,有三塊:eden、survivor0、survivor1,其中EC、S0C、S1C分別表示上述三個區的compacity(KB),EU、S0U、S1U分表表示上述三個區的已使用空間。OC、OU表示救年老代的空間和使用量,PC、PU表示持久帶的情況。YGC、YGCT分別表示新生代GC的次數和總時間,FGC、FGCT表示FULL GC的次數和總時間,GCT表示所有GC的總時間。

通常我們可以根據這些參數來觀察,JVM內存分佈、GC的情況,以便進行調優。(對於互聯網系統,通常YGC與FGC相差數倍,即極少的FGC,但是通常YGC會幾分鐘就會執行一次)

4)-gccapacity:大體作用同-gc,也可以用來查看堆的各區域內存現狀。

5)-gccause 展示內容同上,不過包含兩個特殊的列“LGCC”、“GCC”,表示導致上次或者本次GC的原因,通常原因都是“內存分配失敗”。

6)-gcnew:展示新生代的gc情況,同上。同類型指令還有-gcold。

7)-gcutil:全局的gc行爲統計。基本上是上述幾個gc指令的彙總。

我們可以使用jps找到jvm的進程ID,然後使用jstat分析特定ID的堆內存情況。

1.4 jmap JVM Memory Map,JVM內存圖,通常可以用來查看當前JVM的內存中對象存活情況、跟蹤對象創建過程等
1)-dump:[live,] format=b,file=:將JVM堆內存中對象(live表示只dump存活的)dump到執行的文件中,使用hprof格式,此後我們可以使用jhat工具來查看此文件。通常可以使用-dump來分析內存中對象個數和數據狀態,比如跟蹤某個對象實例的個數,數組的容量變化等。

2)-finalizerinfo:打印出等待finalization的對象信息。如果你的實例有重寫終結方法的,可以通過此選項查看。

3)-heap:打印JVM的heap配置信息,比如堆大小、新生代(newSize)等等,以及GC的算法(打印結果的前幾行)。這些信息當然也可以通過jstat、jinfo來查看。

Java代碼

jmap -heap 26832
using thread-local object allocation.
Parallel GC with 2 thread(s)

Heap Configuration: MinHeapFreeRatio = 0
MaxHeapFreeRatio = 100 MaxHeapSize =
536870912 (512.0MB) NewSize = 178782208
(170.5MB) MaxNewSize = 178782208 (170.5MB)
OldSize = 358088704 (341.5MB) NewRatio
= 2 SurvivorRatio = 8 MetaspaceSize = 21807104 (20.796875MB) CompressedClassSpaceSize = 1073741824
(1024.0MB) MaxMetaspaceSize = 17592186044415 MB
G1HeapRegionSize = 0 (0.0MB) Heap Usage: PS Young
Generation Eden Space: capacity = 102760448 (98.0MB) used
= 54807000 (52.268028259277344MB) free = 47953448 (45.731971740722656MB)
53.33472271354831% used From Space: capacity = 39321600 (37.5MB) used = 7370120 (7.028694152832031MB) free =
31951480 (30.47130584716797MB)
18.743184407552082% used To Space: capacity = 36700160 (35.0MB) used = 0 (0.0MB) free = 36700160 (35.0MB)
0.0% used PS Old Generation capacity = 358088704 (341.5MB) used = 46609072 (44.44987487792969MB) free = 311479632
(297.0501251220703MB)
13.016068778310304% used

4)-histo[:live]:根據每個java class類型,打印出相應類的實例個數、內存佔用空間(bytes)的直方圖,live選項表示只打印存活的對象個數(和佔用空間);這個指令可以幫助我們關注JVM中某種class的實例個數和佔用內存量,對分析內存消耗、OOM排查有很大幫助。

Java代碼

jmap -histo:live 30402

num #instances #bytes class name

1: 129824 15193328 [C 2: 7631
13005088 [B 3: 127333 3055992 java.lang.String
4: 22984 1308592 [Ljava.lang.Object; 5:
14557 1281016 java.lang.reflect.Method 6: 39153
1252896 java.util.HashMapNode7:8843997240java.lang.Class8:7260982096[Ljava.util.HashMapNode 7: 8843 997240 java.lang.Class 8: 7260 982096 [Ljava.util.HashMapNode;

1.5jvisualvm
監控內存泄露,跟蹤垃圾回收,執行時內存、cpu分析,線程分析…
怎麼遠程監控服務可以參考
jvisualvm使用教程
1.6jstackstack trace,用於打印java線程的調用棧(執行棧,瞬時),包括class全名、方法名、行號等,如果指定-m還會打印native幀;不過對於實際工作情況,我們通常用於追蹤多線程任務調度過程、對象lock(或者死鎖)、併發同步阻塞、IO線程執行狀態等;比如排查某個線程爲何wait(假死,阻塞等)

1)-l:打印出當前JVM所有的線程狀態和執行棧,包括locks(java.util.concurrent)。

Java代碼
“http-nio-8080-exec-7” #78 daemon prio=5 os_prio=31 tid=0x00007f876f957000 nid=0x13403 waiting on condition [0x00007000043e8000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x0000000740994e50> (a java.util.concurrent.locks.AbstractQueuedSynchronizerConditionObject)atjava.util.concurrent.locks.LockSupport.park(LockSupport.java:175)atjava.util.concurrent.locks.AbstractQueuedSynchronizerConditionObject) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) at java.util.concurrent.locks.AbstractQueuedSynchronizerConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:103)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:31)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
at java.util.concurrent.ThreadPoolExecutorWorker.run(ThreadPoolExecutor.java:617)atorg.apache.tomcat.util.threads.TaskThreadWorker.run(ThreadPoolExecutor.java:617) at org.apache.tomcat.util.threads.TaskThreadWrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)

Locked ownable synchronizers:
- None

如果有死鎖時,大概的錯誤信息如下:

Java代碼
Found one Java-level deadlock:

“pool-1-thread-2”:
waiting to lock monitor 0x0237ada4 (object 0x272200e8, a java.lang.Object),
which is held by “pool-1-thread-1”
“pool-1-thread-1”:
waiting to lock monitor 0x0237aa64 (object 0x272200f0, a java.lang.Object),
which is held by “pool-1-thread-2”

2)-m:混合模式,可以打印native幀。 

2.阿里巴巴調優神器arthas(阿爾薩斯)
官方網站:
https://alibaba.github.io/arthas/index.html
根據官方介紹阿爾薩斯可以解決一下問題

當你遇到以下類似問題而束手無策時,Arthas可以幫助你解決:

這個類從哪個 jar 包加載的?爲什麼會報各種類相關的 Exception?

我改的代碼爲什麼沒有執行到?難道是我沒 commit?分支搞錯了?

遇到問題無法在線上 debug,難道只能通過加日誌再重新發布嗎?

線上遇到某個用戶的數據處理有問題,但線上同樣無法 debug,線下無法重現!

是否有一個全局視角來查看系統的運行狀況?

有什麼辦法可以監控到JVM的實時運行狀態?

怎麼快速定位應用的熱點,生成火焰圖?

Arthas支持JDK 6+,支持Linux/Mac/Winodws,採用命令行交互模式,同時提供豐富的 Tab

下載安裝使用可以參考官方網站或者通過一下博客進行詳細學習
https://www.cnblogs.com/testfan2019/p/11038791.html

3最後介紹一下其他調優的工具

JProfiler ,NetBeans profiler等
參考一下博文
https://segmentfault.com/a/1190000003940167

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