JVM調優的理解以及常用命令的彙總

jvm簡介什麼的不詳細介紹了,只介紹有重點性,需要理解和記憶以及常用的核心參數的介紹。

 

對象的年齡:每垃圾回收一次,如果一個對象沒被回收掉,他的年齡就會增加1

對象的分配:

  • 對象優先分配在新生代
  • 新生代如果對象滿了,會觸發Minor GC回收掉沒有引用的垃圾對象
  • 如果有對象躲過了十多次垃圾回收,就會放入老年代裏
  • 如果老年代也滿了,那麼也會觸發垃圾回收,把老年代裏沒人引用的垃圾對象清理掉

對象進入老年代的方法:

1、新生代垃圾回收之後,因爲存活對象太多,會導致大量對象直接進入老年代

2、特別大的超大對象直接不經過新生代就進入老年代

3、動態對象年齡判斷機制:假如說當前放對象的Survivor區域裏,一批對象的總大小大於了這塊Survivor區域的內存大小的50%,那麼此時大於等於這批對象年齡的對象,就可以直接進入老年代了。

4、空間擔保機制:執行任何一次Minor GC之前,JVM會先檢查一下老年代最大的可用連續空間,是否大於新生代所有對象的總大小

 

jvm內存分配的核心參數:

-Xms:Java堆內存的大小

-Xmx:Java堆內存的最大大小

-Xmn:Java堆內存中的新生代大小,扣除新生代剩下的就是老年代的內存大小了

-XX:PermSize:永久代大小

-XX:MaxPermSize:永久代最大大小

-Xss:每個線程的棧內存大小
如:

java -Xms512M -Xmx512M -Xmn256M -Xss1M -XX:PermSize=128M -XX:MaxPermSize=128M -jar App.jar
-Xms3072M -Xmx3072M -Xmn1536M -Xss1M -XX:PermSize=256M -XX:MaxPermSize=256M  -XX:HandlePromotionFailure

其他參數:

-XX:MaxTenuringThreshold  多少歲進入老年代  默認15歲 。在JVM中用4個bit存儲(放在對象頭中),所以其最大值是15

其他進入老年代的方法:

如果gc之後eden區剩餘的對象內存大於Survivor區,則將對象直接轉移到老年代中

-XX:PretenureSizeThreshold  默認值是0,超過多大的對象直接進入分配在老年代。設置爲字節數,比如“1048576”字節,就是1MB,如:-XX:PretenureSizeThreshold=1M

-XX:-HandlePromotionFailure  老年代最大可用連續空間是否大於之前到晉級老年代對象的平均大小。參數在JDK 1.6以後就被廢棄

-XX:+UseParNewGC   使用ParNew垃圾回收器(多線程來進行垃圾回收),運行在Windows上的客戶端程序,建議採用Serial垃圾回收器

-XX:+UseG1GC  使用G1垃圾回收器

-XX:+UseParallelGC: 新生代使用ParllelGC回收器

-XX:ParallelGCThreads 控制ParNew的垃圾回收線程數量 

-XX:CMSInitiatingOccupancyFaction 參數可以設置老年代中對象佔多少比例的時候,觸發 CMS 垃圾回收器的回收機制,默認92%如:-XX:CMSInitiatingOccupancyFaction=92

-XX:+UseCMSCompactAtFullCollection

-XX:CMSFullGCsBeforeCompaction=0

G1中,大對象的判定規則就是一個大對象超過了一個Region大小的50%,大對象可以橫跨多個region進行存放

-XX:MaxGCPauseMills G1執行GC的時候最多可以讓系統停頓多長時間。默認值是200ms

-XX:InitiatingHeapOccupancyPercent  默認值是45% 如果老年代佔據了堆內存的45%的Region的時候,此時就會嘗試觸發一個新生代+老年代一起回收的混合回收階段

-XX:G1MixedGCCountTarget  在一次混合回收的過程中,最後一個階段執行幾次混合回收,默認值是8次

-XX:G1MixedGCLiveThresholdPercent,他的默認值是85%,意思就是確定要回收的Region的時候,必須是存活對象低於85%的Region纔可以進行回收

 

-XX:+HeapDumpOnOutOfMemoryError    OOM的時候自動dump內存快照

-XX:HeapDumpPath=/usr/local/app/oom   內存快照放到哪兒去

 

MinorGC觸發條件圖:

 

調優步驟:

1、估計系統每秒會產生多少新的對象,佔用多少內存 訪問壓力以及核心對象的內存佔據,需要多少時間纔會讓新生代觸發Minor GC以及多久之後觸發FullGC。

2、突發巨大的流量壓力,突發的性能抖動,最後導致很多對象長期在新生代被人引用,無法被回收,最後持續進入老年代,最後觸發老年代內存都頻繁佔滿,然後老年代都頻繁被垃圾回收。

 

Tomcat jvm調優在bin目錄下的catalina.sh中可以加入JVM參數

 

CMS垃圾收集算法:

初始標記(CMS-initial-mark) -> 併發標記(CMS-concurrent-mark) -> 重新標記(CMS-remark) -> 併發清除(CMS-concurrent-sweep) ->併發重設狀態等待下次CMS的觸發(CMS-concurrent-reset)
 

可能會出現的異常:Concurrent mode failed的產生是由於CMS回收老年代的速度太慢,導致年老代在CMS完成前就被佔滿,引起full gc(需要時間較長),發現此異常後會使用Serial Old來進行垃圾回收,如果Serial Old也頂不住,會發生OOM。

 

有GC Roots引用的對象不能回收,沒有GC Roots引用的對象可以回收,如果有GC Roots引用,但是如果是軟引用或者弱引用的,也有可能被回收掉。靜態變量也可以看做是一種GC Roots。

Object中的finalize()方法,垃圾回收時會調用的方法,如果不想被回收,可以重寫這個方法。

 

對於 XX:SurvivorRatio 網上很多人說是佔百分比:

官網原話:

The SurvivorRatio parameter controls the size of the two survivor spaces. For example, -XX:SurvivorRatio=6 sets the ratio between each survivor space and eden to be 1:6, each survivor space will be one eighth of the young generation. The default for Solaris is 32. If survivor spaces are too small, copying collection overflows directly into the old generation. If survivor spaces are too large, they will be empty. At each GC, the JVM determines the number of times an object can be copied before it is tenured, called the tenure threshold. This threshold is chosen to keep the survivor space half full.

鏈接:https://docs.oracle.com/cd/E19159-01/819-3681/abeil/index.html

G1 內存模型:

G1(Garbage First):將Java堆內存拆分爲多個大小相等的Region,每個分區內部又被分成了若干個大小爲512 Byte卡片(Card)。每個Region可能是老年代,也可以新生代。G1仍然存在有Eden和Survivor(邏輯概念),各自佔據不同的Region。這樣就和之前的調優步驟一致。

G1可以設置一個垃圾回收的預期停頓時間,如果設置0.5s,G1會計算這個時間可以回收多少個Region,從來只回收部分region已達到控制時間的作用。

G1適用於堆內存比較大(一般4G以上)

題目:

 

-Xms:1G , 就是說初始堆大小爲1G 

-Xmx:2G , 就是說最大堆大小爲2G 

-Xmn:500M ,就是說新生代大小是500M(包括一個Eden和兩個Survivor) 

-XX:MaxPermSize:64M , 就是說設置持久代最大值爲64M 

-XX:+UseConcMarkSweepGC , 就是說使用使用CMS內存收集算法 

-XX:SurvivorRatio=3 , Eden區比例30% 就是說Eden區與Survivor區的大小比值爲3:1:1

題目中所問的Eden區的大小是指年輕代的大小,直接根據-Xmn:500M和-XX:SurvivorRatio=3可以直接計算得出

500M*(3/(3+1+1)) =500M*(3/5) =300M 

因此Eden區域的大小爲300M

 

總結: 

分析系統的壓力點在哪裏,如果在現有內存資源的情況下,儘量減少GC回收的次數。根據每秒的產生在新生代的內存,根據jvm運行原理分析出,什麼時候對象將在老年代中,什麼時候進行minor GC會通過擔保機制直接進入老年代等。

 

附:

比較齊全的一份jvm參數設置:

-Xms4096M -Xmx4096M -Xmn3072M -Xss1M  -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFaction=92 -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=0 -XX:+CMSParallelInitialMarkEnabled -XX:+CMSScavengeBeforeRemark -XX:+DisableExplicitGC -XX:+PrintGCDetails -Xloggc:gc.log -XX:+HeapDumpOnOutOfMemoryError  -XX:HeapDumpPath=/usr/local/app/oom

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章