亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

教你用MAT工具分析Java堆內(nèi)存泄漏問題的解決方法

 更新時(shí)間:2021年06月25日 14:08:24   作者:朱季謙  
今天給大家?guī)淼氖顷P(guān)于Java的相關(guān)知識(shí),文章圍繞著如何使用MAT工具分析Java堆內(nèi)存泄漏問題的解決方法展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下

一、MAT概述與安裝

MAT,全稱Memory Analysis Tools,是一款分析Java堆內(nèi)存的工具,可以快速定位到堆內(nèi)泄漏問題。該工具提供了兩種使用方式,一種是插件版,可以安裝到Eclipse使用,另一種是獨(dú)立版,可以直接解壓使用。

我把獨(dú)立版MAT安裝包放到了網(wǎng)盤上,方便直接下載

鏈接: https://pan.baidu.com/s/1DVHlHuSfi_4TVl2ei5YuLA

提取碼: 42qt

獨(dú)立版解壓后,其內(nèi)部文件是這樣的——

這里有一個(gè)MemoryAnalyzer.ini文件,里面有一個(gè)Xmx參數(shù),默認(rèn)是-Xmx1024m,這代表MAT的最大內(nèi)存大小,根據(jù)具體分析的dump文件大小來做適當(dāng)調(diào)整。

點(diǎn)擊MemoryAnalyzer.exe,啟動(dòng)完成后,即可以使用它來檢查定位內(nèi)存泄漏相關(guān)的問題了。

二、內(nèi)存泄漏案例分析

下面,我會(huì)結(jié)合一個(gè)小案例來分享MAT的使用。

首先,用IDEA建立一個(gè)測(cè)試類——

public class example {
    public static void main(String[] args)  {
        List<User> list=new ArrayList<>();
        while (true){
            list.add(new User());
        }
    }
}

class User {
    private String name="demo";
    public User() {
    }
}

給這個(gè)測(cè)試類設(shè)置虛擬機(jī)參數(shù),設(shè)置如:-Xms2m -Xmx2m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:/local_system/git/demo/heapdump.hprof

這幾個(gè)參數(shù)的意義是:

-Xms2m -Xmx2m:堆最小內(nèi)存為2M,最大內(nèi)存為2M。這里沒有顯示設(shè)置新生代大小,它會(huì)自動(dòng)分配新生代大小,分配完剩下的,就是老年代大小了。

-XX:+HeapDumpOnOutOfMemoryError:指發(fā)生內(nèi)存溢出的時(shí)候,會(huì)自動(dòng)生成一個(gè)二進(jìn)制的堆快照文件,這個(gè)快照文件以.hprof后綴結(jié)尾。用MAT分析堆內(nèi)存信息,就是利用這個(gè).hprof文件。除了可以設(shè)置相應(yīng)的虛擬機(jī)參數(shù)外,還可以通過jmap指令來獲取到某個(gè)進(jìn)程的堆快照文件,執(zhí)行指令格式是:

jmap -dump:format=b,file=<dumpfile.hprof> <pid>

例如:jmap -dump:format=b,file=20210618.dump 7132,那么,這里20210618.dump就是自定義的dump堆轉(zhuǎn)儲(chǔ)文件名字,而7132是進(jìn)程ID。只是使用jmap指令可能有一點(diǎn)不好的地方是,內(nèi)存溢出是某個(gè)時(shí)間點(diǎn)發(fā)生的事情,jmap指令去獲取到dump文件,存在時(shí)間差問題。而HeapDumpOnOutOfMemoryError則是在發(fā)生內(nèi)存溢出時(shí),同時(shí)生成的,故而會(huì)更準(zhǔn)確些。

-XX:HeapDumpPath=D:/local_system/git/demo/heapdump.hprof:內(nèi)存溢出產(chǎn)生的堆快照自動(dòng)存儲(chǔ)路徑,可以自定義指定路徑。

其實(shí),在實(shí)際生產(chǎn)環(huán)境里,除了這些基本參數(shù)外,還有其他的JVM參數(shù),這些參數(shù)都是用來調(diào)優(yōu)的重點(diǎn)所在。

這里暫且以這些參數(shù)做實(shí)驗(yàn),在運(yùn)行IDEA時(shí),可以將這些參數(shù)設(shè)置在IDEA的“Run/Debug Configurations”彈出框的VM options輸入框里,如下截圖所示——

按照以上方式設(shè)置好后,就可以運(yùn)行該案例代碼了,運(yùn)行一會(huì)兒后,就會(huì)出現(xiàn)以下提示——

這表明,該代碼已經(jīng)發(fā)生內(nèi)存溢出了,即ArrayList存儲(chǔ)的對(duì)象大小已經(jīng)超過堆內(nèi)存,導(dǎo)致無法進(jìn)行垃圾回收,也就是出現(xiàn)內(nèi)存泄漏,進(jìn)而導(dǎo)致內(nèi)存溢出。當(dāng)然,在本地是可以看到這么簡(jiǎn)單的異常提示的,但是在線上服務(wù)器上,就沒有那么明顯的內(nèi)存溢出提示,就需要獲取到產(chǎn)生的堆快照dump文件,然后再進(jìn)一步分析堆快照信息。

三、使用MAT分析堆轉(zhuǎn)儲(chǔ)dump文件

我們將這個(gè)heapdump.hprof文件導(dǎo)入到MAT里。啟動(dòng)MAT,點(diǎn)擊File,選擇Open Heap Dump,然后選擇對(duì)應(yīng)的hprof文件

在彈出框處,選擇Leak Suspects Report,這是指內(nèi)存泄漏報(bào)告——

點(diǎn)擊Finish后,展示Overview主頁面如下——

Overview主頁面顯示應(yīng)用程序內(nèi)存使用情況的概覽,中間的餅圖按retained size來顯示最大的對(duì)象。注意一點(diǎn)是,在MAT中,會(huì)有兩種大小表示,一個(gè)是Retained size,還有一個(gè)是Shallow Size,那么,兩者有什么區(qū)別呢?

  • Shallow Size:表示對(duì)象自身占用的內(nèi)存大小,不包括它引用的對(duì)象。
  • Retained size:當(dāng)前對(duì)象內(nèi)存大小+當(dāng)前對(duì)象直接或間接引用的對(duì)象大小,全部的總和,簡(jiǎn)單理解,就是當(dāng)前對(duì)象被GC后,總共能釋放的內(nèi)存大小。

1.Details顯示的是dump文件的情況,表示堆大小為1.1MB,有516個(gè)class,40.2k個(gè)Object,3個(gè)類加載器等;

2.功能視圖模塊;

3.報(bào)表模塊;

我比較喜歡用Actions的Histogram視圖和Reports的Leak Suspects報(bào)表,Histogram視圖是以類為維度來顯示其實(shí)例數(shù)和每個(gè)類的使用內(nèi)存量,可以協(xié)助我們查詢哪些類對(duì)象占用較大內(nèi)存;Leak Suspects則可以協(xié)助分析內(nèi)存泄漏的原因所在。

- Histogram視圖

以Class Name為維度,分別展示各個(gè)類的對(duì)象數(shù)量,Shallow Size,Retained size。這里有一個(gè)疑惑是,Shallow Size和Retained size沒有顯示是以什么為單位的,它默認(rèn)是以byte為單位的,若要顯示地讓單位展示出來,可以這樣設(shè)置,點(diǎn)擊Window->Preferences

選擇最后一項(xiàng),點(diǎn)擊Apply and Close——

再重新打開Histogram視圖,就會(huì)生效了,單位就顯示出來了——

根據(jù)這個(gè)Histogram視圖,我們可以發(fā)現(xiàn),com.example.demo.User數(shù)量和占用內(nèi)存大小都比較高,同時(shí)說明了該User對(duì)象一直沒有被GC回收掉,這時(shí),可以右擊,彈出框有以下一些菜單選項(xiàng)——

List objects

使用List Object可以查看對(duì)象引用關(guān)系,這里查看引用功能,包括本對(duì)象引用外部對(duì)象with outgoing references與外部對(duì)象引用本對(duì)象with incoming references。

with outgoing references

使用該功能,可以查看對(duì)象內(nèi)部都引用了哪些外部對(duì)象,例如,這里的User,其引用外部對(duì)象情況如下:

對(duì)照這個(gè)案例的代碼,可見,在創(chuàng)建這個(gè)User對(duì)象時(shí),內(nèi)部屬性name就會(huì)指向一個(gè)字符串地址,換言之,該User對(duì)象內(nèi)部有個(gè)引用指向了一個(gè)name字符串地址。

with incoming references

​ 使用該功能,可以查看該對(duì)象都被哪些外部所引用了——

在案例代碼當(dāng)中,是以list.add(User)來不斷存儲(chǔ)User對(duì)象的,如截圖所示,通過MAT可確定,存在一個(gè)ArrayList集合一直引用該User對(duì)象。

在實(shí)際開發(fā)當(dāng)中,一個(gè)對(duì)象可能引用了諸多其他外部對(duì)象或者被諸多外部對(duì)象所引用,若一直引用著,說明某個(gè)對(duì)象一直存在GC ROOT可達(dá)的情況,反過來就意味著,該被引用的對(duì)象一直無法被GC回收處理,那么就可能會(huì)一直存在堆內(nèi)存里,進(jìn)而造成內(nèi)存泄漏的情況。

Merge Shortest Paths to GC Roots->exclude all phantom/weak/soft etc. references

排除其他引用,只觀察GC路徑上強(qiáng)引用的對(duì)象,所觀察到的,都是仍存活的對(duì)象。

除此之外,Histogram視圖仍有其他功能,后期在學(xué)習(xí)過程當(dāng)中,不斷進(jìn)行完善。

- Leak Suspects報(bào)表

Leak Suspects報(bào)表很直觀地展現(xiàn)了一個(gè)餅圖,圖中顏色深的部分表示可能存在內(nèi)存泄漏的嫌疑。每一個(gè)模塊都有對(duì)應(yīng)的詳情信息。

這里拿模塊a來講解,其詳情部分有一句話很關(guān)鍵:The memory is accumulated in one instance of "java.lang.Object[]", loaded by "", which occupies 617.55 KB (52.54%) bytes.The stacktrace of this Thread is available. See stacktrace. See stacktrace with involved local variables.

這句話翻譯過來就是,內(nèi)存累積在一個(gè)“java.lang.Object[]”實(shí)例中,由“”加載,占用617.55 KB(52.54%)字節(jié)。此線程的堆棧跟蹤可用。請(qǐng)參見stacktrace。請(qǐng)參閱包含局部變量的stacktrace。

點(diǎn)擊stacktrace,進(jìn)入到一個(gè)頁面,可以看到日志信息——

在這里,從下往上看異常信息,可以快速定位內(nèi)存泄漏地方出現(xiàn)在哪個(gè)類方法里的哪行代碼。

我很喜歡使用這個(gè)功能,通過獲取線上堆轉(zhuǎn)儲(chǔ)文件,便可以通過Leak Suspects定位到內(nèi)存泄漏快速定位在哪一行代碼。

到此這篇關(guān)于教你用MAT工具分析Java堆內(nèi)存泄漏問題的解決方法的文章就介紹到這了,更多相關(guān)Java堆內(nèi)存泄漏內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • ActiveMQ結(jié)合Spring收發(fā)消息的示例代碼

    ActiveMQ結(jié)合Spring收發(fā)消息的示例代碼

    這篇文章主要介紹了ActiveMQ結(jié)合Spring收發(fā)消息的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-10-10
  • Java使用反射來獲取泛型信息示例

    Java使用反射來獲取泛型信息示例

    這篇文章主要介紹了Java使用反射來獲取泛型信息,結(jié)合實(shí)例形式分析了java基于反射操作泛型信息的相關(guān)實(shí)現(xiàn)技巧與注意事項(xiàng),需要的朋友可以參考下
    2019-07-07
  • 用命令行編譯java并生成可執(zhí)行的jar包方法

    用命令行編譯java并生成可執(zhí)行的jar包方法

    下面小編就為大家分享一篇用命令行編譯java并生成可執(zhí)行的jar包方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2017-12-12
  • java解決單緩沖生產(chǎn)者消費(fèi)者問題示例

    java解決單緩沖生產(chǎn)者消費(fèi)者問題示例

    這篇文章主要介紹了java解單緩沖生產(chǎn)者消費(fèi)者問題示例,需要的朋友可以參考下
    2014-04-04
  • Java中Spring MVC接收表單數(shù)據(jù)的常用方法

    Java中Spring MVC接收表單數(shù)據(jù)的常用方法

    Spring MVC是Spring框架中的一個(gè)模塊,用于開發(fā)基于MVC(Model-View-Controller)架構(gòu)的Web應(yīng)用程序,它提供了一種輕量級(jí)的、靈活的方式來構(gòu)建Web應(yīng)用,同時(shí)提供了豐富的功能和特性,本文給大家介紹了Spring MVC接收表單數(shù)據(jù)的方法,需要的朋友可以參考下
    2024-05-05
  • 一個(gè)簡(jiǎn)單的Spring容器初始化流程詳解

    一個(gè)簡(jiǎn)單的Spring容器初始化流程詳解

    這篇文章主要給大家介紹了一個(gè)簡(jiǎn)單的Spring容器初始化流程的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • Java中的final關(guān)鍵字詳細(xì)介紹

    Java中的final關(guān)鍵字詳細(xì)介紹

    這篇文章主要介紹了Java中的final關(guān)鍵字,有需要的朋友可以參考一下
    2014-01-01
  • Spring手動(dòng)生成web.xml配置文件過程詳解

    Spring手動(dòng)生成web.xml配置文件過程詳解

    這篇文章主要介紹了Spring手動(dòng)生成web.xml配置文件過程詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-07-07
  • RocketMQ?Push?消費(fèi)模型示例詳解

    RocketMQ?Push?消費(fèi)模型示例詳解

    這篇文章主要為大家介紹了RocketMQ?Push?消費(fèi)模型示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • Spring Boot利用@Async異步調(diào)用:ThreadPoolTaskScheduler線程池的優(yōu)雅關(guān)閉詳解

    Spring Boot利用@Async異步調(diào)用:ThreadPoolTaskScheduler線程池的優(yōu)雅關(guān)閉詳解

    這篇文章主要給大家介紹了關(guān)于Spring Boot利用@Async異步調(diào)用:ThreadPoolTaskScheduler線程池的優(yōu)雅關(guān)閉的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-05-05

最新評(píng)論