JVM-GC日志查看分析

1.怎么查看日志

  • 首先在eclipse中準(zhǔn)備一個Gcdemo.java
package leetcode;
public class Gcdemo {
    public static void main(String[] args) {
         int _1m = 1024 * 1024;
            byte[] data = new byte[_1m];
            // 將data置為null即讓它成為垃圾
            data = null;
            // 通知垃圾回收器回收垃圾
            System.gc();
    }
}
  • 按如下圖運行這個demo 右鍵- Run AS - Run Configurations
  • 輸入如下圖參數(shù)-XX:+PrintGCDetails
  • 得到如圖內(nèi)容

    當(dāng)然也可以通過cmd的形式。
    在工程的bin層打開cmd 輸入命令:java -XX:+PrintGCDetails leetcode.Gcdemo

2.GC日志的參數(shù)

首先了解關(guān)于輸出GC日志的參數(shù)有以下幾種

-XX:+PrintGC 輸出GC日志
-XX:+PrintGCDetails 輸出GC的詳細(xì)日志
-XX:+PrintGCTimeStamps 輸出GC的時間戳(以基準(zhǔn)時間的形式)
-XX:+PrintGCDateStamps 輸出GC的時間戳(以日期的形式,如 2013-05-04T21:53:59.234+0800)
-XX:+PrintHeapAtGC 在進(jìn)行GC的前后打印出堆的信息
-Xloggc:../logs/gc.log 日志文件的輸出路徑

3.分析日志

[GC (System.gc()) [PSYoungGen: 2908K->680K(54784K)] 2908K->688K(180736K), 0.0314018 secs] [Times: user=0.00 sys=0.00, real=0.07 secs] 
[Full GC (System.gc()) [PSYoungGen: 680K->0K(54784K)] [ParOldGen: 8K->530K(125952K)] 688K->530K(180736K), [Metaspace: 2656K->2656K(1056768K)], 0.0115257 secs] [Times: user=0.03 sys=0.00, real=0.01 secs] 
Heap
 PSYoungGen      total 54784K, used 471K [0x0000000782f00000, 0x0000000786c00000, 0x00000007c0000000)
  eden space 47104K, 1% used [0x0000000782f00000,0x0000000782f75da0,0x0000000785d00000)
  from space 7680K, 0% used [0x0000000785d00000,0x0000000785d00000,0x0000000786480000)
  to   space 7680K, 0% used [0x0000000786480000,0x0000000786480000,0x0000000786c00000)
 ParOldGen       total 125952K, used 530K [0x0000000708c00000, 0x0000000710700000, 0x0000000782f00000)
  object space 125952K, 0% used [0x0000000708c00000,0x0000000708c84848,0x0000000710700000)
 Metaspace       used 2663K, capacity 4486K, committed 4864K, reserved 1056768K
  class space    used 288K, capacity 386K, committed 512K, reserved 1048576K

①GC日志開頭的[GC[Full GC說明了這次垃圾收集的類型.

Partial GC(局部 GC): 并不收集整個 GC 堆的模式
    - Young GC: 只收集young gen的GC,Young GC還有種說法就叫做 "Minor GC"
    - Old GC: 只收集old gen的GC。只有垃圾收集器CMS的concurrent collection 是這個模式
    - Mixed GC: 收集整個young gen 以及部分old gen的GC。只有垃圾收集器 G1有這個模式

Full GC 就是收集整個堆,包括新生代,老年代,永久代(在JDK 1.8及以后,永久代會被移除,換為metaspace(元空間))等收集所有部分的模式。

針對不同的垃圾收集器,F(xiàn)ull GC的觸發(fā)條件可能不都一樣。按HotSpot VM的serial GC的實現(xiàn)來看,觸發(fā)條件是:

1.當(dāng)準(zhǔn)備要觸發(fā)一次 young GC時,如果發(fā)現(xiàn)統(tǒng)計數(shù)據(jù)說之前 young GC的平均晉升大小比目前的 old gen剩余的空間大,則不會觸發(fā)young GC而是轉(zhuǎn)為觸發(fā) full GC 
(因為HotSpot VM的GC里,除了垃圾回收器 CMS的concurrent collection 之外,其他能收集old gen的GC都會同時收集整個GC堆,包括young gen,所以不需要事先準(zhǔn)備一次單獨的young GC)

2.如果有永久代(perm gen),要在永久代分配空間但已經(jīng)沒有足夠空間時,也要觸發(fā)一次 full GC

3.執(zhí)行System.gc(),heap dump帶GC,其默認(rèn)都是觸發(fā) full GC.

[PSYoungGen[ParOldGen是指GC發(fā)生的區(qū)域,分別代表使用Parallel Scavenge垃圾收集器的新生代和使用Parallel old垃圾收集器的老生代。為什么是這兩個垃圾收集器組合呢?因為我的jvm開啟的模式是Server,而Server模式的默認(rèn)垃圾收集器組合便是這個,在命令行輸入java -version就可以看到自己的jvm默認(rèn)開啟模式。還有一種是client模式,默認(rèn)組合是Serial收集器和Serial Old收集器組合。


③在方括號中PSYoungGen:后面的2908K->680K(54784K)代表的是GC前該內(nèi)存區(qū)域已使用的容量->GC后該內(nèi)存區(qū)域已使用的容量(該內(nèi)存區(qū)域總?cè)萘?/strong>)
④在方括號之外的2908K->688K(180736K)代表的是GC前Java堆已使用容量->GC后Java堆已使用容量(Java堆總?cè)萘?/strong>)
⑤再往后的0.0314018 secs代表該內(nèi)存區(qū)域GC所占用的時間,單位是秒。
⑥再后面的[Times: user=0.00 sys=0.00, real=0.07 secs],user代表進(jìn)程在用戶態(tài)消耗的CPU時間,sys代表代表進(jìn)程在內(nèi)核態(tài)消耗的CPU時間、real代表程序從開始到結(jié)束所用的時鐘時間。這個時間包括其他進(jìn)程使用的時間片和進(jìn)程阻塞的時間(比如等待 I/O 完成)

下面是堆詳細(xì)信息的日志
Heap
 PSYoungGen      total 54784K, used 471K [0x0000000782f00000, 0x0000000786c00000, 0x00000007c0000000)
  eden space 47104K, 1% used [0x0000000782f00000,0x0000000782f75da0,0x0000000785d00000)
  from space 7680K, 0% used [0x0000000785d00000,0x0000000785d00000,0x0000000786480000)
  to   space 7680K, 0% used [0x0000000786480000,0x0000000786480000,0x0000000786c00000)
 ParOldGen       total 125952K, used 530K [0x0000000708c00000, 0x0000000710700000, 0x0000000782f00000)
  object space 125952K, 0% used [0x0000000708c00000,0x0000000708c84848,0x0000000710700000)
 Metaspace       used 2663K, capacity 4486K, committed 4864K, reserved 1056768K
  class space    used 288K, capacity 386K, committed 512K, reserved 1048576K

先了解下Java memory劃分:
Java memory主要分heap memorynon-heap memory,如下圖:


⑦第一行為新生代的大小,大小為54784K。而新生代又分為三個區(qū)域分別叫Eden,和倆個Survivor spaces(fromto)。Eden用來存放新的對象,Survivor spaces用于 新對象 升級到Tenured area時的 拷貝。默認(rèn)的,Edem : from : to = 8 : 1 : 1( 可以通過參數(shù)–XX:SurvivorRatio來設(shè)定 ),即:Eden = 8/10 的新生代空間大小,from = to = 1/10的新生代空間大小。

⑧默認(rèn)的,新生代 ( Young) 與老年代 ( Old ) 的比例的值為 1:2( 該值可以通過參數(shù)–XX:NewRatio來指定 ),即:新生代 ( Young) = 1/3的堆空間大小。老年代 ( Old) = 2/3 的堆空間大小。其中,新生代 ( Young) 被細(xì)分為 Eden 和 兩個 Survivor區(qū)域,這兩個 Survivor區(qū)域分別被命名為 fromto,以示區(qū)分。

ParOldGen為老年代,大小為125952K,大約為PSYoungGen內(nèi)存大小的2倍。 從JDK8開始,永久代(PermGen)的概念被廢棄掉了,取而代之的是一個稱為Metaspace(元空間)的存儲空間。MetaspacePermGen之間最大的區(qū)別在于:Metaspace并不在虛擬機中,而是使用本地內(nèi)存。

文章參考:https://segmentfault.com/a/1190000012577387

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容