1. 程式人生 > 程式設計 >JVM效能調優實現原理及配置

JVM效能調優實現原理及配置

1、JVM記憶體模型

JVM效能調優實現原理及配置

總結:可以發現最明顯的一個變化是元空間從虛擬機器轉移到了本地記憶體。預設情況下,元資料空間大小僅受限於本地記憶體, 這意味著以後不會因為永久代大小不夠而丟擲OOM異常了。 jdk1.8以前,HotSpot VM將class和類的jar包資料儲存在PermGen裡, PermGen大小是固定的,而且專案之間無法公用公有的class,所以很容易碰到OOM異常。改成MateSpace後, 各個專案會共享同樣的class空間。比如多個專案都引用了apache-common包, 在MateSpace中只會儲存一份的apache-common的class,提高了記憶體的利用率,垃圾回收更有效。

2、JVM堆記憶體常用引數

引數 描述
-Xms 堆記憶體初始大小,單位m、g
-Xmx(MaxHeapSize) 堆記憶體最大允許大小,一般不要大於實體記憶體的80%
-XX:PermSize 非堆記憶體初始大小,一般應用設定初始化200m,最大1024m就夠了
-XX:MaxPermSize 非堆記憶體最大允許大小
-XX:NewSize(-Xns) 年輕代記憶體初始大小
-XX:MaxNewSize(-Xmn) 年輕代記憶體最大允許大小,也可以縮寫
-XX:SurvivorRatio=8 年輕代中Eden區與Survivor區的容量比例值,預設為8,即8:1
-Xss 堆疊記憶體大小

3、GC(Garbage Collection)演算法

這裡的GC具體指的是新生代的複製演算法

首先貼一張網上盜來的大圖,用它來說明一下GC的過程

JVM效能調優實現原理及配置

記憶體分配策略:

大多數情況下,物件在新生代的Eden中分配。當Eden區沒有足夠的空間進行分配時,虛擬機器將發起一次Minor GC,而大物件(需要大量連續記憶體空間的Java物件,類似長字串和陣列)將通過分配擔保機制直接進入老年代。

Minor GC——複製演算法具體過程:

將Eden和S0中還存活著的物件一次性的複製到S1中,並且清理掉Eden與S0的空間。如果S1放不下還存活著的物件,那這些物件將通過分配擔保機制進入老年代。【原理上隨時保持S0和S1有一個是空的,用來存下一次的物件】

Eden區快滿的時候,會進行上一步類似操作,將Eden和S1區的年紀大的物件放到S0區【此時S1區就是空的】
直到Eden區快滿,S0或者S1也快滿的時候,這時候就把這兩個區的年紀大的物件放到Old區。

依次迴圈,直到Old區也快滿的時候,Eden區也快滿的時候,會對整個這一塊記憶體區域進行一次大清洗(FullGC),騰出記憶體,為之後的物件建立,程式執行騰地方。

新生代GC(Minor GC):指發生在新生代的垃圾回收動作,因為java物件大多具備朝生夕滅的特徵,所以Minor GC發生的特別頻繁,

一般回收速度也很快。

老年代GC(Major GC/Full GC):指發生在老年代的GC,出現了Major GC,至少會伴隨一次的MinorGC(但非絕對,
在Parallel Scavenge收集器的收集策略裡就有直接進行Minor GC的策略選擇過程)。Major GC的速度一般比Minor GC慢10倍以上。

4、JVM引數配置

在jdk1.8以前,生產環境一般有如下配置

-XX:PermSize=512M -XX:MaxPermSize=1024M

表示在JVM裡儲存Java類資訊,常量池和靜態變數的永久代區域初始大小為512M,最大為1024M。在專案啟動後,這個值是固定的,如果專案class過多,很可能遇到OutOfMemoryError: PermGen異常。

升級JDK1.8之後,上面的perm配置已經變成

-XX:MetaspaceSize=512M XX:MaxMetaspaceSize=1024M

MetaspaceSize如果不做配置,通過jinfo檢視預設MetaspaceSize大小(約21M),MaxMetaspaceSize很大很大,前面說過MetaSpace只受本地記憶體大小限制。

jinfo -flag MetaspaceSize 1234 #結果為:-XX:MetaspaceSize=21807104
jinfo -flag MaxMetaspaceSize 1234 #結果為:-XX:MaxMetaspaceSize=18446744073709547520

乾貨:MetaspaceSize為觸發FullGC的閾值,預設約為21M,如做了配置,最小閾值為自定義配置大小。空間使用達到閾值,觸發FullGC,同時對該值擴大。當然如果元空間實際使用小於閾值,在GC的時候也會對該值縮小。
MaxMetaspaceSize為元空間的最大值,如果設定太小,可能會導致頻繁FullGC,甚至OOM。

5. JVM引數配置指南

前面三個部分對JVM進行了整體的瞭解,接下來是本文的重點。

-XX:MetaspaceSize=128M -XX:MaxMetaspaceSize=256M -Xms256m -Xmx256m

文章看下來上面這段配置的意思很簡單,設定元空間的初始值和最大值,設定堆空間的初始值和最大值。

為什麼MetaspaceSize要設定為128M?為什麼堆記憶體初始值Xms設定為256M而不是512M?

按照Java官方的指導

  • Java堆大小設定,Xms 和 Xmx設定為老年代存活物件的3-4倍,即FullGC之後的老年代記憶體佔用的3-4倍
  • MaxPermSize(元空間)設定為老年代存活物件的1.2-1.5倍。
  • 年輕代Xmn的設定為老年代存活物件的1-1.5倍。
  • 老年代的記憶體大小設定為老年代存活物件的2-3倍。

5. JVM監控jstat

可以讓系統執行一段時間後檢視系統的各個指標,然後在進行配置。如下用jstat工具檢視jvm的情況

jstat -gc 12345
###
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
13824.0 22528.0 13377.0 0.0 548864.0 535257.2 113152.0 46189.3 73984.0 71119.8 9728.0 9196.2 14 0.259 3 0.287 0.546

OU表示老年代所佔用的記憶體為 46189.3 K(大約45M);那麼jvm相應的配置引數應該做如下修改

-XX:MetaspaceSize=64M -XX:MaxMetaspaceSize=64M -Xms180m -Xmx180m

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。