本文主要是工作過程中總結的一些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 [ 8 0 1 ] [ 0 0 0 0 0 ] 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問題