1. 程式人生 > >JVM調優大全及實戰總結

JVM調優大全及實戰總結

文章目錄

JVM 型別

Java Virtual Machine 是Java 的執行環境。
常用的JVM型別包括:

  • HotSpot VM
     是Sun JDK和OpenJDK中所帶的虛擬機器,也是目前使用範圍最廣的Java虛擬機器。
  • JRockit JVM: 由Oracle提供的
  • IBM JVM : IBM出品的

JVM 記憶體中的概念及分割槽

程式要跑的快,是需要足夠的空間。但是記憶體空間總是有限的, 解決辦法就是把不需要的東西騰地方並清除掉。
JVM具備垃圾自動回收功能,其如何進行垃圾回收並保持整體的效能呢?
JVM將記憶體空間切分為不同的區塊, 經常會看見如下概念:

  1. Young: 年輕代
  2. Eden: 伊甸區
  3. Survivor0: 倖存者區0
  4. Survivor1: 倖存者區1
  5. Tenured:老年代, 也稱作Old Gen
  6. Perm:永久代
  7. 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的編譯器。

效能調優的程式

  1. 測試, 使用SopaUI或是LoadRunner等工具
  2. 監控, 使用Top , VisualVM等
  3. 量測: 使用Head Dumps等
  4. 調優: 引數、程式碼

效能調優的標準:

  • 記憶體
  • 啟動時間
  • 吞吐量 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基礎

  1. 一般物件Typical object (Young object), 在建立之後很快就被回收,像一些本地的物件
  2. 已經存活了一段時間的舊物件會繼續存活一段時間
  3. Only a few references from old objects to
    young objects exist

GC日誌

在weblogic 下檢視gclog.1.txt檔案
可以看到
-記憶體使用、空閒狀況等
-GC發生的頻率和花費的時間等

GC日誌引數:
常用:

  1. -XX:+PrintGCTimeStamps
    或者 -XX:+PrintGCDateStamps
  2. -XX:+PrintGCDetails
    選用:
  3. -Xloggc: 日誌檔名
  4. 日誌滾動配置
    -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

  1. 使用JConsole/VisualVM執行GC
    點選"Perform GC"

  2. jmap檢視
    jmap -histo:live

統計方法二:
GC log
GC Log 可以統計:

  1. LDS
  2. 最大的永久代大小
  3. 延遲狀況

總體設定原則:

  1. 設定 -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

  1. 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配置越大,建立的執行緒數量就越小。
如果需要增加:辦法有:

  1. MaxProcessMemory
    修改OS設定, 或者使用64位的系統
  2. JVMMemory
    減少JVM的記憶體使用
  3. ThreadStackSize
    減少單一執行緒執行的棧的大小

未完, 待續…


請再駐足一分鐘,並幫忙點選一下滑鼠。

博主正在參加2018部落格之星評選,如果本部落格有幫到您或是有緣看到這篇的話,請幫忙投一下 180 號, oscar999。
投票地址:https://bss.csdn.net/m/topic/blog_star2018
感激之致,順祝新年快樂!