1. 程式人生 > >使用Memory Analyzer tool(MAT)分析記憶體洩漏(一)

使用Memory Analyzer tool(MAT)分析記憶體洩漏(一)

前言

在平時工作過程中,有時會遇到OutOfMemoryError,我們知道遇到Error一般表明程式存在著嚴重問題,可能是災難性的。所以找出是什麼原因造成OutOfMemoryError非常重要。現在向大家引薦Eclipse Memory Analyzer tool(MAT),來化解我們遇到的難題。如未說明,本文均使用Java 5.0 on Windows XP SP3環境。

為什麼用MAT

之前的觀點,我認為使用實時profiling/monitoring之類的工具,用一種非常實時的方式來分析哪裡存在記憶體洩漏是很正確的。年初使用了某profiler工具測試訊息中介軟體中存在的記憶體洩漏,發現在吞吐量很高的時候profiler工具自己也無法響應,這讓人很頭痛。後來瞭解到這樣的工具本身就要消耗效能,且在某些條件下還發現不了洩漏。所以,分析離線資料就非常重要了,MAT正是這樣一款工具。

為何會記憶體溢位

我們知道JVM根據generation(代)來進行GC,根據下圖所示,一共被分為young generation(年輕代)、tenured generation(老年代)、permanent generation(永久代, perm gen),perm gen(或稱Non-Heap 非堆)是個異類,稍後會講到。注意,heap空間不包括perm gen。

絕大多數的物件都在young generation被分配,也在young generation被收回,當young generation的空間被填滿,GC會進行minor collection(次回收),這次回收不涉及到heap中的其他generation,minor collection根據weak generational hypothesis(弱年代假設)來假設younggeneration中大量的物件都是垃圾需要回收,minor collection的過程會非常快。young generation中未被回收的物件被轉移到tenured generation,然而tenured generation也會被填滿,最終觸發major collection(主回收),這次回收針對整個heap,由於涉及到大量物件,所以比minor collection慢得多。

JVM有三種垃圾回收器,分別是throughputcollector,用來做並行young generation回收,由引數-XX:+UseParallelGC啟動;concurrent low pause collector,用來做tenuredgeneration併發回收,由引數-XX:+UseConcMarkSweepGC啟動;incremental lowpause collector,可以認為是預設的垃圾回收器。不建議直接使用某種垃圾回收器,最好讓JVM自己決斷,除非自己有足夠的把握。

Heap中各generation空間是如何劃分的?通過JVM的-Xmx=n引數可指定最大heap空間,而-Xms=n

則是指定最小heap空間。在JVM初始化的時候,如果最小heap空間小於最大heap空間的話,如上圖所示JVM會把未用到的空間標註為Virtual。除了這兩個引數還有-XX:MinHeapFreeRatio=n和-XX:MaxHeapFreeRatio=n來分別控制最大、最小的剩餘空間與活動物件之比例。在32位Solaris SPARC作業系統下,預設值如下,在32位windows xp下,預設值也差不多。

引數

預設值

MinHeapFreeRatio

40

MaxHeapFreeRatio

70

-Xms

3670k

-Xmx

64m

由於tenured generation的major collection較慢,所以tenured generation空間小於young generation的話,會造成頻繁的major collection,影響效率。Server JVM預設的young generation和tenured generation空間比例為1:2,也就是說young generation的eden和survivor空間之和是整個heap(當然不包括perm gen)的三分之一,該比例可以通過-XX:NewRatio=n引數來控制,而Client JVM預設的-XX:NewRatio是8。至於調整young generation空間大小的NewSize=n和MaxNewSize=n引數就不講了,請參考後面的資料。

young generation中倖存的物件被轉移到tenuredgeneration,但不幸的是concurrent collector執行緒在這裡進行major collection,而在回收任務結束前空間被耗盡了,這時將會發生Full Collections(Full GC),整個應用程式都會停止下來直到回收完成。FullGC是高負載生產環境的噩夢……

現在來說說異類perm gen,它是JVM用來儲存無法在Java語言級描述的物件,這些物件分別是類和方法資料(與class loader有關)以及interned strings(字串駐留)。一般32位OS下perm gen預設64m,可通過引數-XX:MaxPermSize=n指定,JVM Memory Structure一文說,對於這塊區域,沒有更詳細的文獻了,神祕。

回到問題“為何會記憶體溢位?”。

要回答這個問題又要引出另外一個話題,既什麼樣的物件GC才會回收?當然是GC發現通過任何reference chain(引用鏈)無法訪問某個物件的時候,該物件即被回收。名詞GC Roots正是分析這一過程的起點,例如JVM自己確保了物件的可到達性(那麼JVM就是GC Roots),所以GC Roots就是這樣在記憶體中保持物件可到達性的,一旦不可到達,即被回收。通常GC Roots是一個在current thread(當前執行緒)的call stack(呼叫棧)上的物件(例如方法引數和區域性變數),或者是執行緒自身或者是system class loader(系統類載入器)載入的類以及native code(原生代碼)保留的活動物件。所以GC Roots是分析物件為何還存活於記憶體中的利器。知道了什麼樣的物件GC才會回收後,再來學習下物件引用都包含哪些吧。

從最強到最弱,不同的引用(可到達性)級別反映了物件的生命週期。

l  Strong Ref(強引用):通常我們編寫的程式碼都是Strong Ref,於此對應的是強可達性,只有去掉強可達,物件才被回收。

l  Soft Ref(軟引用):對應軟可達性,只要有足夠的記憶體,就一直保持物件,直到發現記憶體吃緊且沒有Strong Ref時才回收物件。一般可用來實現快取,通過java.lang.ref.SoftReference類實現。

l  Weak Ref(弱引用):比Soft Ref更弱,當發現不存在Strong Ref時,立刻回收物件而不必等到記憶體吃緊的時候。通過java.lang.ref.WeakReference和java.util.WeakHashMap類實現。

l  Phantom Ref(虛引用):根本不會在記憶體中保持任何物件,你只能使用Phantom Ref本身。一般用於在進入finalize()方法後進行特殊的清理過程,通過java.lang.ref.PhantomReference實現。

有了上面的種種我相信很容易就能把heap和perm gen撐破了吧,是的利用Strong Ref,儲存大量資料,直到heap撐破;利用interned strings(或者class loader載入大量的類)把perm gen撐破。

關於shallowsize、retained size

Shallow size就是物件本身佔用記憶體的大小,不包含對其他物件的引用,也就是物件頭加成員變數(不是成員變數的值)的總和。在32位系統上,物件頭佔用8位元組,int佔用4位元組,不管成員變數(物件或陣列)是否引用了其他物件(例項)或者賦值為null它始終佔用4位元組。故此,對於String物件例項來說,它有三個int成員(3*4=12位元組)、一個char[]成員(1*4=4位元組)以及一個物件頭(8位元組),總共3*4 +1*4+8=24位元組。根據這一原則,對String a=”rosen jiang”來說,例項a的shallow size也是24位元組(很多人對此有爭議,請看官甄別並留言給我)。

Retained size是該物件自己的shallow size,加上從該物件能直接或間接訪問到物件的shallow size之和。換句話說,retained size是該物件被GC之後所能回收到記憶體的總和。為了更好的理解retained size,不妨看個例子。

把記憶體中的物件看成下圖中的節點,並且物件和物件之間互相引用。這裡有一個特殊的節點GC Roots,正解!這就是reference chain的起點。

retained_objects.gifretained_objects_2.gif

從obj1入手,上圖中藍色節點代表僅僅只有通過obj1才能直接或間接訪問的物件。因為可以通過GC Roots訪問,所以左圖的obj3不是藍色節點;而在右圖卻是藍色,因為它已經被包含在retained集合內。

所以對於左圖,obj1的retained size是obj1、obj2、obj4的shallow size總和;右圖的retained size是obj1、obj2、obj3、obj4的shallow size總和。obj2的retained size可以通過相同的方式計算。

Heap Dump

heap dump是特定時間點,java程序的記憶體快照。有不同的格式來儲存這些資料,總的來說包含了快照被觸發時java物件和類在heap中的情況。由於快照只是一瞬間的事情,所以heap dump中無法包含一個物件在何時、何地(哪個方法中)被分配這樣的資訊。

在不同平臺和不同java版本有不同的方式獲取heap dump,而MAT需要的是HPROF格式的heap dump二進位制檔案。想無需人工干預的話,要這樣配置JVM引數:-XX:-HeapDumpOnOutOfMemoryError,當錯誤發生時,會自動生成heapdump,在生產環境中,只有用這種方式。如果你想自己控制什麼時候生成heap dump,在Windows+JDK6環境中可利用JConsole工具,而在Linux或者Mac OS X環境下均可使用JDK5、6自帶的jmap工具。當然,還可以配置JVM引數:-XX:+HeapDumpOnCtrlBreak,也就是在控制檯使用Ctrl+Break鍵來生成heap dump。由於我是windows+JDK5,所以選擇了-XX:-HeapDumpOnOutOfMemoryError這種方式,更多配置請參考MAT Wiki

參考資料

相關推薦

使用Memory Analyzer tool(MAT)分析記憶體洩漏()

前言 在平時工作過程中,有時會遇到OutOfMemoryError,我們知道遇到Error一般表明程式存在著嚴重問題,可能是災難性的。所以找出是什麼原因造成OutOfMemoryError非常重要。現在向大家引薦Eclipse Memory Analyzer tool(M

使用Memory Analyzer tool(MAT)分析記憶體洩漏

介紹Memory Analyzer tool (MAT) 經典文章,轉載留念: 注: 文章中提到在Eclipse中配置VM引數-XX:+HeapDumpOnOutOfMemoryError方法:           在Eclipse中的專案中的Run Configurati

Analyzer tool(MAT)分析JVM內存泄露案例

gc roots 菜單 exc fff open 技術分享 consumer tool 圖形 1、監控目的 2、常用分析工具 3、分析案例-MATMAT 介紹及分析:啟動MAT, 然後選擇菜單項 File- Open Heap Dump 來加載需要分析的堆轉儲文件。文件

Android Studio +MAT 分析記憶體洩漏實戰

對於記憶體洩漏,在Android中如果不注意的話,還是很容易出現的,尤其是在Activity中,比較容易出現,下面我就說下自己是如何查詢記憶體洩露的。 首先什麼是記憶體洩漏? 記憶體洩漏就是一些已經不使用的物件還存在於記憶體之中且垃圾回收機制無法回收它們,導致它們常駐記憶體,會使記憶

Android之Mat分析記憶體洩漏

安裝完成後提示重啟Eclipse,重啟後開啟window - > open perspective,看到Memory Analysis證明安裝成功。 mat的使用 1.生成hprof檔案 1)進入DDMS 2)在Devices中選擇需要監聽的

記憶體洩漏檢測分析工具mat(memory analyzer tool) 的使用

.下載、安裝 地址:http://www.eclipse.org/mat/downloads.php  直接解壓即可 初始介面 .獲取對應程序的heapdump,使用jmap命令         jmap -dump:

記憶體洩漏檢測分析工具MATMemory Analyzer Tool)的使用

工具下載地址:https://www.eclipse.org/mat/   首先準備一個案例demo。上次講了經典Handler導致的記憶體洩漏,今天也講個經典例子。單例造成的記憶體洩漏。 public class MySingleton { priva

Eclipse MAT記憶體分析工具(Memory Analyzer Tool

MAT記憶體分析工具 MAT是Memory Analyzer的簡稱,它是一款功能強大的Java堆記憶體分析器。可以用於查詢記憶體洩露以及檢視記憶體消耗情況。MAT是基於Eclipse開發的,是一款免費的效能分析工具。讀者可以在http://www.eclipse.org/mat/下載並使用MAT。 1 初

次通過Memory Analyzer分析記憶體洩漏的解決過程

狀況描述: 最近專案新打的版本,過不了多長時間,專案就會掛掉。狀況就是處於一種假死的狀態。索引查詢都很慢,幾乎進行不了任何操作,慢慢卡死。 然後我們再發版時,只能基於之前打好的war包,替換或者增加c

記憶體分析工具MAT(Memory Analyzer Tool)從安裝到使用

一.安裝 首先,你得有一個Eclipse(因為MAT是Eclipse的外掛) 然後,你要在Eclipse上安裝MAT,步驟如下: 1.點選Help,Install New Soft,就出現了以下Install介面:然後我們點選ADD,在彈出的框中填上Mat外掛的地址:htt

記憶體分析工具MAT(Memory Analyzer Tool)從安裝到使用,配合jconsole jvisualvm分析

一.安裝 首先,你得有一個Eclipse(因為MAT是Eclipse的外掛) 然後,你要在Eclipse上安裝MAT,步驟如下: 1.點選Help,Install New Soft,就出現了以下Install介面:然後我們點選ADD,在彈出的框中填上Mat外掛的地址:h

eclipse記憶體分析工具MAT Memory Analyzer Tool 外掛安裝(圖解)

第一步:下載Eclipse MAT 下載地址:http://www.eclipse.org/mat/downloads.php 第二步:下載之後將壓縮包解壓,放置到Myeclipse 的\MyEclipse 9\dropins目錄下 解壓後會看見這些檔案: 糾正下面一個錯別字不是"寫"是 "下"

Eclipse MAT內存分析工具(Memory Analyzer Tool

vector 集合實例 address 說明 bpa 使用情況 snap 索引 length MAT內存分析工具 MAT是Memory Analyzer的簡稱,它是一款功能強大的Java堆內存分析器。可以用於查找內存泄露以及查看內存消耗情況。MAT是基於Eclipse開發的

MAT(Memory Analyzer tool)使用

模擬 index st2 -c mx2 ID www. ray 執行 當線上環境出現OOM/內存泄漏了,怎麽辦? 讓虛擬機在發生內存溢出時 Dump 出當前的內存堆轉儲快照,配置-XX:+HeapDumpOnOutOfMemoryError, 當出現OOM時,分析dump下

JVM:使用 MAT 工具結合jmap命令分析記憶體洩漏

1、下載MAT工具 2、演示記憶體溢位 新建一個springboot專案,新建一個controller @RestController public class HeapControler { private ArrayList<User> a

MAT(Memory Analyzer Tool)工具入門介紹

1、MAT是什麼?     MAT(Memory Analyzer Tool),一個基於Eclipse的記憶體分析工具,是一個快速、功能豐富的JAVA heap分析工具,它可以幫助我們查詢記憶體洩漏和減少記憶體消耗。使用記憶體分析工具從眾多的物件中進行分析,快速的計算出在記

MAT(Memory Analyzer Tool)工具入門介紹(轉)

1、MAT是什麼?     MAT(Memory Analyzer Tool),一個基於Eclipse的記憶體分析工具,是一個快速、功能豐富的JAVA heap分析工具,它可以幫助我們查詢記憶體洩漏和減少記憶體消耗。使用記憶體分析工具從眾多的物件中進行分析,快速的計算出在記憶體中物件的佔用大小,看看是誰阻止

MAT Memory Analyzer Tool 外掛安裝(圖解)

@author YHC 前段時間做了一個專案,Exception in thread "main" java.lang.OutOfMemoryError: Java heap space 出現這個錯誤,所以需要查詢原因,所以就用到這個工具,安裝比較麻煩,貼出來和大家共享一下

android 中如何分析記憶體洩漏

前提條件: 1,電腦安裝了java 執行環境   2,手機端開啟了 USB 除錯開關  3,獲取 root 許可權 4,安裝MAT工具,下載地址:http://www.eclipse.org/mat/downloads.php 基本步驟: 1,使用eclipse 自帶的 D

手把手教你在Android Studio 3.0上分析記憶體洩漏

這個不用梯子我會告訴你嗎 1.寫在前面 Google在上週釋出了Android Studio 3.0的正式版本,週四早晨在上班的地鐵上就看到群裡在沸沸揚揚的討論關於3.0版本的各種坑,啊,不對,各種特性,到公司之後就迫不及待的更新了3.0版本