標籤:並發 雙擊 java gc and 代碼 堆記憶體 顯示 int 時間長度
Java GC就是JVM記錄儀,書畫了JVM各個分區的表演。
什麼是 Java GC
Java GC(Garbage Collection,垃圾收集,記憶體回收)機制,是Java與C++/C的主要區別之一,作為Java開發人員,一般不需要專門編寫記憶體回收和垃圾清理代碼,對記憶體泄露和溢出的問題,也不需要像C程式員那樣戰戰兢兢。這是因為在Java虛擬機器中,存在自動記憶體管理和垃圾清掃機制。概括地說,該機制對JVM(Java Virtual Machine)中的記憶體進行標記,並確定哪些記憶體需要回收,根據一定的回收策略,自動的回收記憶體,永不停息(Nerver Stop)的保證JVM中的記憶體空間,防止出現記憶體泄露和溢出問題。
在Java語言出現之前,就有GC機制的存在,如Lisp語言),Java GC機制已經日臻完善,幾乎可以自動的為我們做絕大多數的事情。然而,如果我們從事較大型的應用軟體開發,曾經出現過記憶體最佳化的需求,就必定要研究Java GC機制。
簡單總結一下,Java GC就是通過GC收集器回收不在存活的對象,保證JVM更加高效的運轉。如果不瞭解GC演算法和記憶體回收行程可以參考這篇文章:jvm系列(三):GC演算法 垃圾收集器。
如何擷取 Java GC日誌
一般情況可以通過兩種方式來擷取GC日誌,一種是使用命令動態查看,一種是在容器中設定相關參數列印GC日誌。
命令動態查看
Java 自動的工具行命令,jstat可以用來動態監控JVM記憶體的使用,統計記憶體回收的各項資訊。
比如常用命令,jstat -gc 統計記憶體回收堆的行為
$ jstat -gc 1262 S0C S1C S0U S1U EC EU OC OU PC PU YGC YGCT FGC FGCT GCT 26112.0 24064.0 6562.5 0.0 564224.0 76274.5 434176.0 388518.3 524288.0 42724.7 320 6.417 1 0.398 6.815
也可以設定間隔固定時間來列印:
$ jstat -gc 1262 2000 20
這個命令意思就是每隔2000ms輸出1262的gc情況,一共輸出20次
更詳細的內容參考這篇文章:jvm系列(四):jvm調優-命令篇
GC參數
JVM的GC日誌的主要參數包括如下幾個:
-XX:+PrintGC 輸出GC日誌
-XX:+PrintGCDetails 輸出GC的詳細日誌
-XX:+PrintGCTimeStamps 輸出GC的時間戳記(以基準時間的形式)
-XX:+PrintGCDateStamps 輸出GC的時間戳記(以日期的形式,如 2017-09-04T21:53:59.234+0800)
-XX:+PrintHeapAtGC 在進行GC的前後列印出堆的資訊
-Xloggc:../logs/gc.log 記錄檔的輸出路徑
在生產環境中,根據需要配置相應的參數來監控JVM運行情況。
Tomcat 設定樣本
我們經常在tomcat的啟動參數中添加JVM相關參數,這裡有一個典型的樣本:
JAVA_OPTS="-server -Xms2000m -Xmx2000m -Xmn800m -XX:PermSize=64m -XX:MaxPermSize=256m -XX:SurvivorRatio=4-verbose:gc -Xloggc:$CATALINA_HOME/logs/gc.log -Djava.awt.headless=true -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Dsun.rmi.dgc.server.gcInterval=600000 -Dsun.rmi.dgc.client.gcInterval=600000-XX:+UseConcMarkSweepGC -XX:MaxTenuringThreshold=15"
根據上面的參數我們來做一下解析:
-
-Xms2000m -Xmx2000m -Xmn800m -XX:PermSize=64m -XX:MaxPermSize=256m
Xms,即為jvm啟動時得JVM初始堆大小,Xmx為jvm的最大堆大小,xmn為新生代的大小,permsize為永久代的初始大小,MaxPermSize為永久代的最大空間。
-
-XX:SurvivorRatio=4
SurvivorRatio為新生代空間中的Eden區和救助空間Survivor區的大小比值,預設是8,則兩個Survivor區與一個Eden區的比值為2:8,一個Survivor區占整個年輕代的1/10。調小這個參數將增大survivor區,讓對象盡量在survitor區呆長一點,減少進入年老代的對象。去掉救助空間的想法是讓大部分不能馬上回收的資料儘快進入年老代,加快年老代的回收頻率,減少年老代暴漲的可能性,這個是通過將-XX:SurvivorRatio 設定成比較大的值(比如65536)來做到。
-
-verbose:gc -Xloggc:$CATALINA_HOME/logs/gc.log
將虛擬機器每次記憶體回收的資訊寫到記錄檔中,檔案名稱由file指定,檔案格式是平檔案,內容和-verbose:gc輸出內容相同。
-
-Djava.awt.headless=true
Headless模式是系統的一種配置模式。在該模式下,系統缺少了顯示裝置、鍵盤或滑鼠。
-
-XX:+PrintGCTimeStamps -XX:+PrintGCDetails
設定gc日誌的格式
-
-Dsun.rmi.dgc.server.gcInterval=600000 -Dsun.rmi.dgc.client.gcInterval=600000
指定rmi調用時gc的時間間隔
-
-XX:+UseConcMarkSweepGC -XX:MaxTenuringThreshold=15
採用並發gc方式,經過15次minor gc 後進入年老代
如何分析GC日誌
摘錄GC日誌一部分
Young GC回收日誌:
2016-07-05T10:43:18.093+0800: 25.395: [GC [PSYoungGen: 274931K->10738K(274944K)] 371093K->147186K(450048K), 0.0668480 secs] [Times: user=0.17 sys=0.08, real=0.07 secs]
Full GC回收日誌:
2016-07-05T10:43:18.160+0800: 25.462: [Full GC [PSYoungGen: 10738K->0K(274944K)] [ParOldGen: 136447K->140379K(302592K)] 147186K->140379K(577536K) [PSPermGen: 85411K->85376K(171008K)], 0.6763541 secs] [Times: user=1.75 sys=0.02, real=0.68 secs]
通過上面日誌分析得出,PSYoungGen、ParOldGen、PSPermGen屬於Parallel收集器。其中PSYoungGen表示gc回收前後年輕代的記憶體變化;ParOldGen表示gc回收前後老年代的記憶體變化;PSPermGen表示gc回收前後永久區的記憶體變化。young gc 主要是針對年輕代進行記憶體回收比較頻繁,耗時短;full gc 會對整個堆記憶體進行回城,耗時間長度,因此一般盡量減少full gc的次數
通過兩張圖非常明顯看出gc日誌構成:
Young GC日誌:
Full GC日誌:
GC分析工具
GChisto
GChisto是一款專業分析gc日誌的工具,可以通過gc日誌來分析:Minor GC、full gc的時間、頻率等等,通過列表、報表、圖表等不同的形式來反應gc的情況。雖然介面略顯粗糙,但是功能還是不錯的。
配置好本地的jdk環境之後,雙擊GChisto.jar,在彈出的輸入框中點擊 add 選擇gc.log日誌
- GC Pause Stats:可以查看GC 的次數、GC的時間、GC的開銷、最大GC時間和最小GC時間等,以及相應的柱狀圖
不過這款工具已經不再維護
GC Easy
這是一個web工具,線上使用非常方便.
地址: http://gceasy.io
進入官網,講打包好的zip或者gz為尾碼的壓縮包上傳,過一會就會拿到分析結果。
推薦使用此工具進行gc分析。
jvm系列:Java GC 分析