1. 程式人生 > 程式設計 >解決jmap命令列印JVM堆資訊異常的問題

解決jmap命令列印JVM堆資訊異常的問題

jmap命令可以列印java程序的JVM堆資訊,今天在某臺機器上執行該命令檢視 19560程序的堆資訊

jmap -heap 19560

出現以下異常

Attaching to process ID 19560,please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.79-b02
 
using thread-local object allocation.
Parallel GC with 33 thread(s)
 
Heap Configuration:
  MinHeapFreeRatio = 0
  MaxHeapFreeRatio = 100
  MaxHeapSize   = 32038191104 (30554.0MB)
  NewSize     = 1310720 (1.25MB)
  MaxNewSize    = 17592186044415 MB
  OldSize     = 5439488 (5.1875MB)
  NewRatio     = 2
  SurvivorRatio  = 8
  PermSize     = 21757952 (20.75MB)
  MaxPermSize   = 174063616 (166.0MB)
  G1HeapRegionSize = 0 (0.0MB)
 
Heap Usage:
Exception in thread "main" java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at sun.tools.jmap.JMap.runTool(JMap.java:197)
    at sun.tools.jmap.JMap.main(JMap.java:128)
Caused by: java.lang.RuntimeException: unknown CollectedHeap type : class sun.jvm.hotspot.gc_interface.CollectedHeap
    at sun.jvm.hotspot.tools.HeapSummary.run(HeapSummary.java:146)
    at sun.jvm.hotspot.tools.Tool.start(Tool.java:221)
    at sun.jvm.hotspot.tools.HeapSummary.main(HeapSummary.java:40)
    ... 6 more

是因為機器上缺少 openjdk-debuginfo 包 或者 機器上的 openjdk-debuginfo 包與jdk版本不一致導致

是用 java -version 檢視機器上的java版本

java version "1.7.0_79"

OpenJDK Runtime Environment (rhel-2.5.5.4.el6-x86_64 u79-b14)

OpenJDK 64-Bit Server VM (build 24.79-b02,mixed mode)

到 http://debuginfo.centos.org/6/x86_64/ 網站上去查詢和jdk版本對應的debuginfo包,我的jdk版本是 1.7.0_79,所以頁面展示完所有的包後,搜尋 openjdk-debuginfo-1.7.0.79,總共出現了三個包

java-1.7.0-openjdk-debuginfo-1.7.0.79-2.5.5.1.el6_6.x86_64.rpm

java-1.7.0-openjdk-debuginfo-1.7.0.79-2.5.5.3.el6_6.x86_64.rpm

java-1.7.0-openjdk-debuginfo-1.7.0.79-2.5.5.4.el6.x86_64.rpm

均滿足我的jdk版本,下載第一個進行嘗試,下載完成後使用 rpm命令安裝

rpm -ivh java-1.7.0-openjdk-debuginfo-1.7.0.79-2.5.5.1.el6_6.x86_64.rpm

安裝完成後使用檢視是否在已安裝列表中,執行命令顯示的確安裝成功

[root@identity_test tmp]# rpm -qa |grep debuginfo

java-1.7.0-openjdk-debuginfo-1.7.0.79-2.5.5.1.el6_6.x86_64

再次執行我最初想執行的命令

jmap -heap 19560

已經能正常顯示JVM堆區資訊

Attaching to process ID 19560,please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.79-b02
 
using thread-local object allocation.
Parallel GC with 33 thread(s)
 
Heap Configuration:
  MinHeapFreeRatio = 0
  MaxHeapFreeRatio = 100
  MaxHeapSize   = 32038191104 (30554.0MB)
  NewSize     = 1310720 (1.25MB)
  MaxNewSize    = 17592186044415 MB
  OldSize     = 5439488 (5.1875MB)
  NewRatio     = 2
  SurvivorRatio  = 8
  PermSize     = 21757952 (20.75MB)
  MaxPermSize   = 174063616 (166.0MB)
  G1HeapRegionSize = 0 (0.0MB)
 
Heap Usage:
PS Young Generation
Eden Space:
  capacity = 537919488 (513.0MB)
  used   = 532557632 (507.88653564453125MB)
  free   = 5361856 (5.11346435546875MB)
  99.00322332252071% used
From Space:
  capacity = 89128960 (85.0MB)
  used   = 0 (0.0MB)
  free   = 89128960 (85.0MB)
  0.0% used
To Space:
  capacity = 89128960 (85.0MB)
  used   = 0 (0.0MB)
  free   = 89128960 (85.0MB)
  0.0% used
PS Old Generation
  capacity = 1431306240 (1365.0MB)
  used   = 844440 (0.8053207397460938MB)
  free   = 1430461800 (1364.194679260254MB)
  0.058997856391655217% used
PS Perm Generation
  capacity = 22020096 (21.0MB)
  used   = 8512616 (8.118263244628906MB)
  free   = 13507480 (12.881736755371094MB)
  38.65839640299479% used
 
3145 interned Strings occupying 252104 bytes.

補充知識:JVM引數,jmap列印堆快照,jstack實戰死鎖

1 jinfo指令:如何執行時檢視引數值

jinfo -flag MaxHeapSize 23789(檢視最大堆:23789即執行緒id)

jinfo -flag ThreadStackSize 23789(查詢執行緒棧大小:預設值1024)

2 檢視jvm執行時引數

(1)-XX:+PrintFlagsInitial 檢視初始值

解決jmap命令列印JVM堆資訊異常的問題

=表示預設值

:=被使用者或者JVM修改後的值

(2)-XX:+PrintFlagsFinal表示打印出執行時引數生效的值

-XX:+UnlockExperimentalVMOptions解鎖實驗引數(並非所有的引數都可以直接修改)

(3)jps

jps是用於檢視有權訪問的hotspot虛擬機器的程序. 當未指定hostid時,預設檢視本機jvm程序,否者檢視指定的hostid機器上的jvm程序,此時hostid所指機器必須開啟jstatd服務。 jps可以列出jvm程序lvmid,主類類名,main函式引數,jvm引數,jar名稱等資訊。

(4)jinfo -flag 23789(檢視tomcat程序23789執行時jvm引數)

jinfo -flag UseParallelGC 23789

jinfo -flag UseG1GC 23789

jinfo -flag UseConcMarkSweepGC 23789

(5)jstat 檢視JVM統計資訊,例如類載入資訊、垃圾收集、JIT編譯

jstat -class 23789 載入了多少個類,佔用多少Kb,解除安裝多少個,平臺解除安裝載入所花費時間

jstat -gc 23789

jstat -gc 23789 1000 10 (每個1秒列印gc資訊,共列印10次)

解決jmap命令列印JVM堆資訊異常的問題

解決jmap命令列印JVM堆資訊異常的問題

Metaspace裡面有ccs,CodeCache等ccs表示啟用指向自己類檔案的短指標的時候就會存在ccs。CodeCache:存放jit編譯程式碼資訊。把java程式碼轉化為native程式碼。

(6)jmap+MAT實戰記憶體溢位

①匯出記憶體對映檔案:

自動匯出:

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./

jmap命令手動匯出:

jmap -dump:format=b,file=heap.hprof 23789

我們實驗的時候在eclipse debug新增引數:

-Xms23m -Xmx23m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./

②匯入mat中分析:

File -> openFile ->匯入自己的檔案heap.hprof

檢視可能存在記憶體溢位:

解決jmap命令列印JVM堆資訊異常的問題

檢視類佔用記憶體大小

解決jmap命令列印JVM堆資訊異常的問題

正則匹配檢視我們的類佔用記憶體大小(shallow heap不包括其內部引用物件大小)

(7)jstack 檢視執行緒

jstack 23789 > 23789.txt

注意: top命令檢視pid是十進位制的,printf “%x” 23789 就將23789轉化為16進位制5ced。然後在23789.txt中搜索ox5ced,就能找到pid對應的類資訊

死迴圈案例分析:

private Object lock1 = new Object();
private Object lock2 = new Object();
public  String deadlock() {
   new Thread(() -> {
  synchronized(lock1) {
  synchronized(lock1) {System.out.println(“Thread1 get lock1”)}
  try{Thread.sleep(5000);}cache(Exception e){}
  synchronized(lock2) {System.out.println(“Thread1 get lock2”)}
}
}).start();
new Thread(() -> {
  synchronized(lock2) {
  synchronized(lock1) {System.out.println(“Thread2 get lock2”)}
  try{Thread.sleep(5000);}cache(Exception e){}
  synchronized(lock1) {System.out.println(“Thread2 get lock1”)}
}
}).start();
}

jstack 執行緒id > 執行緒id.txt

解決jmap命令列印JVM堆資訊異常的問題

在檔案末尾,我們就可以看到明顯的死鎖資訊。

以上這篇解決jmap命令列印JVM堆資訊異常的問題就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援我們。