JVM調優大全及實戰總結
文章目錄
JVM 型別
Java Virtual Machine 是Java 的執行環境。
常用的JVM型別包括:
- HotSpot VM
是Sun JDK和OpenJDK中所帶的虛擬機器,也是目前使用範圍最廣的Java虛擬機器。 - JRockit JVM: 由Oracle提供的
- IBM JVM : IBM出品的
JVM 記憶體中的概念及分割槽
程式要跑的快,是需要足夠的空間。但是記憶體空間總是有限的, 解決辦法就是把不需要的東西騰地方並清除掉。
JVM具備垃圾自動回收功能,其如何進行垃圾回收並保持整體的效能呢?
JVM將記憶體空間切分為不同的區塊, 經常會看見如下概念:
- Young: 年輕代
- Eden: 伊甸區
- Survivor0: 倖存者區0
- Survivor1: 倖存者區1
- Tenured:老年代, 也稱作Old Gen
- Perm:永久代
- G1:Garbage First Garbage Collector
在JDK6及之前的版本
Young = Eden + Survivor1+ Survivor2
JDK7及之後的版本
JDK7使用了G1。
G1 GC由Young Generation和Old Generation組成。G1將Java堆空間分割成了若干個Region,即年輕代/老年代是一系列Region的集合,這就意味著在分配空間時不需要一個連續的記憶體區間,即不需要在JVM啟動時決定哪些Region屬於老年代,哪些屬於年輕代。因為隨著時間推移,年輕代Region被回收後,又會變為可用狀態(後面會說到的Unused Region或Available Region)了
IBM的JVM雖然也有Nursery(Allocate+Survivor)+Tenured 的概念, 但實際上是一整塊劃分。
所以對於IBM的JVM來說, -Xms和-Xmx的初始值設定成不一樣會有點意義。
為什麼叫Hot Spot?
Java執行先將 .java編譯成平臺通用的 .class位元組碼檔案, 這些位元組碼檔案會被JVM逐條執行,速度相對較慢。對於一些執行頻繁的程式碼,也就是Hot Spot Code(熱點程式碼)。為了提高熱點程式碼的執行效率,在執行時,虛擬機器的JIT 編譯器將會把這些程式碼編譯成與本地平臺相關的機器碼,並進行各層次的優化。
注意 JRockit沒有JIT的編譯器。
效能調優的程式
- 測試, 使用SopaUI或是LoadRunner等工具
- 監控, 使用Top , VisualVM等
- 量測: 使用Head Dumps等
- 調優: 引數、程式碼
效能調優的標準:
- 記憶體
- 啟動時間
- 吞吐量 TPS
- 響應時間
效能調優的工具:
監控工具:
線上: JRMC(JRockit), VisualVM(Hotspot)
離線: GC Logs, GC Viewer , JFR
分析工具:
- Most IDE’s(JVMTI)
- MAT (Heap dumps)
- JRMC
- VisualVM
- 第三方, 類似JProfiler, YourKit
JVM自帶工具
- jps -v
列出當前使用者的所有Java程序, 可以顯示程序Id和啟動路徑等資訊。
-jinfo
列出Java程序更多的資訊
-jstack
提供程序的statck dump資訊。
對於執行緒Dump分析有用。
-jstat
根據引數顯示不同的JVM統計, 例如:
jstat -gcutil -v -h5 10000 20
顯示GC的利用百分比。
在GC的日誌關閉的狀況下適用。
注意: 在Windows下無法使用這個命令。
GC基礎
- 一般物件Typical object (Young object), 在建立之後很快就被回收,像一些本地的物件
- 已經存活了一段時間的舊物件會繼續存活一段時間
- Only a few references from old objects to
young objects exist
GC日誌
在weblogic 下檢視gclog.1.txt檔案
可以看到
-記憶體使用、空閒狀況等
-GC發生的頻率和花費的時間等
GC日誌引數:
常用:
- -XX:+PrintGCTimeStamps
或者 -XX:+PrintGCDateStamps - -XX:+PrintGCDetails
選用: - -Xloggc: 日誌檔名
- 日誌滾動配置
-XX:+UseGCLogFileRotation
-XX:NumberOfGCLogFiles=5
-XX:GCLogFileSize=10M
GC 調優
最常使用的GC引數:
-垃圾回收策略: 例如:non-generational, concurrent, parallel GC, deterministic,等
-GC並行:serial , parrallel, concurrent
-各個代的大小
最常使用GC診斷引數
-gc 日誌 (-verbose:gc)
-日誌層級: 例如: -XX:+PrintGCDetails(Hotspot)
-Xverbose:gcpause(JRockit)
-日誌檔案: -Xloggc: (Hotspot), -Xverboselog: (JRockit)
HotSpot VM的Heap佈局
32位作業系統最大記憶體 2^32 = 4G
2G 記憶體, JVM最大 1.5
3G 記憶體: 2.6~2.7 G(Weblogic)
物件在不同代的移動
新建立的物件放入 Eden,
在Minor GC 的時候,有些物件移動到兩個倖存區。
老年代放置一些長久的物件
永久代放置Class的資訊。
一個物件在放入到老年代之前, 會在S0,S1之間來來回回三次。
Runtime Stack會link到使用的物件, 對於沒有到達的物件,就會清除。
虛擬機器調優
JVM不能使用到所有的記憶體, 還要預留空間給其他。不能超過實體記憶體的大小。
最大(80%~90%)
減少執行緒棧的空間給heap -xss: 128k
如何決定年輕代的空間大小:
- minor GC的頻率
- minor GC回收的物件數量
老年代大小:
- 維護系統穩定執行的存活資料大小
-最小化 major GC的頻率
原則:在年輕代最大化回收物件,最小化full gc的頻率。
調整任何代的空間大小,需要Full GC.
比較好的設定是初始化和最大記憶體設定相同: -Xmx=-Xms
-可以預防Xms 到Xmx空間大小導致的full GC
-效能比較好
永久代的大小
-XX:PermSize=-XX:MaxPermSize
永久代佔用的大小很難預估, 動態Class
設定足夠大預防 PermGen的OOME錯誤
-XX:NewSize=-XX:MaxNewSize
一般使用-Xmn配置
Live Data Size(LDS)-存活資料大小統計
統計方法一:
統計之前,執行full GC
-
使用JConsole/VisualVM執行GC
點選"Perform GC" -
jmap檢視
jmap -histo:live
統計方法二:
GC log
GC Log 可以統計:
- LDS
- 最大的永久代大小
- 延遲狀況
總體設定原則:
- 設定 -Xms 和-Xmx是 LDS的3到4倍。
2.設定-XX:PermSize和-XX:MaxPermSize為最大永久代空間的1.2 到1.5倍
新生代 設定成 LDS的1到1.5倍
永久代設定成 LDS的2到3倍
新生代的空間大約設定成堆空間的1/3 - 1/4
For LDS of 512m : -Xmn768m -Xms2g -Xmx2g
記憶體洩漏
- 出現OutOfMemory錯誤
-長時間存活物件使用的空間一直在增加 - 一般問題出在應用程式
常見錯誤:
1.java.lang.OutOfMemoryError: Java heap space
堆空間滿了
配置-Xms 和-Xmx
- java.lang.OutOfMemoryError: PermGen space
永久代空間滿了
配置 MinPermGen 和MaxPermGen
3.java.lang.OutOfMemoryError:unable to create new native thread
(MaxProcessMemory-JVMMemory-ReservedOsMemory)/(ThreadStackSize) = Number of threads
MaxProcessMemory: 作業系統給一個程序的記憶體
JVMMemory: JVM記憶體 Heap+PermGen
ReservedOsMemory: 保留給作業系統的記憶體
ThreadStackSize: 執行緒記憶體的大小 -Xss
TreadStackSize
預設 325 , -Xms, -Xmx配置越大,建立的執行緒數量就越小。
如果需要增加:辦法有:
- MaxProcessMemory
修改OS設定, 或者使用64位的系統 - JVMMemory
減少JVM的記憶體使用 - ThreadStackSize
減少單一執行緒執行的棧的大小
未完, 待續…
請再駐足一分鐘,並幫忙點選一下滑鼠。
博主正在參加2018部落格之星評選,如果本部落格有幫到您或是有緣看到這篇的話,請幫忙投一下 180 號, oscar999。
投票地址:https://bss.csdn.net/m/topic/blog_star2018
感激之致,順祝新年快樂!