一、jmap介紹
jmap是JDK自帶的一款用於獲取Java應用的heap或類信息快照的命令行工具,它能夠讓我們更好地了解內存中對象的使用情況,從而方便優化應用程序。
二、jmap常用選項
jmap有多個選項,我們通常會用到以下幾個:
-heap
該選項可以讓我們獲得應用程序的heap大小、佔用率等內存信息。例如:
jmap -heap 19321
這條命令會輸出進程號19321對應的Java應用的heap信息,例如:
Attaching to process ID 19321, please wait... Debugger attached successfully. Server compiler detected JVM version is 25.102-b14 using thread-local object allocation. Parallel GC with 4 thread(s) Heap Configuration: MinHeapFreeRatio = 40 MaxHeapFreeRatio = 70 MaxHeapSize = 2147483648 (2048.0MB) // 最大可用heap大小 NewSize = 1048576 (1.0MB) // 新生代大小 MaxNewSize = 33554432 (32.0MB) // 新生代最大大小 OldSize = 4194304 (4.0MB) // 老年代大小 NewRatio = 2 SurvivorRatio = 8 MetaspaceSize = 21807104 (20.796875MB) //永久代大小 CompressedClassSpaceSize = 1073741824 (1024.0MB) //壓縮類空間大小 MaxMetaspaceSize = 17592186044415 MB G1HeapRegionSize = 0 (0.0MB) Heap Usage: PS Young Generation Eden Space: capacity = 279183360 (266.125MB) // Eden區域容量 used = 36645336 (34.925048828125MB) // 已使用空間 free = 242538024 (231.199951171875MB) // 未使用空間 13.11123171556415% used //空間使用率 ...
-histo[:live]
該選項會輸出Java堆內存中的對象信息,包括對象的數量、佔用內存大小、類名等。如果加上”:live”參數,則只統計存活對象的信息。例如:
jmap -histo 19321
這條命令會輸出進程號19321對應的Java應用中對象的統計信息,例如:
num #instances #bytes class name ---------------------------------------------- 1: 183765 474534880 [C // char數組對象 2: 8749 274628312 [B // byte數組對象 3: 21869 164735880 java.lang.String 4: 9350 57402584 [I // int數組對象 5: 310942 49910872 java.util.LinkedHashMap$Entry ...
-dump:[live,]format=b,file=filename
該選項可以生成一個Java堆的dump文件,我們可以用jhat、MAT等工具來解析這個文件,進行一些內存分析。例如:
jmap -dump:live,format=b,file=heapdump.bin 19321
這條命令會生成進程號19321對應Java應用的存活對象的dump文件heapdump.bin。我們可以使用jhat工具來解析這個文件:
jhat heapdump.bin
然後在瀏覽器中訪問http://localhost:7000/即可查看內存分析報告。
三、jmap的優化實踐
1. 分析內存泄漏
使用jmap可以針對Java應用程序進行內存泄漏分析。如果應用程序出現了內存泄漏,就可以藉助jmap管理Java堆中的對象,通過GC日誌、堆轉儲文件等方式來確定內存泄漏的類型和原因。
下面是一個jmap分析內存泄漏的示例代碼:
public class MemoryLeak { private static List
在運行該程序之後,我們可以使用如下命令來獲取Java進程的pid:
jps -l
得到pid之後,我們可以使用如下命令來生成堆轉儲文件:
jmap -dump:live,format=b,file=heapdump.bin pid
使用MAT等工具,可以分析堆轉儲文件,找到內存泄漏的對象。例如,我們可以在MAT的Histogram視圖中查看對象數量排名前100的對象,如下圖所示:
可以看到,LinkedList$Entry對象數量排名第一,說明LinkedList中的節點佔用了大量的內存。打開該對象的histogram視圖,可以查看該對象的實例數量、大小、引用關係等信息,如下圖所示:
可以看到,可以直接從該對象的鏈表、size屬性追尋到具體的對象,從而找到內存泄漏的原因。
2. 分析OOM
jmap可以用於定位一個Java進程的OOM問題,步驟與上面類似。首先,需要在發生OOM的時候,使用jmap生成一個堆映射文件。這個文件可以與MAT等工具一起使用,從而進行內存分析。
下面是OOM的一些示例代碼:
public class OOMTest { private static List
在運行該程序之後,我們可以使用如下命令來獲取Java進程的pid:
jps -l
得到pid之後,我們可以使用如下命令來生成堆轉儲文件:
jmap -dump:live,format=b,file=heapdump.bin pid
使用MAT等工具,可以分析堆轉儲文件,找到OOM的原因。例如,我們可以在MAT的Histogram視圖中查看對象數量排名前10的對象,如下圖所示:
可以看到,Object實例的數量是最多的,Java應用在運行過程中創建了非常多的Object實例,使得堆內存被耗盡,從而發生了OOM。
四、jmap小結
jmap是一個非常強大的工具,可以幫助我們更好地了解Java應用程序的內存使用情況,從而進行優化。在實踐中,我們可以使用jmap分析內存泄漏、OOM等問題,從而根據分析結果對應用程序進行優化。
原創文章,作者:KTDSR,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/369467.html