JVM調優常用引數和注意點備忘錄
本文主要是工作過程中總結的一些jvm調優的引數和注意的地方,作為一個備忘錄,先佔個坑,有時間在來細化具體的例項。
- gc日誌是覆蓋的方式如果檔名字固定會導致上一次被覆蓋可以採用這個-Xloggc:backv2_gc_%t.log
- jinfo 可以動態修改java -XX:+PrintFlagsFinal -version|grep manageable這些引數
- 列印java可配置的非穩定引數 :java -XX:+PrintFlagsFinal ,輸出的資訊中 “:=” 表明了引數被使用者或者 JVM 賦值了
- jstat可以檢視類載入和gc的耗時資訊 -t引數表示每行前面輸出時間
- java堆溢位時獲取heap dump -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./m.hprof
- 當系統發生OOM錯誤時,虛擬機器在錯誤發生時執行一段第三方指令碼, 比如, 當OOM發生時,重置系統 -XX:OnOutOfMemoryError=c:\reset.bat
- 取消outofmemory警告:-XX:-UseGCOverheadLimit
-
獲取GC資訊
- -verbose:gc(-verbose:class可以輸出類載入的資訊) 或者 -XX:+PrintGC 列印gc日誌
- 如果要獲得更加詳細的資訊, 可以使用 -XX:+PrintGCDetails.
-
如果需要檢視新生物件晉升老年代的實際閾值, 可以使用引數 -XX:+PrintTenuringDistribution
java8中使用這個引數沒有詳細輸出各個年齡的分佈,因為java8預設的收集器是ParallelGC和ParallelGC Old,
這個收集器注重吞吐量沒有用年齡,所以沒必要列印詳細的年齡分佈。只會顯示晉升到老年代的閾值還有期望的Survivor區的預期大小。
- 輸出jvm啟動時的引數 -XX:+PrintFlagsInitial
- 禁用程式碼中顯示的觸發FULL GC [System.gc()]:-XX:+DisableExplicitGC
- 64位機器上壓縮指標 -XX:+UseCompressedOops
- 禁用類驗證 -Xverfy:none
- 禁用類元資料回收 -Xnoclassgc
- 確定堆記憶體大小 -Xmx 堆最大記憶體, -Xms對最小記憶體
-
合理分配新生代和老生代-Xmn 新生代大小, -XX:SurvivorRatio Eden和Survivor空間的比例 預設是8 設定年輕代(包括Eden和兩個Survivor區)與年老代的比值(除去持久代) -XX:NewRatio=4 預設是2
老年代和新生代大小比例調節:如果應用存在大量的臨時物件,應該選擇更大的年輕代;如果存在相對較多的持久物件,年老代應該適當增大。但很多應用都沒有這樣明顯的特性,在抉擇時應該根據以下兩點:
a.本著Full GC儘量少的原則,讓年老代儘量快取常用物件,JVM的預設比例1:2也是這個道理
b.通過觀察應用一段時間,看其他在峰值時年老代會佔多少記憶體,在不影響Full GC的前提下,根據實際情況加大年輕代,比如可以把比例控制在1:1。但應該給年老代至少預留1/3的增長空間
- 設定每個執行緒的堆疊大小,如:-Xss128k
-
導致jvm停頓的原因
- 垃圾收集
- 程式碼反優化
- Flushing code
- 類重定義如熱載入
- 取消偏向鎖
- 除錯動作(死鎖檢測,輸出執行緒堆疊)
-
STW
的四個階段
- Spin階段:因為jvm在決定進入全域性safepoint的時候,有的執行緒在安全點上,而有的執行緒不在安全點上,這個階段是等待未在安全點上的使用者執行緒進入安全點。
- Block階段:即使進入safepoint,使用者執行緒這時候仍然是running狀態,保證使用者不在繼續執行,需要將使用者執行緒阻塞
- Cleanup:這個階段是JVM做的一些內部的清理工作
- VM Operation. JVM執行的一些全域性性工作,例如GC,程式碼反優化,偏向鎖
- jvm停頓時間的輸出 :-XX:+PrintGCApplicationStoppedTime 上一次gc停頓程式執行時間 -XX:+PrintGCApplicationConcurrentTime
-
jvm停頓原因分析
: -XX:+PrintSafepointStatistics -XX:PrintSafepointStatisticsCount=1
- vmop:引發STW的原因,以及觸發時間該項常見的輸出有:RevokeBias、BulkRevokeBias、Deoptimize、G1IncCollectionPause。GC log可以根據該項內容定位Total time for which application threads…引發的詳細資訊。
- total :STW發生時,JVM存在的執行緒數目。
- initially_running :STW發生時,仍在執行的執行緒數,這項是Spin階段的 時間來源
- wait_to_block : STW需要阻塞的執行緒數目,這項是block階段的時間來源
-
輸出如下
發生時間操作執行緒總數正在執行等待阻塞 vmop[threads: total initially_running wait_to_block][time: spin block sync cleanup vmop] page_trap_count 0.462: ForceSafepoint[801][00000]0
- -XX:+UnlockDiagnosticVMOptions -XX:-DisplayVMOutput -XX:+LogVMOutput -XX:LogFile=vm.log 可以將詳細的停頓資訊輸出到日誌檔案中
- 來解鎖任何額外的隱藏引數-XX:+UnlockDiagnosticVMOptions和-XX:+UnlockExperimentalVMOptions
- 輸出啟動時的引數資訊和vm根據環境設定的引數資訊: -XX:+PrintCommandLineFlags
- CMS垃圾收集器的理解
- java啟動引數-agentlib,最常用的兩種常見一個是jdwp遠端除錯,還有個hprof記憶體和CPU分析
- string的intern方法,內部實現是hash資料結構,引數StringTableSize可以用來控制雜湊桶的數量,java8預設是60013,自定義的話最好設定一個素數
- JIT相關引數:-Djava.compiler=NONE禁用JIT,-XX:+PrintCompilation 列印JIT編譯情況
-
定製JIT編譯的引數 -XX:CompileCommand
待解決:
GC overhead limit exceeded問題