java jmap 分析_利用java虚拟机的工具jmap分析java内存情况
有時(shí)候碰到性能問(wèn)題,比如一個(gè)java application出現(xiàn)out of memory,出現(xiàn)內(nèi)存泄漏的情況,再去修改bug可能會(huì)變得異常復(fù)雜,利用工具去分析整個(gè)java application 內(nèi)存占用情況,然后再去走查代碼。
首先先看一下,java內(nèi)存分配的基本模型,由于JVM內(nèi)存劃分比較復(fù)雜,這里只是簡(jiǎn)單的說(shuō)一下java內(nèi)存劃分
java 堆(heap):
Java?堆是被所有線程共享的一塊內(nèi)存區(qū)域,在虛擬機(jī)啟動(dòng)時(shí)創(chuàng)建。此內(nèi)存區(qū)域的
唯一目的就是存放對(duì)象實(shí)例,幾乎所有的對(duì)象實(shí)例都在這里分配內(nèi)存。
Java?堆是垃圾收集器管理的主要區(qū)域,因此很多時(shí)候也被稱(chēng)做“GC?堆”
所以Java?堆中還可以細(xì)分為:新生代和老年代;
新生代:所有新生成的對(duì)象首先都是放在年輕代的。年輕代的目標(biāo)就是盡可能快速的收集掉那些生命周期短的對(duì)象。
老年代(old Generation):在年輕代中經(jīng)歷了N次垃圾回收后仍然存活的對(duì)象,就會(huì)被放到年老代中。因此,可以認(rèn)為年老代中存放的都是一些生命周期較長(zhǎng)的對(duì)象
持久代(Prem Generation):用于存放靜態(tài)文件,如今Java類(lèi)、方法等。持久代對(duì)垃圾回收沒(méi)有顯著影響,但是有些應(yīng)用可能動(dòng)態(tài)生成或者調(diào)用一些class,例如Hibernate等,在這種時(shí)候需要設(shè)置一個(gè)比較大的持久代空間來(lái)存放這些運(yùn)行過(guò)程中新增的類(lèi)。持久代大小通過(guò)-XX:MaxPermSize=進(jìn)行設(shè)置。
再細(xì)致一點(diǎn)的有Eden?空間、From Survivor?空間、To Survivor?空間等。如果從內(nèi)存分配
的角度看,線程共享的Java?堆中可能劃分出多個(gè)線程私有的分配緩沖區(qū)(Thread Local
Allocation Buffer,TLAB)。不過(guò),無(wú)論如何劃分,都與存放內(nèi)容無(wú)關(guān),無(wú)論哪個(gè)區(qū)域,
存儲(chǔ)的都仍然是對(duì)象實(shí)例,進(jìn)一步劃分的目的是為了更好地回收內(nèi)存,或者更快地分配內(nèi)存。
java 棧區(qū):
JVM中運(yùn)行的每個(gè)線程都擁有自己的線程棧,線程棧包含了當(dāng)前線程執(zhí)行的方法調(diào)用相關(guān)信息,我們也把它稱(chēng)作調(diào)用棧。隨著代碼的不斷執(zhí)行,調(diào)用棧會(huì)不斷變化。
一般認(rèn)為 方法,局部變量,對(duì)象的引用 都是存在棧區(qū)內(nèi)的。
java方法區(qū):
方法區(qū)(Method Area)與Java?堆一樣,是各個(gè)線程共享的內(nèi)存區(qū)域,它用于存
儲(chǔ)已被虛擬機(jī)加載的類(lèi)信息、常量、靜態(tài)變量、即時(shí)編譯器編譯后的代碼等數(shù)據(jù)。
很多人稱(chēng)之為永生代(Permanent Generation);
出現(xiàn)out of memory 接著會(huì)出現(xiàn) java heap space,這種情況是堆空間滿了,
可能出現(xiàn)的情況,比如一個(gè)方法 進(jìn)棧了,里面有一段邏輯,最常見(jiàn)的就是打個(gè)比方
public void method(){
List list=...;
.... 執(zhí)行代碼的邏輯
}
這個(gè)list 里面有N多對(duì)象,但是執(zhí)行下面的邏輯時(shí)內(nèi)存溢出,這是因?yàn)榉椒ㄔ跊](méi)有出棧之前,java heap中的對(duì)象太多(方法在出棧之后GC 對(duì) 沒(méi)有引用的 對(duì)象進(jìn)行垃圾回收)。
還有 就是有一些全局的變量或者集合 ,或者存在方法區(qū)的 內(nèi)存 沒(méi)有進(jìn)行及時(shí)清理,導(dǎo)致內(nèi)存沒(méi)有釋放,這種稱(chēng)之為真泄漏。
2.1 利用jmap 進(jìn)行內(nèi)存分析,
jmap -heap pid //打印heap空間的概要,這里可以粗略的檢驗(yàn)heap空間的使用情況。
Heap Configuration:指java應(yīng)用啟動(dòng)時(shí)設(shè)置的JVM參數(shù)。像最大使用內(nèi)存大小,年老代,年青代,持久代大小等。
Heap Usage:當(dāng)時(shí)的heap實(shí)際使用情況。包括新生代、老生代和持久代。
其中新生代包括:Eden區(qū)的大小、已使用大小、空閑大小及使用率。Survive區(qū)的From和To同樣。
有這個(gè)可以很簡(jiǎn)單的查看本進(jìn)程的內(nèi)存使用情況。
可以用于分析堆內(nèi)存分區(qū)大小是否合理,新生代和老生代的大小分配是否合適等。
也許進(jìn)程占用的總內(nèi)存比較多,但我們?cè)谶@里可以看到真正用到的并沒(méi)有多少,很多都是"Free"。內(nèi)存使用的堆積大多在老年代,內(nèi)存池露始于此,所以要格外關(guān)心“Old Generation”。
jmap -histo PID //這里會(huì)生成一個(gè)類(lèi)的統(tǒng)計(jì)報(bào)表,此表非常簡(jiǎn)單,如顯示什么類(lèi)有多少個(gè)實(shí)例,共占了多少字節(jié)等。
2.2 ?利用jmap 生成dump 文件,然后再利用mat工具進(jìn)行分析。
jmap -dump:live,format=b,file=‘文件名 ’2657 //2657 是進(jìn)程的PID 號(hào)
生成轉(zhuǎn)儲(chǔ)文件之后,file -open(該轉(zhuǎn)儲(chǔ)文件)
上面的餅狀圖顯示了內(nèi)存分配的比例,通過(guò)dominator_tree可以看到詳細(xì)信息。
總結(jié)
以上是生活随笔為你收集整理的java jmap 分析_利用java虚拟机的工具jmap分析java内存情况的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 新能源产业迎重大利好!碳酸锂价格三个月大
- 下一篇: java dao service实例_浅