1. 程式人生 > >JVM 調優 - jmap

JVM 調優 - jmap

 

Java命令學習系列(三)——Jmap

2015-05-16 分類:Java 閱讀(17065) 評論(9) 阿里大牛珍藏架構資料,點選連結免費獲取

Jmap

jmap是JDK自帶的工具軟體,主要用於列印指定Java程序(或核心檔案、遠端除錯伺服器)的共享物件記憶體對映或堆記憶體細節。可以使用jmap生成Heap Dump。在Java命令學習系列(零)——常見命令及Java Dump介紹Java命令學習系列(二)——Jstack中分別有關於Java Dump以及執行緒 Dump的介紹。 這篇文章主要介紹Java的堆Dump以及jamp命令

 

什麼是堆Dump

堆Dump是反應Java堆使用情況的記憶體映象,其中主要包括系統資訊虛擬機器屬性完整的執行緒Dump所有類和物件的狀態等。 一般,在記憶體不足、GC異常等情況下,我們就會懷疑有記憶體洩露。這個時候我們就可以製作堆Dump來檢視具體情況。分析原因。

基礎知識

Java虛擬機器的記憶體組成以及堆記憶體介紹 Java GC工作原理 常見記憶體錯誤:

outOfMemoryError 年老代記憶體不足。 outOfMemoryError:PermGen Space 永久代記憶體不足。 outOfMemoryError:GC overhead limit exceed 垃圾回收時間佔用系統執行時間的98%或以上。

jmap

用法摘要

Usage: jmap [option] <pid> (to connect to running process) jmap [option] <executable <core> (to connect to a core file) jmap [option] [[email protected]]<remote server IP or hostname> (to connect to remote debug server) where <option> is one of: <none> to print same info as Solaris pmap -heap to print java heap summary -histo[:live] to print histogram of java object heap; if the "live" suboption is specified, only count live objects -permstat to print permanent generation statistics -finalizerinfo to print information on objects awaiting finalization -dump:<dump-options> to dump java heap in hprof binary format dump-options: live dump only live objects; if not specified, all objects in the heap are dumped. format=b binary format file=<file> dump heap to <file> Example: jmap -dump:live,format=b,file=heap.bin <pid> -F force. Use with -dump:<dump-options> <pid> or -histo to force a heap dump or histogram when <pid> does not respond. The "live" suboption is not supported in this mode. -h | -help to print this help message -J<flag> to pass <flag> directly to the runtime system

指定程序號(pid)的程序 jmap [ option ] 指定核心檔案 jmap [ option ] 指定遠端除錯伺服器 jmap [ option ] [[email protected]]


引數:

option 選項引數是互斥的(不可同時使用)。想要使用選項引數,直接跟在命令名稱後即可。 pid 需要列印配置資訊的程序ID。該程序必須是一個Java程序。想要獲取執行的Java程序列表,你可以使用jps。 executable 產生核心dump的Java可執行檔案。 core 需要列印配置資訊的核心檔案。 remote-hostname-or-IP 遠端除錯伺服器的(請檢視jsadebugd)主機名或IP地址。 server-id 可選的唯一id,如果相同的遠端主機上運行了多臺除錯伺服器,用此選項引數標識伺服器。

選項:

<no option> 如果使用不帶選項引數的jmap列印共享物件對映,將會列印目標虛擬機器中載入的每個共享物件的起始地址、對映大小以及共享物件檔案的路徑全稱。這與Solaris的pmap工具比較相似。 -dump:[live,]format=b,file=<filename> 以hprof二進位制格式轉儲Java堆到指定filename的檔案中。live子選項是可選的。如果指定了live子選項,堆中只有活動的物件會被轉儲。想要瀏覽heap dump,你可以使用jhat(Java堆分析工具)讀取生成的檔案。 -finalizerinfo 列印等待終結的物件資訊。 -heap 列印一個堆的摘要資訊,包括使用的GC演算法、堆配置資訊和generation wise heap usage。 -histo[:live] 列印堆的柱狀圖。其中包括每個Java類、物件數量、記憶體大小(單位:位元組)、完全限定的類名。列印的虛擬機器內部的類名稱將會帶有一個’*’字首。如果指定了live子選項,則只計算活動的物件。 -permstat 列印Java堆記憶體的永久儲存區域的類載入器的智慧統計資訊。對於每個類載入器而言,它的名稱、活躍度、地址、父類載入器、它所載入的類的數量和大小都會被列印。此外,包含的字串數量和大小也會被列印。 -F 強制模式。如果指定的pid沒有響應,請使用jmap -dump或jmap -histo選項。此模式下,不支援live子選項。 -h 列印幫助資訊。 -help 列印幫助資訊。 -J<flag> 指定傳遞給執行jmap的JVM的引數。

舉例

檢視java 堆(heap)使用情況,執行命令: [email protected]:~/workspace/design_apaas/apaasweb/control/bin$ jmap -heap 31846

Attaching to process ID 31846, please wait... Debugger attached successfully. Server compiler detected. JVM version is 24.71-b01 using thread-local object allocation. Parallel GC with 4 thread(s)//GC 方式 Heap Configuration: //堆記憶體初始化配置 MinHeapFreeRatio = 0 //對應jvm啟動引數-XX:MinHeapFreeRatio設定JVM堆最小空閒比率(default 40) MaxHeapFreeRatio = 100 //對應jvm啟動引數 -XX:MaxHeapFreeRatio設定JVM堆最大空閒比率(default 70) MaxHeapSize = 2082471936 (1986.0MB) //對應jvm啟動引數-XX:MaxHeapSize=設定JVM堆的最大大小 NewSize = 1310720 (1.25MB)//對應jvm啟動引數-XX:NewSize=設定JVM堆的‘新生代’的預設大小 MaxNewSize = 17592186044415 MB//對應jvm啟動引數-XX:MaxNewSize=設定JVM堆的‘新生代’的最大大小 OldSize = 5439488 (5.1875MB)//對應jvm啟動引數-XX:OldSize=<value>:設定JVM堆的‘老生代’的大小 NewRatio = 2 //對應jvm啟動引數-XX:NewRatio=:‘新生代’和‘老生代’的大小比率 SurvivorRatio = 8 //對應jvm啟動引數-XX:SurvivorRatio=設定年輕代中Eden區與Survivor區的大小比值  PermSize = 21757952 (20.75MB) //對應jvm啟動引數-XX:PermSize=<value>:設定JVM堆的‘永生代’的初始大小 MaxPermSize = 85983232 (82.0MB)//對應jvm啟動引數-XX:MaxPermSize=<value>:設定JVM堆的‘永生代’的最大大小 G1HeapRegionSize = 0 (0.0MB) Heap Usage://堆記憶體使用情況 PS Young Generation Eden Space://Eden區記憶體分佈 capacity = 33030144 (31.5MB)//Eden區總容量 used = 1524040 (1.4534378051757812MB) //Eden區已使用 free = 31506104 (30.04656219482422MB) //Eden區剩餘容量 4.614088270399305% used //Eden區使用比率 From Space: //其中一個Survivor區的記憶體分佈 capacity = 5242880 (5.0MB) used = 0 (0.0MB) free = 5242880 (5.0MB) 0.0% used To Space: //另一個Survivor區的記憶體分佈 capacity = 5242880 (5.0MB) used = 0 (0.0MB) free = 5242880 (5.0MB) 0.0% used PS Old Generation //當前的Old區記憶體分佈 capacity = 86507520 (82.5MB) used = 0 (0.0MB) free = 86507520 (82.5MB) 0.0% used PS Perm Generation//當前的 “永生代” 記憶體分佈 capacity = 22020096 (21.0MB) used = 2496528 (2.3808746337890625MB) free = 19523568 (18.619125366210938MB) 11.337498256138392% used 670 interned Strings occupying 43720 bytes.

檢視堆記憶體(histogram)中的物件數量及大小。執行命令: [email protected]:~/workspace/design_apaas/apaasweb/control/bin$ jmap -histo 3331

num     #instances         #bytes  class name 編號 個數 位元組 類名 ---------------------------------------------- 1: 7 1322080 [I 2: 5603 722368 <methodKlass> 3: 5603 641944 <constMethodKlass> 4: 34022 544352 java.lang.Integer 5: 371 437208 <constantPoolKlass> 6: 336 270624 <constantPoolCacheKlass> 7: 371 253816 <instanceKlassKlass>

jmap -histo:live 這個命令執行,JVM會先觸發gc,然後再統計資訊。

將記憶體使用的詳細情況輸出到檔案,執行命令: [email protected]:~/workspace/design_apaas/apaasweb/control/bin$  jmap -dump:format=b,file=heapDump 6900

然後用jhat命令可以參看 jhat -port 5000 heapDump 在瀏覽器中訪問:http://localhost:5000/ 檢視詳細資訊

這個命令執行,JVM會將整個heap的資訊dump寫入到一個檔案,heap如果比較大的話,就會導致這個過程比較耗時,並且執行的過程中為了保證dump的資訊是可靠的,所以會暫停應用。

總結

1.如果程式記憶體不足或者頻繁GC,很有可能存在記憶體洩露情況,這時候就要藉助Java堆Dump檢視物件的情況。 2.要製作堆Dump可以直接使用jvm自帶的jmap命令 3.可以先使用jmap -heap命令檢視堆的使用情況,看一下各個堆空間的佔用情況。 4.使用jmap -histo:[live]檢視堆記憶體中的物件的情況。如果有大量物件在持續被引用,並沒有被釋放掉,那就產生了記憶體洩露,就要結合程式碼,把不用的物件釋放掉。 5.也可以使用 jmap -dump:format=b,file=<fileName>命令將堆資訊儲存到一個檔案中,再借助jhat命令檢視詳細內容 6.在記憶體出現洩露、溢位或者其它前提條件下,建議多dump幾次記憶體,把記憶體檔案進行編號歸檔,便於後續記憶體整理分析。

Error attaching to process: sun.jvm.hotspot.debugger.DebuggerException: Can’t attach to the process

在ubuntu中第一次使用jmap會報錯:Error attaching to process: sun.jvm.hotspot.debugger.DebuggerException: Can't attach to the process,這是oracla文件中提到的一個bug:http://bugs.java.com/bugdatabase/view_bug.do?bug_id=7050524,解決方式如下:

  1. echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope 該方法在下次重啟前有效。

  2. 永久有效方法 sudo vi /etc/sysctl.d/10-ptrace.conf 編輯下面這行: kernel.yama.ptrace_scope = 1 修改為: kernel.yama.ptrace_scope = 0 重啟系統,使修改生效。

 

 

轉:https://www.hollischuang.com/archives/303