jvm複習筆記

 

一、jvm組成部分

名稱 內容 備註
數組,對象、分爲新生代、存活區、老年代

新生代:存活區 8:2

新生代:老年代 1:2

 

局部變量表、對象的引用、操作數棧、方法出口  
程序計數器 行號指示器、通過改變這個計數器的值來選取下一條需要執行的字節碼指令,分支、循環、跳轉、異常處理、線程恢復等基礎功能都需要依賴這個計數器來完成,也就是記錄當前線程的執行點,調度線程執行  
方法區 類的編譯信息,靜態變量,常量  
直接內存 nio操作

在jdk1.4中新加入了NIO類,他可以調用native函數庫直接分配堆外內存,然後通過java堆中的DirectByteBuffer

對象來指向這塊內存,進行內存分配等工作。

 
     

二、參數配置

名稱 參數 參數說明

-Xms:堆最小值(新生代,老年代之後)

-Xmx:堆最大值(新生代,老年代之後)

-Xmn指定eden區的大小

-XX:SruvirorRation調整倖存區的大小

-XX:PretenureSizeThreshold設置進入老年代的閾值

例:-Xms1024 -Xmx1024

通常將-Xms與-Xmx設置爲一樣大小來減小gc的次數,堆內存不足時拋出OutOfMemoryError異常

-Xss

例:-Xss128k

單線程下無論棧幀太大還是棧容量太小,及應用深度超過虛擬機允許深度都會拋出StackOverflowError每個方法壓入棧的幀大小是不一致的。多線程下當每個線程分配棧幀太大內存不夠擴展時拋出OutOfMemoryError異常線程棧幀越大,可創建的線程越少

方法區

-XX:PermSize方法區內存最小值

-XX:MaxPermSize方法區內存最大值

例: -XX:PermSize=20M

  -XX:MaxPermSize=20M

 

各個線程共享的內存區域,主要用來存儲類的元數據、常量、靜態變量、即時編譯後的代碼

異常類型 OutOfMemoryError

原因:常量過多,或代理反射等使用頻繁

直接內存 -XX:MaxDirectMemorySize

例: -XX:MaxDirectMemorySize=10M

不足時拋出OutOfMemory異常

輔助參數

-XX:+HeapDumpOnOutOfMemoryError 打印堆內存異常時快照信息

-XX:+HeapDumpPath快照輸出路徑

-

 
     
     
     
     

三、垃圾回收算法

名稱 優缺點 備註
標記--清除算法(Mark-Sweep)

算法執行分爲兩個階段標記與清除,所有的回收算法基本都是基於標記回收算法深度優化

缺點:效率問題,內存空間碎片(不連續的空間)

 
複製回收算法(包括分代算法)

比較標記清除算法,避免回收造成的碎片化問題

缺點:以局部的內存空間犧牲爲代價,不過空間的浪費比較小,默認8:1比例1是浪費的,複製也有一定的效率與空間成本

 
標記整理算法(Mark-Compact)

避免了空間的浪費,與內存碎片問題

缺點:整理時複製有效率成本

 

四、垃圾收集器

垃圾收集器種類
名稱 用法 備註
Serial(串行GC) -XX:+UseSerialGC

串行收集器採用單線程stop-the-world的方式進行收集。當內存不足時,串行GC設置停頓標識,待所有線程都進入安全點(Safepoint)時,應用線程暫停,串行GC開始工作,採用單線程方式回收空間並整理內存。單線程也意味着複雜度更低、佔用內存更少,但同時也意味着不能有效利用多核優勢。事實上,串行收集器特別適合堆內存不高、單核甚至雙核CPU的場合。
 

Serial Old收集器(串行GC) -XX:+UseSerialGC
ParNew(並行GC) -XX:+UseParNewGC 新生代收集器,可以認爲是Serial收集器的多線程版本,在多核CPU環境下悠着比Serial更好的表現
Parallel Scavenge(並行回收GC)

-XX:UserParallelGC

-XX:parallelGcThreads=4指定線程數

並行收集器,追求高吞吐量,高效利用CPU。吞吐量一般爲99%,吞吐量=用戶線程時間/(用戶線程時間+GC線程時間)。適合後臺應用等對交互響應要求不高的廠家,是server級別默認採用的GC方式
Parallel Old -XX:+UseParallelOldGC Parallel Scavenge收集器的老年代版本,並行收集器,吞吐量有限
CMS(併發GC) -XX:+UseConcMarkSweepGC

年輕代ParNew與並行收集器類似,而老年代CMS每個收集週期都要經歷:初始標記、併發標記、重新標記、併發清除。其中,初始標記以STW的方式標記所有的根對象;併發標記則同應用線程一起並行,標記出根對象的可達路徑;在進行垃圾回收前,CMS再以一個STW進行重新標記,標記那些由mutator線程(指引起數據變化的線程,即應用線程)修改而可能錯過的可達對象;最後得到的不可達對象將在併發清除階段進行回收。值得注意的是,初始標記和重新標記都已優化爲多線程執行。CMS非常適合堆內存大、CPU核數多的服務器端應用,也是G1出現之前大型應用的首選收集器。

但是CMS並不完美,它有以下缺點:

由於併發進行,CMS在收集與應用線程會同時會增加對堆內存的佔用,也就是說,CMS必須要在老年代堆內存用盡之前完成垃圾回收,否則CMS回收失敗時,將觸發擔保機制,串行老年代收集器將會以STW的方式進行一次GC,從而造成較大停頓時間;
標記清除算法無法整理空間碎片,老年代空間會隨着應用時長被逐步耗盡,最後將不得不通過擔保機制對堆內存進行壓縮。CMS也提供了參數-XX:CMSFullGCsBeForeCompaction(默認0,即每次都進行內存整理)來指定多少次CMS收集之後,進行一次壓縮的Full GC。

G1

-XX:+UseG1GC

-XX:G1HeapRegionSize=n可指定分區大小(1MB~32MB,且必須是2的冪)

 

五、常用組合

常用組合
Serial/Serial Old

年輕代Serial收集器採用單個GC線程實現"複製"算法(包括掃描、複製)

年老代Serial Old收集器採用單個GC線程實現"標記-整理"算法

Serial與Serial Old都會暫停所有用戶線程(即STW)

適用場合:

CPU核數<2,物理內存<2G的機器(簡單來講,單CPU,新生代空間較小且對STW時間要求不高的情況下使用)

-XX:UseSerialGC:強制使用該GC組合

-XX:PrintGCApplicationStoppedTime:查看STW時間

ParNew/Serial Old 與上邊相比,只是比年輕代多了多線程垃圾回收而已
ParNew/CMS 當下比較高效的組合
Parallel Scavenge/Parallel Old

自動管理的組合 

年輕代Parallel Scavenge收集器採用多個GC線程實現"複製"算法(包括掃描、複製)年老代Parallel Old收集器採用多個GC線程實現"標記-整理"算ParallelScavenge與Parallel Old都會暫停所有用戶線程(即STW)

     適用於 很多的CPU計算任務而用戶交互任務較少的情況不想自己去過多的關注GC參數,想讓虛擬機自己進行調優工作

G1 最先進的收集器,但是需要JDK1.7update14以上
   

六、調優方法

1.預留新生代空間

  由於fullGC的成本遠比minorGC的成本打,所以給應用分配一個合理的新生代空間,儘量將對象分配到新生代減少fullGC的頻率

2.大對象進入老年代

   將大對象直接分配到老年代,保持新生代對象的結構完整性,以提高GC效率,以通過-XX:PretenureSizeThreshold設置進入老年代的閥值

3.穩定與震盪的堆大小

穩定的對大小是對垃圾回收有利的,方法將-Xms和-Xmx的大小一致

4.吞吐量優先

儘可能減少系統執行垃圾回收的總時間,故採用並行垃圾回收器XX:+UseParallelGC或使用-XX:+UseParallelOldGC

5.減低停頓

使用CMS回收器,同時減少fullGC的次數

七、調優工具

調優工具
jps 虛擬機進程狀況工具
jstat 虛擬機統計信息監視工具
jmap java內存印象工具
jhat 虛擬機堆轉儲快照分析工具
jstack java線程堆棧跟蹤工具
jinfo java配置信息工具
   

如果各項參數設置合理,系統沒有超時日誌出現,GC頻率不高,CG耗時不高,那麼沒有必要進行GC優化;如果GC時間超過1-3S,或者平方GC,則必須優化。如果滿足下面的指標,則一般不需要進行GC優化:

(1)Minor GC執行時間不到50ms;

  (2)MinorGC執行不頻繁,約10秒一次;

  (3)Full GC執行時間不到1s

  (4)FullGC執行平路不算頻繁,不低於10分鐘1次

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