JVM GC優化

查看JVM的GC過程

在啓動你的程序的時候,使用-verbose:gc 參數,將程序的 GC情況輸出至 log 文本文件中。對log 文件進行簡要分析。
輸入的參數爲“-verbose:gc -Xloggc:gc.log -XX:+PrintGCTimeStamps -XX:+PrintGCDetails”將日誌文件輸入到gc.log中並且打印時間戳和GC的詳細信息。
這裏寫圖片描述
輸出的gc.log文件爲:
這裏寫圖片描述
發現:Minor GC的頻率較高,Full GC的頻率較低。
Minor GC每次耗費的時間0.01-0.03秒之間,Full GC的每次耗費的時間約爲0.13秒。
每次GC前後 heap 中各區域佔用情況的變化:
每次Minor GC前後,PSYoungGen區域的佔用減少。
每次Full GC前後,ParOldGen區域的佔用增加。

用jstat命令行工具的-gc和-gcutil參數

打開cmd,找到jdk的目錄下的bin文件夾,在其中執行jstat –gc 22784 250 112每250毫秒查詢一次進程22784垃圾收集狀況,一共查詢112次。其中的22784爲pid。
這裏寫圖片描述
其中:S0C:年輕代中第一個存活區的大小
S1C:年輕代中第二個存活區的大小
S0U:年輕代中第一個存活區已使用的空間 (KB)
S1U:年輕代中第二個存活區已使用的空間 (KB)
EC: Edem區大小
EU: 年輕代中Edem區已使用的空間 (KB)
OC: 老年代大小
OU: 老年代已使用的空間 (KB)
PC: 持久代大小
PU: 持久代已使用的空間 (KB)
YGC: 從應用程序啓動到採樣時young gc的次數
YGCT: 從應用程序啓動到採樣時young gc的所用的時間(s)
FGC: 從應用程序啓動到採樣時full gc的次數
FGCT: 從應用程序啓動到採樣時full gc的所用的時間
GCT: 從應用程序啓動到採樣時整個gc所用的時間
然後再使用-gcutil (GC統計彙總),輸入命令jstat –gcutil 25228 250 112.
這裏寫圖片描述
其中:S0 — Heap上的 Survivor space 0 區已使用空間的百分比
S1 — Heap上的 Survivor space 1 區已使用空間的百分比
E — Heap上的 Eden space 區已使用空間的百分比
O — Heap上的 Old space 區已使用空間的百分比
P — Perm space 區已使用空間的百分比
YGC — 從應用程序啓動到採樣時發生 Young GC 的次數
YGCT– 從應用程序啓動到採樣時 Young GC 所用的時間(單位秒)
FGC — 從應用程序啓動到採樣時發生 Full GC 的次數
FGCT– 從應用程序啓動到採樣時 Full GC 所用的時間(單位秒)
GCT — 從應用程序啓動到採樣時用於垃圾回收的總時間(單位秒)
分析:
程序運行期間young gc的次數大約爲38次,young gc的總時間時間大約爲0.816s,平均每次young gc的時間爲0.0215秒,時間較短,屬於正常。full gc的次數爲1次,用時0.151秒,整個程序用於垃圾回收的總時間爲1.12s,程序總運行時間爲27.552s,大約佔其時間的4.07%。
4次young gc之後,垃圾內存被從Eden space區(E)放入了Old space區(O),並引起了百分比的變化,導致Survivor space使用的百分比從31.25%(S0)降到25.00%(S1)。有效釋放了內存空間。上圖中,我們可以看到,一次full gc之後,Old space區(O)的內存被回收,從90.31%降到52.31%。
常駐內存區(P)的使用率,始終停留在93%-95%左右,說明常駐內存沒有突變,比較正常。
young gc和full gc能夠正常發生,而且都能有效回收內存,常駐內存區變化不明顯,則說明java內存釋放情況正常,垃圾回收及時,java內存泄露的機率就會大大降低。

使用jmap -heap命令行工具

在命令行中輸入jmap –heap 10864,顯示如圖:
這裏寫圖片描述
虛擬機當前使用的gc策略爲Parallel GC,heap 的配置情況(各區域的大小等)爲OldSize爲85.5MB,MaxHeapSize爲2018.0MB,NewSize爲42.5MB,MaxNewSize爲672.5MB,MetaspaceSize爲20.8MB,MaxMetaspaceSize爲17592186044415MB。heap 的使用情況統計,Eden已用101MB,剩餘79MB,FromSpace已用31MB,剩餘11MB,ToSpace已用0MB,剩餘44MB。Old已用86.5MB,剩餘56.7MB。

使用jmap -histo命令行工具

在命令行中輸入jmap –histo 17080,產生的結果如圖:
這裏寫圖片描述
查詢當前裝載進內存的各類的實例數目爲2767273,及內存佔用情況爲165538304bytes,約爲157MB。

使用jmap -permstat命令行工具

在命令行中輸入jmap –clstats 848(在jdk8之前用jmap -permstat命令)
這裏寫圖片描述
class loader總數爲76,class總數爲1687,總字節爲3020254,alive的爲1,dead爲75。

配置JVM參數並發現最優參數配置

JVM中的堆

首先我們要了解JVM中堆的分區情況:
這裏寫圖片描述
JVM堆分爲新生代,舊生代和年老代,新生代可用的gc方式有:串行gc(Serial Copying),並行回收gc(Parellel Scavenge),並行gc(ParNew),舊生代和年老代可用的gc方式有串行gc(Serial MSC),並行gc(Parallel MSC),併發gc(CMS)。

GC優化的標準

Minor GC執行時間不到50ms;
Minor GC執行不頻繁,約10秒一次;
Full GC執行時間不到1s;
Full GC執行頻率不算頻繁,不低於10分鐘1次;

重要的參數的含義

-Xmn 設置新生代大小
-XX:NewRatio 新生代(eden+2*s)和老年代(不包含永久區)的比值,例如:4,表示新生代:老年代=1:4,即新生代佔整個堆的1/5
-XX:SurvivorRatio(倖存代) 設置兩個Survivor區和eden的比值。例如:8,表示兩個Survivor:eden=2:8,即一個Survivor佔年輕代的1/10
-Xmx –Xms:指定最大堆和最小堆
-XX:+UseConcMarkSweepGC -XX:MaxTenuringThreshold=15 指定rmi調用時gc的時間間隔

優化方式

較大的heap會導致較少發生GC,但每次GC時間很長 。較小的heap,則需要頻繁GC,但每次GC的時間較短。
heap尺寸可隨時間變化 ,heap尺寸變化時需要full GC 。
CMS是用於對tenured generation的回收,也就是年老代的回收,目標是儘量減少應用的暫停時間,減少full gc發生的機率,利用和應用程序線程併發的垃圾回收線程來標記清除年老代。在我們的應用中,因爲有緩存的存在,並且對於響應時間也有比較高的要求,因此希望能嘗試使用CMS來替代默認的server型JVM使用的並行收集器,以便獲得更短的垃圾回收的暫停時間,提高程序的響應性。
例如,程序每秒都有大約400M的海量短命對象產生,那麼我們可以採用CMS收集器,並且對MaxTenuringThreshold(生代對象撐過過多少次minor gc才進入年老代的設置)設置爲較高參數(默認爲0)。得到了很大的性能優化。

Shallow heap & Retained heap

Shallow Size
對象自身佔用的內存大小,不包括它引用的對象。
針對非數組類型的對象,它的大小就是對象與它所有的成員變量大小的總和。當然這裏面還會包括一些java語言特性的數據存儲單元。
針對數組類型的對象,它的大小是數組元素對象的大小總和。
Retained Size
Retained Size=當前對象大小+當前對象可直接或間接引用到的對象的大小總和。(間接引用的含義:A->B->C, C就是間接引用)
換句話說,Retained Size就是當前對象被GC後,從Heap上總共能釋放掉的內存。
不過,釋放的時候還要排除被GC Roots直接或間接引用的對象。他們暫時不會被被當做Garbage。

參考GC優化文獻

gc優化小記
https://blog.csdn.net/u013593306/article/details/51838350
JVM GC 機制與性能優化
https://blog.csdn.net/antony9118/article/details/51375662
頻繁GC (Allocation Failure)及young gc時間過長分析
https://my.oschina.net/go4it/blog/1628795
《JVM故障診斷指南》之6 —— JVM verbose GC 輸出日誌指南
https://blog.csdn.net/wang8118/article/details/46273385
在IDE的後臺打印GC日誌
https://blog.csdn.net/u011767040/article/details/49180973
JVM調優:選擇合適的GC collector
https://blog.csdn.net/macyang/article/details/8731313
java jvm內存管理/gc策略/參數設置
https://www.cnblogs.com/yang-hao/p/5939487.html
java 堆中新生代老年代
https://blog.csdn.net/lvyuan30276/article/details/48527123

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