JDK本身為調(diào)試內(nèi)存泄漏問題提供了比較完善的工具。
先用命令jps找出要調(diào)試的jvm的進(jìn)程id(jps這個(gè)命令,就是ps命令前面加j,列出所有正在運(yùn)行的jvm的進(jìn)程id)。
例如:jps
輸出類似下面這樣:15976 java_app.jar 7586 startup.jar 22476 Jps 12248 Main 5437 Bootstrap
假設(shè)我們要調(diào)試的進(jìn)程id是15976.
如果只是想簡(jiǎn)單觀察一下堆內(nèi)存的使用情況,可以用命令jmap -histo:live 15976這個(gè)命令會(huì)輸出指定的jvm上當(dāng)前各個(gè)Java類的實(shí)例數(shù)、占用的內(nèi)存大小和完整的類名。虛擬機(jī)內(nèi)部類的類名前面有"*"標(biāo)記。
如果想得到堆內(nèi)存使用的詳細(xì)情況,可以用命令jmap -dump:live,format=b,file=/tmp/java_app-heap.bin 15976
這樣在/tmp目錄下得到一個(gè)java_app-heap.bin文件,其中保存的信息就是指定的jvm中堆內(nèi)存的使用詳情。這個(gè)二進(jìn)制文件可以用JDK附帶的jhat(Java Heap Analysis Tool)來分析:
jhat -J-Xmx326m /tmp/java_app-heap.bin
這個(gè)工具相當(dāng)耗內(nèi)存,如果出現(xiàn)了OutOfMemoryException的話,請(qǐng)加大-J-Xmx326m中指定的預(yù)留堆內(nèi)存大小再試。
Jhat會(huì)解析堆內(nèi)存信息轉(zhuǎn)儲(chǔ)文件(上面用jmap生成的。bin文件),輸出大概像下面這樣:
lewis@mgr $ jhat -J-Xmx326m /tmp/java_app-heap.bin Reading from /tmp/java_app-heap.bin……
Dump file created Thu Sep 08 20:08:14 CST 2011 Snapshot read, resolving……
Resolving 71327 objects……
Chasing references, expect 14 dots……
Eliminating duplicate references……
Snapshot resolved. Started HTTP server on port 7000 Server is ready.
注意最后兩行:堆內(nèi)存信息轉(zhuǎn)儲(chǔ)文件分析完畢后,jhat并不會(huì)將分析結(jié)果輸出為一個(gè)靜態(tài)文件。
為了方便查找,以及在相關(guān)的類之間導(dǎo)航,jhat會(huì)啟動(dòng)一個(gè)服務(wù),監(jiān)聽7000端口。這時(shí)候就可以用瀏覽器來瀏覽和分析結(jié)果了:在瀏覽器地址欄里輸入:
http://localhost:7000
里面的各個(gè)頁面都有很多鏈接,可以在相關(guān)的各個(gè)類及各種統(tǒng)計(jì)數(shù)據(jù)之間跳轉(zhuǎn),還是很方便的。