jmap命令 檢查記憶體洩漏
阿新 • • 發佈:2020-09-02
命令介紹
jmap - Prints shared object memory maps or heap memory details for a process, core file, or remote
debug server.
jmap不僅能生成dump檔案,還闊以查詢finalize執行佇列、Java堆和永久代的詳細資訊,如當前使用率、當前使用的是哪種收集器等。主要的作用是檢查記憶體洩漏、物件建立不合理和銷燬等問題
語法:
jmap [ options ] pid
jmap [ options ] executable core
jmap [ options ] [ pid ] server-id@ ] remote-hostname-or-IP
常用選項
-dump:[live,] format=b, file=filename
dump堆使用資訊到檔案,format指定格式,live指存活的物件,file為檔名
[root@node1 ~]# jmap -dump:live,format=b,file=hprof.dump 2712
2712: Unable to open socket file: target process not responding or HotSpot VM not loaded
The -F option can be used when the target process is not responding
報錯原因:
jvm執行時會生成一個目錄hsperfdata_$USER($USER是啟動java程序的使用者),在linux中預設是/tmp。目錄下會有些pid檔案,存放jvm程序資訊。
jvm相關命令會從這個路徑/tmp/hsperfdata_$USER去獲取pid的連線資訊,我是root使用者執行的命令,所以沒有pid檔案,而對應應用程式裡面有
例如:
jmap報錯原因:
可能是由於tmpwatch機制,防止/tmp目錄裡檔案過多,系統每天基於此機制刪除超過240小時未訪問的檔案和目錄。
jmap和jstack不能正常執行的原因:
因為對應目錄裡沒有pid檔案
檢視關鍵配置/etc/cron.daily/tmpwatch:
flags=-umc /usr/sbin/tmpwatch "$flags"
-x /tmp/.X11-unix -x /tmp/.XIM-unix \
-x /tmp/.font-unix -x /tmp/.ICE-unix
-x /tmp/.Test-unix 240 /tmp /usr/sbin/tmpwatch "$flags" 720 /var/tmp
for d in /var/{cache/man,catman}/{cat?,X11R6/cat?,local/cat?};
do if [ -d "$d" ]; then /usr/sbin/tmpwatch "$flags" -f 720 "$d" fi done
解決辦法:
1、修改對應應用的Djava.io.tmpdir引數,統一使用/tmp目錄。重啟應用
2、修改/etc/cron.daily/tmpwatch
/usr/sbin/tmpwatch "$flags" -x /tmp/hsperfdata_* -x /tmp/.X11-unix -x /tmp/.XIM-unix
-x /tmp/.font-unix -x /tmp/.ICE-unix -x /tmp/.Test-unix 240 /tmp
[root@node1 ~]# jmap -F -dump:live,format=b,file=hprof.dump 2712
Attaching to process ID 2712, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.201-b09
Dumping heap to hprof.dump ...
Heap dump file created
dump.hprof這個字尾是為了後續可以直接用MAT(Memory Anlysis Tool)開啟。
-finalizerinfo :列印等待回收物件的資訊
[root@node1 ~]# jmap -finalizerinfo 2712
Attaching to process ID 2712, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.201-b09
Number of objects pending for finalization: 0
可以看到當前F-QUEUE佇列中並沒有等待Finalizer執行緒執行finalizer方法的物件。
-heap :列印heap的概要資訊,GC使用的演算法,heap的配置及wise heap的使用情況,可以用此來判斷記憶體目前的使用情況以及垃圾回收情況
[root@node1 ~]# jmap -heap 2712
Attaching to process ID 2712, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.201-b09
using thread-local object allocation.
Parallel GC with 2 thread(s) # GC方式
Heap Configuration: // 堆記憶體初始化配置
MinHeapFreeRatio = 0 // 對應jvm啟動引數-XX:MinHeapFreeRatio設定JVM堆最小空閒比率(default 40)
MaxHeapFreeRatio = 100 // 對應jvm啟動引數 -XX:MaxHeapFreeRatio設定JVM堆最大空閒比率(default 70)
MaxHeapSize = 52428800 (50.0MB) // 對應jvm啟動引數-XX:MaxHeapSize=設定JVM堆的最大大小
NewSize = 17301504 (16.5MB) // 對應jvm啟動引數-XX:NewSize=設定JVM堆的‘新生代’的預設大小
MaxNewSize = 17301504 (16.5MB) // 對應jvm啟動引數-XX:MaxNewSize=設定JVM堆的‘新生代’的最大大小
OldSize = 35127296 (33.5MB) // 對應jvm啟動引數-XX:OldSize=<value>:設定JVM堆的‘老生代’的大小
NewRatio = 2 // 對應jvm啟動引數-XX:NewRatio=:‘新生代’和‘老生代’的大小比率
SurvivorRatio = 8 // 對應jvm啟動引數-XX:SurvivorRatio=設定年輕代中Eden區與Survivor區的大小比值
MetaspaceSize = 21807104 (20.796875MB) // 對應jvm啟動引數-XX:PermSize=<value>:設定JVM堆的‘永生代’的初始大小
CompressedClassSpaceSize = 1073741824 (1024.0MB) // 對應jvm啟動引數-XX:MaxPermSize=<value>:設定JVM堆的‘永生代’的最大大小
MaxMetaspaceSize = 17592186044415 MB
G1HeapRegionSize = 0 (0.0MB)
Heap Usage: // 堆記憶體使用情況
PS Young Generation
Eden Space: // Eden區記憶體分佈
capacity = 9961472 (9.5MB) // Eden區總容量
used = 3917840 (3.7363433837890625MB) // Eden區已使用
free = 6043632 (5.7636566162109375MB) // Eden區剩餘容量
39.32993035567434% used // Eden區使用比率
From Space: // 其中一個Survivor區的記憶體分佈
capacity = 3670016 (3.5MB)
used = 1028528 (0.9808807373046875MB)
free = 2641488 (2.5191192626953125MB)
28.025163922991073% used
To Space: // 另一個Survivor區的記憶體分佈
capacity = 3145728 (3.0MB)
used = 0 (0.0MB)
free = 3145728 (3.0MB)
0.0% used
PS Old Generation // 當前的Old區記憶體分佈
capacity = 35127296 (33.5MB)
used = 27684384 (26.401885986328125MB)
free = 7442912 (7.098114013671875MB)
78.81159995918843% used
20704 interned Strings occupying 2153624 bytes.
-histo :列印堆的物件統計,包括物件數、記憶體大小等等 (因為在dump:live前會進行full gc,如果帶上live則只統計活物件,因此不加live的堆大小要大於加live堆的大小 )
[root@node1 ~]# jmap -F -histo 2656
num #instances #bytes Class description
--------------------------------------------------------------------------
1: 526458 45456832 char[]
2: 275076 6601824 java.lang.String
3: 44613 5271264 byte[]
4: 215455 5170920 java.util.concurrent.ConcurrentSkipListMap$Node
5: 62357 4515576 int[]
6: 109775 2634600 java.lang.Double
7: 74848 2395136 java.util.HashMap$Node
8: 18442 1880400 java.util.HashMap$Node[]
9: 53471 1820904 java.lang.Object[]
....
僅僅列印了前10行
xml class name是物件型別,說明如下:
B byte
C char
D double
F float
I int
J long
Z boolean
[ 陣列,如[I表示int[]
[L+類名 其他物件