JAVA垃圾回收筆記

1、分析GC日誌java

/**
 * @author : Hejinsheng
 * @date : 2019/1/18 0018
 * @Description: 模擬FULL GC/YOUNG GC
 * -Xms100M -Xmx100M -Xmn32m -XX:SurvivorRatio=8 -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError
 */
public class GCTest {

    public static void main(String[] args) {
        List<Object> list = new ArrayList<>();
        for(int i=0;;i++){
            System.out.println(i);
            list.add(new byte[1024]);
        }
    }
}

打印的GC信息linux

[Full GC (Ergonomics) [PSYoungGen: 26624K->26623K(29696K)] [ParOldGen: 69631K->69630K(69632K)] 96255K->96253K(99328K), [Metaspace: 3298K->3298K(1056768K)], 0.0200149 secs] [Times: user=0.03 sys=0.00, real=0.02 secs]
[Full GC (Ergonomics) [PSYoungGen: 26624K->26623K(29696K)] [ParOldGen: 69631K->69631K(69632K)] 96255K->96255K(99328K), [Metaspace: 3298K->3298K(1056768K)], 0.0177546 secs] [Times: user=0.08 sys=0.00, real=0.02 secs]
[Full GC (Allocation Failure) [PSYoungGen: 26623K->26623K(29696K)] [ParOldGen: 69631K->69613K(69632K)] 96255K->96236K(99328K), [Metaspace: 3298K->3298K(1056768K)], 0.0466197 secs] [Times: user=0.03 sys=0.00, real=0.05 secs]多線程

1. 最前面的數字217.539:表明GC發生的時間,從虛擬機啓動開始算起工具

2. GC日誌開頭的[GC和FULL GC]說明此次垃圾收集的停頓類型,而不是區分新生代和老年代的。spa

FULL GC : 說明此次GC是發生了線程停頓Stop-The-World,若是是System.gc()方法所觸發的收集,,那麼在這裏將顯示[Full GC (System)線程

3. [DefNew,[Tenured,[Perm表示GC發生的區域,這裏顯示的區域名稱和使用的垃圾收集器是密切相關的日誌

1>在Serial收集器中新生代名爲Default New Generation ,顯示就是DefNeworm

2>垃圾收集器ParNew中新生代名稱就會變爲[Parnew,意思爲Parallel New Generation 對象

3>若是採用Parrallel Scavenge收集器,那麼它配套的新生代名稱爲PSYongGenblog

老年代和永久代同理,名稱由垃圾收集器決定

4.[DefNew: 102646K->10770K(102976K), 0.0415902 secs] 239776K->153169K(331528K), 0.0416785 secs] [Times: user=0.03 sys=0.02, real=0.04 secs] 就這段而言,

1>方括號內部102646K->10770K(102976K)的含義是GC前改內存區域已使用內存->GC後改內存區域使用容量(該內存區域總容量)

2>方括號外 239776K->153169K(331528K)表示GC前java堆已使用容量->GC後java堆已使用容量(java堆總容量)

3>在日後時間表示該內存區域gc清理用的時間

4>[Times: user=0.03 sys=0.02, real=0.04 secs]

這裏面的user、sys和real與linux的time命令所輸出的時間含義一致,分別表示用戶態消耗的CPU時間、內核態消耗的CPU事件和操做從開始到結束經歷的牆鍾時間

牆鍾時間和CPU時間的區別是,牆鍾時間包括各類非運算的等待耗時(i/o,線程阻塞),而CPU時間不包括這些,可是若是是多核,

多線程會疊加這些CPU時間,此時user或sys時間超過real時間徹底是正常的

 

2、獲取堆轉儲的幾種方式

Heap Dump 是 Java進程所使用的內存狀況在某一時間的一次快照。以文件的形式持久化到磁盤中。
Heap Dump的格式有不少種,並且不一樣的格式包含的信息也可能不同。但總的來講,Heap Dump通常都包含了一個堆中的Java Objects, Class等基本信息。同時,當你在執行一個轉儲操做時,每每會觸發一次GC,因此你轉儲獲得的文件裏包含的信息一般是有效的內容(包含比較少,或沒有垃圾對象了) 。

Heap Dump 包含的信息

全部的對象信息
  對象的類信息、字段信息、原生值(int, long等)及引用值
全部的類信息
  類加載器、類名、超類及靜態字段
垃圾回收的根對象
  根對象是指那些能夠直接被虛擬機觸及的對象
線程棧及局部變量
  包含了轉儲時刻的線程調用棧信息和棧幀中的局部變量信息
Heap Dump 獲取方式

1. 使用 jmap 命令生成 dump 文件

jmap -dump:live,format=b,file=d:\dump\heap.hprof <pid>

2. 使用 jcmd 命令生成 dump 文件

jcmd <pid> GC.heap_dump d:\dump\heap.hprof

3. 使用 JVM 參數獲取 dump 文件

  1. -XX:+HeapDumpOnOutOfMemoryError
  當OutOfMemoryError發生時自動生成 Heap Dump 文件。

  這但是一個很是有用的參數,由於當你須要分析Java內存使用狀況時,每每是在OOM(OutOfMemoryError)發生時。
  2. -XX:+HeapDumpBeforeFullGC
  當 JVM 執行 FullGC 前執行 dump。

  3. -XX:+HeapDumpAfterFullGC
  當 JVM 執行 FullGC 後執行 dump。

  4. -XX:+HeapDumpOnCtrlBreak
  交互式獲取dump。在控制檯按下快捷鍵Ctrl + Break時,JVM就會轉存一下堆快照。

  5. -XX:HeapDumpPath=d:\test.hprof
  指定 dump 文件存儲路徑。

  注意:JVM 生成 Heap Dump 的時候,虛擬機是暫停一切服務的。若是是線上系統執行 Heap Dump 時須要注意。

分析 工具:jdk 自帶的工具 jvisualvm、Eclipse memory analyzer(jmat)、JProfiler 等。

3、jvisualvm使用

一、點擊文件-裝入,載入dump下來的文件

 

二、點擊類選項卡

 

三、根據上圖分析實例數或佔用大小比例較高的類,右鍵 「在實例視圖中顯示」,如

找到可能發生內存泄漏或內存溢出的根對象

相關文章
相關標籤/搜索