JVM - 要上线了,JVM参数还没正儿八经的估算过咋办?
文章目錄
- Pre
- jstat
- 評估內存使用及GC壓力的整體情況 jstat -gc PID
- -gcutil 輸出主要關注已使用空間占總空間的百分比
- -gccause 額外輸出導致上一次GC產生的原因
- 堆內存統計
- 新生代垃圾回收統計
- 新生代內存統計
- 老年代垃圾回收統計
- 老年代內存統計
- 元數據空間統計
- 運行情況預估
Pre
如題, 一頓操作猛如虎,業務系統總算快發布了,可是JVM的參數還是當初隨意設置的那么幾個參數, 咋弄? 系統的流量預估(均值、峰值)導致一系列的評估: 每秒的對象生成大小,新生代 老年代的比例是否合理, 動態年齡判斷機制、老年代擔保機制會不會被頻繁觸發,full gc 的頻率。。。。
留下一臉懵逼的你在風中瑟瑟發抖~
不要怕 ,今天我們就來看一下如何通過合理的預估來設置系統的JVM參數
JVM-10虛擬機性能監控與故障處理工具之【JDK的命令行】
| jps | JVM Process Status Tool | 顯示指定系統內所有的HotSPot虛擬機進程 |
| jstat | JVM Statistics Monitoring Tool | 用于手機HotSpot虛擬機個方面的運行數據 |
| jinfo | Configuration Info for Java | 顯示虛擬機配置信息 |
| jmap | Memory Map for Java | 生成虛擬機的內存轉儲快照(headump文件) |
| jhat | Java Heap Analysis Tool | 虛擬機堆轉儲快照分析工具 |
| jstack | Stack Trace For Java | java堆棧跟蹤工具,,顯示線程快照 |
jstat
[root@artisan ~]# java -version java version "1.8.0_221" Java(TM) SE Runtime Environment (build 1.8.0_221-b11) Java HotSpot(TM) 64-Bit Server VM (build 25.221-b11, mixed mode) [root@artisan ~]# jstat -help Usage: jstat -help|-optionsjstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]Definitions:<option> An option reported by the -options option<vmid> Virtual Machine Identifier. A vmid takes the following form:<lvmid>[@<hostname>[:<port>]]Where <lvmid> is the local vm identifier for the targetJava virtual machine, typically a process id; <hostname> isthe name of the host running the target Java virtual machine;and <port> is the port number for the rmiregistry on thetarget host. See the jvmstat documentation for a more completedescription of the Virtual Machine Identifier.<lines> Number of samples between header lines.<interval> Sampling interval. The following forms are allowed:<n>["ms"|"s"]Where <n> is an integer and the suffix specifies the units as milliseconds("ms") or seconds("s"). The default units are "ms".<count> Number of samples to take before terminating.-J<flag> Pass <flag> directly to the runtime system. [root@artisan ~]#官方都說了 jstat -help|-options ,是吧 看看 options的選項吧
[root@artisan ~]# jstat -options -class -compiler -gc -gccapacity -gccause -gcmetacapacity -gcnew -gcnewcapacity -gcold -gcoldcapacity -gcutil -printcompilation [root@artisan ~]#從中可以看出 , jstat (JVM Statistics Monitoring Tool)用于監視虛擬機各種運行狀態信息的命令行工具。 它可以顯示本地或者遠程虛擬機進程中的類裝載、內存、垃圾回收、JIT編譯等運行數據 。
劃重點, 垃圾回收 ,這里我們重點看GC垃圾回收 ,因為JVM調優的本質就是為了減少full GC 的發生。
通過不同方式的測試,觀察GC的情況,可以很好的預測和分析 每秒的對象生成大小,新生代 老年代的比例是否合理, 動態年齡判斷機制、老年代擔保機制會不會被頻繁觸發,full gc 的頻率。。。。
選項option代表用戶希望查詢的虛擬機信息,主要分為3類:類裝載、垃圾收集、運行期編譯狀況。
jstat的主要選項
| -class | 監視類裝載、卸載數量,總空間以及類裝載鎖耗費的時間 |
| -gc | 監視Java堆狀況,包括eden區、兩個Survivor區、老年代、永久代等的容量、已使用空間、GC時間合計等信息 |
| -gccapacity | 監視內容與-gc基本相同,但輸出主要關注Java堆各個區域使用的最大、最小空間 |
| -gcutil | 監視內容與-gc基本相同,但輸出主要關注已使用空間占總空間的百分比 |
| -gccause | 與-gcutil功能一樣,但是會額外輸出導致上一次GC產生的原因 |
| -gcnew | 監視新生代GC狀況 |
| -gcnewcapacity | 監視內容與-gcnew 基本相同,但輸出主要關注Java堆各個區域使用的最大、最小空間 |
| -gcold | 監視老年代代GC狀況 |
| -gcoldcapacity | 監視內容與-gcold 基本相同,但輸出主要關注Java堆各個區域使用的最大、最小空間 |
| -gcpermcapacity | 輸出永久代使用的最大、最小空間 |
| -compiler | 輸出JIT編譯器編譯過的方法、耗時等信息 |
| -printcompilation | 輸出已經被JIT編譯的方法 |
評估內存使用及GC壓力的整體情況 jstat -gc PID
[root@artisan ~]# jps 5811 kooteam.jar 10478 Jps [root@artisan ~]# jstat -gc 5811 S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT 34944.0 34944.0 0.0 0.0 279616.0 44044.5 699072.0 13979.2 21248.0 20630.5 2560.0 2386.8 0 0.000 1 0.338 0.338 [root@artisan ~]#參數解讀
- S0C:第一個幸存區的大小,單位KB
- S1C:第二個幸存區的大小
- S0U:第一個幸存區的使用大小
- S1U:第二個幸存區的使用大小
- EC:伊甸園區的大小
- EU:伊甸園區的使用大小
- OC:老年代大小
- OU:老年代使用大小
- MC:方法區大小(元空間)
- MU:方法區使用大小
- CCSC:壓縮類空間大小
- CCSU:壓縮類空間使用大小
- YGC:年輕代垃圾回收次數
- YGCT:年輕代垃圾回收消耗時間,單位s
- FGC:老年代垃圾回收次數
- FGCT:老年代垃圾回收消耗時間,單位s
- GCT:垃圾回收消耗總時間,單位s
當然了,看一次肯定不行啊,一般都是間隔多長時間輸出一次,持續觀察。
比如 間隔2秒,打印1萬次
[root@artisan ~]# jstat -gc 5811 2000 10000S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT 34944.0 34944.0 0.0 0.0 279616.0 56627.5 699072.0 13979.2 21248.0 20630.5 2560.0 2386.8 0 0.000 1 0.338 0.338 34944.0 34944.0 0.0 0.0 279616.0 56627.5 699072.0 13979.2 21248.0 20630.5 2560.0 2386.8 0 0.000 1 0.338 0.338根據壓測,結合這個GC各個分代的情況,加之對業務的理解,推斷是否存在不合理的地方。
-gcutil 輸出主要關注已使用空間占總空間的百分比
監視內容與-gc基本相同,但輸出主要關注已使用空間占總空間的百分比
[root@artisan ~]# jstat -gcutil 5811S0 S1 E O M CCS YGC YGCT FGC FGCT GCT 0.00 0.00 24.75 2.00 97.09 93.23 0 0.000 1 0.338 0.338 [root@artisan ~]# jstat -gcutil 5811 2000 10000參數解讀
- S0:幸存1區當前使用比例
- S1:幸存2區當前使用比例
- E:伊甸園區使用比例
- O:老年代使用比例
- M:元數據區使用比例
- CCS:壓縮使用比例
- YGC:年輕代垃圾回收次數
- FGC:老年代垃圾回收次數
- FGCT:老年代垃圾回收消耗時間
- GCT:垃圾回收消耗總時間
-gccause 額外輸出導致上一次GC產生的原因
與-gcutil功能一樣,但是會額外輸出導致上一次GC產生的原因
[root@artisan ~]# jstat -gccause 5811S0 S1 E O M CCS YGC YGCT FGC FGCT GCT LGCC GCC 0.00 0.00 25.75 2.00 97.09 93.23 0 0.000 1 0.338 0.338 Metadata GC Threshold No GC [root@artisan ~]# jstat -gccause 5811 2000 10000- LGCC : 上一次GC的原因
堆內存統計
[root@artisan ~]# jstat -gccapacity 5811NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC 349504.0 349504.0 349504.0 34944.0 34944.0 279616.0 699072.0 699072.0 699072.0 699072.0 0.0 1069056.0 21248.0 0.0 1048576.0 2560.0 0 1 [root@artisan ~]# jstat -gccapacity 5811 2000 10000 --> 2秒輸出一次 輸出1萬次參數解讀
- NGCMN:新生代最小容量
- NGCMX:新生代最大容量
- NGC:當前新生代容量
- S0C:第一個幸存區大小
- S1C:第二個幸存區的大小
- EC:伊甸園區的大小
- OGCMN:老年代最小容量
- OGCMX:老年代最大容量
- OGC:當前老年代大小
- OC:當前老年代大小
- MCMN:最小元數據容量
- MCMX:最大元數據容量
- MC:當前元數據空間大小
- CCSMN:最小壓縮類空間大小
- CCSMX:最大壓縮類空間大小
- CCSC:當前壓縮類空間大小
- YGC:年輕代gc次數
- FGC:老年代GC次數
新生代垃圾回收統計
[root@artisan ~]# jstat -gcnew 5811S0C S1C S0U S1U TT MTT DSS EC EU YGC YGCT 34944.0 34944.0 0.0 0.0 15 15 0.0 279616.0 56627.5 0 0.000 [root@artisan ~]# jstat -gcnew 5811 2000 10000 --> 2秒輸出一次 輸出1萬次參數解讀
- S0C:第一個幸存區的大小
- S1C:第二個幸存區的大小
- S0U:第一個幸存區的使用大小
- S1U:第二個幸存區的使用大小
- TT:對象在新生代存活的次數
- MTT:對象在新生代存活的最大次數
- DSS:期望的幸存區大小
- EC:伊甸園區的大小
- EU:伊甸園區的使用大小
- YGC:年輕代垃圾回收次數
- YGCT:年輕代垃圾回收消耗時間
新生代內存統計
[root@artisan ~]# jstat -gcnewcapacity 5811 NGCMN NGCMX NGC S0CMX S0C S1CMX S1C ECMX EC YGC FGC 349504.0 349504.0 349504.0 34944.0 34944.0 34944.0 34944.0 279616.0 279616.0 0 1 [root@artisan ~]# jstat -gcnewcapacity 5811 2000 10000 --> 2秒輸出一次 輸出1萬次參數解讀
- NGCMN:新生代最小容量
- NGCMX:新生代最大容量
- NGC:當前新生代容量
- S0CMX:最大幸存1區大小
- S0C:當前幸存1區大小
- S1CMX:最大幸存2區大小
- S1C:當前幸存2區大小
- ECMX:最大伊甸園區大小
- EC:當前伊甸園區大小
- YGC:年輕代垃圾回收次數
- FGC:老年代回收次數
老年代垃圾回收統計
[root@artisan ~]# jstat -gcold 5811 MC MU CCSC CCSU OC OU YGC FGC FGCT GCT 21248.0 20630.5 2560.0 2386.8 699072.0 13979.2 0 1 0.338 0.338 [root@artisan ~]# jstat -gcold 5811 2000 10000 --> 2秒輸出一次 輸出1萬次參數解讀
- MC:方法區大小
- MU:方法區使用大小
- CCSC:壓縮類空間大小
- CCSU:壓縮類空間使用大小
- OC:老年代大小
- OU:老年代使用大小
- YGC:年輕代垃圾回收次數
- FGC:老年代垃圾回收次數
- FGCT:老年代垃圾回收消耗時間
- GCT:垃圾回收消耗總時間
老年代內存統計
[root@artisan ~]# jstat -gcoldcapacity 5811 OGCMN OGCMX OGC OC YGC FGC FGCT GCT 699072.0 699072.0 699072.0 699072.0 0 1 0.338 0.338 [root@artisan ~]# jstat -gcoldcapacity 5811 2000 10000參數解讀
- OGCMN:老年代最小容量
- OGCMX:老年代最大容量
- OGC:當前老年代大小
- OC:老年代大小
- YGC:年輕代垃圾回收次數
- FGC:老年代垃圾回收次數
- FGCT:老年代垃圾回收消耗時間
- GCT:垃圾回收消耗總時間
元數據空間統計
[root@artisan ~]# jstat -gcmetacapacity 5811 MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC FGCT GCT 0.0 1069056.0 21248.0 0.0 1048576.0 2560.0 0 1 0.338 0.338 [root@artisan ~]# jstat -gcmetacapacity 5811 2000 10000參數解讀
- MCMN:最小元數據容量
- MCMX:最大元數據容量
- MC:當前元數據空間大小
- CCSMN:最小壓縮類空間大小
- CCSMX:最大壓縮類空間大小
- CCSC:當前壓縮類空間大小
- YGC:年輕代垃圾回收次數
- FGC:老年代垃圾回收次數
- FGCT:老年代垃圾回收消耗時間
- GCT:垃圾回收消耗總時間
運行情況預估
jstat 會用了哈
主要是利用jstat -gc pid 算出系統的關鍵參數 ,結合我們之前梳理的理論知識(這個沒有,那基本上是不太可行了) ,先設置一些初始值,然后根據壓測情況合理調整。
主要觀察一下幾點
【年輕代對象增長的速率】
可以執行命令 jstat -gc pid 2000 100(每隔2秒執行1次命令,共執行100次),通過觀察EU(eden區的使用)來估算每秒eden大概新增多少對象.
如果系統負載不高,可以把頻率2秒調大一些觀察整體情況。
要考慮: 系統高峰期和低谷期間的壓力,肯定是不一樣的,總和考慮。
【Young GC的觸發頻率和每次耗時】
知道年輕代對象增長速率我們就能推根據eden區的大小推算出Young GC大概多久觸發一次,Young GC的平均耗時可以通過 YGCT/YGC 公式算出,根據結果我們大概就能知道系統大概多久會因為Young GC的執行而卡頓多久。
【每次Young GC后有多少對象存活和進入老年代】
這個因為之前已經大概知道Young GC的頻率,假設是每5分鐘一次,那么可以執行命令 jstat -gc pid 300000 10 ,觀察每次結果eden,survivor和老年代使用的變化情況,在每次gc后eden區使用一般會大幅減少,survivor和老年代都有可能增長,這些增長的對象就是每次Young GC后存活的對象,同時還可以看出每次Young GC后進去老年代大概多少對象,從而可以推算出老年代對象增長速率。
【Full GC的觸發頻率和每次耗時】
知道了老年代對象的增長速率就可以推算出Full GC的觸發頻率了,Full GC的每次耗時可以用公式 FGCT/FGC 計算得出。
優化思路其實簡單來說就是盡量讓每次Young GC后的存活對象小于Survivor區域的50%,都留存在年輕代里。盡量別讓對象進入老年代。盡量減少Full GC的頻率,避免頻繁Full GC對JVM性能的影響。
總結
以上是生活随笔為你收集整理的JVM - 要上线了,JVM参数还没正儿八经的估算过咋办?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JVM - 列出JVM默认参数及运行时生
- 下一篇: Java - String源码解析及常见