Java命令学习系列(三)——Jmap
轉(zhuǎn)載自?Java命令學(xué)習(xí)系列(三)——Jmap
jmap是JDK自帶的工具軟件,主要用于打印指定Java進(jìn)程(或核心文件、遠(yuǎn)程調(diào)試服務(wù)器)的共享對象內(nèi)存映射或堆內(nèi)存細(xì)節(jié)。可以使用jmap生成Heap Dump。在Java命令學(xué)習(xí)系列(零)——常見命令及Java Dump介紹和Java命令學(xué)習(xí)系列(二)——Jstack中分別有關(guān)于Java Dump以及線程 Dump的介紹。?這篇文章主要介紹Java的堆Dump以及jamp命令
什么是堆Dump
堆Dump是反應(yīng)Java堆使用情況的內(nèi)存鏡像,其中主要包括系統(tǒng)信息、虛擬機(jī)屬性、完整的線程Dump、所有類和對象的狀態(tài)等。 一般,在內(nèi)存不足、GC異常等情況下,我們就會懷疑有內(nèi)存泄露。這個時候我們就可以制作堆Dump來查看具體情況。分析原因。
基礎(chǔ)知識
常見內(nèi)存錯誤:
outOfMemoryError?年老代內(nèi)存不足。
outOfMemoryError:PermGen Space?永久代內(nèi)存不足。
outOfMemoryError:GC overhead limit exceed?垃圾回收時間占用系統(tǒng)運行時間的98%或以上。
jmap
用法摘要
Usage:jmap [option] <pid>(to connect to running process)jmap [option] <executable <core>(to connect to a core file)jmap [option] [server_id@]<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 formatdump-options:live ? ? ? ? dump only live objects; if not specified,all objects in the heap are dumped.format=b ? ? binary formatfile=<file> ?dump heap to <file>Example: jmap -dump:live,format=b,file=heap.bin <pid>-F ? ? ? ? ? ? ? ? ? force. Use with -dump:<dump-options> <pid> or -histoto force a heap dump or histogram when <pid> does notrespond. The "live" suboption is not supportedin this mode.-h | -help ? ? ? ? ? to print this help message-J<flag> ? ? ? ? ? ? to pass <flag> directly to the runtime system指定進(jìn)程號(pid)的進(jìn)程?jmap [ option ]?指定核心文件?jmap [ option ]?<executable指定遠(yuǎn)程調(diào)試服務(wù)器?jmap [ option ] [server-id@]
參數(shù):
option?選項參數(shù)是互斥的(不可同時使用)。想要使用選項參數(shù),直接跟在命令名稱后即可。?pid?需要打印配置信息的進(jìn)程ID。該進(jìn)程必須是一個Java進(jìn)程。想要獲取運行的Java進(jìn)程列表,你可以使用jps。?executable?產(chǎn)生核心dump的Java可執(zhí)行文件。?core?需要打印配置信息的核心文件。?remote-hostname-or-IP?遠(yuǎn)程調(diào)試服務(wù)器的(請查看jsadebugd)主機(jī)名或IP地址。?server-id?可選的唯一id,如果相同的遠(yuǎn)程主機(jī)上運行了多臺調(diào)試服務(wù)器,用此選項參數(shù)標(biāo)識服務(wù)器。
選項:
<no option>?如果使用不帶選項參數(shù)的jmap打印共享對象映射,將會打印目標(biāo)虛擬機(jī)中加載的每個共享對象的起始地址、映射大小以及共享對象文件的路徑全稱。這與Solaris的pmap工具比較相似。
?-dump:[live,]format=b,file=<filename>?
以hprof二進(jìn)制格式轉(zhuǎn)儲Java堆到指定filename的文件中。live子選項是可選的。如果指定了live子選項,堆中只有活動的對象會被轉(zhuǎn)儲。想要瀏覽heap dump,你可以使用jhat(Java堆分析工具)讀取生成的文件。
?-finalizerinfo?打印等待終結(jié)的對象信息。?-heap打印一個堆的摘要信息,包括使用的GC算法、堆配置信息和generation wise heap usage。?-histo[:live]?打印堆的柱狀圖。其中包括每個Java類、對象數(shù)量、內(nèi)存大小(單位:字節(jié))、完全限定的類名。打印的虛擬機(jī)內(nèi)部的類名稱將會帶有一個'*'前綴。如果指定了live子選項,則只計算活動的對象。?-permstat?打印Java堆內(nèi)存的永久保存區(qū)域的類加載器的智能統(tǒng)計信息。對于每個類加載器而言,它的名稱、活躍度、地址、父類加載器、它所加載的類的數(shù)量和大小都會被打印。此外,包含的字符串?dāng)?shù)量和大小也會被打印。?-F?強制模式。如果指定的pid沒有響應(yīng),請使用jmap -dump或jmap -histo選項。此模式下,不支持live子選項。?-h?打印幫助信息。?-help?打印幫助信息。?-J<flag>?指定傳遞給運行jmap的JVM的參數(shù)。
舉例
查看java 堆(heap)使用情況,執(zhí)行命令:?
?jmap -heap 31846
Attaching to process ID 31846, please wait... Debugger attached successfully. Server compiler detected. JVM version is 24.71-b01using thread-local object allocation. Parallel GC with 4 thread(s)//GC 方式Heap Configuration: //堆內(nèi)存初始化配置MinHeapFreeRatio = 0 //對應(yīng)jvm啟動參數(shù)-XX:MinHeapFreeRatio設(shè)置JVM堆最小空閑比率(default 40)MaxHeapFreeRatio = 100 //對應(yīng)jvm啟動參數(shù) -XX:MaxHeapFreeRatio設(shè)置JVM堆最大空閑比率(default 70)MaxHeapSize ? ? ?= 2082471936 (1986.0MB) //對應(yīng)jvm啟動參數(shù)-XX:MaxHeapSize=設(shè)置JVM堆的最大大小NewSize ? ? ? ? ?= 1310720 (1.25MB)//對應(yīng)jvm啟動參數(shù)-XX:NewSize=設(shè)置JVM堆的‘新生代’的默認(rèn)大小MaxNewSize ? ? ? = 17592186044415 MB//對應(yīng)jvm啟動參數(shù)-XX:MaxNewSize=設(shè)置JVM堆的‘新生代’的最大大小OldSize ? ? ? ? ?= 5439488 (5.1875MB)//對應(yīng)jvm啟動參數(shù)-XX:OldSize=<value>:設(shè)置JVM堆的‘老生代’的大小NewRatio ? ? ? ? = 2 //對應(yīng)jvm啟動參數(shù)-XX:NewRatio=:‘新生代’和‘老生代’的大小比率SurvivorRatio ? ?= 8 //對應(yīng)jvm啟動參數(shù)-XX:SurvivorRatio=設(shè)置年輕代中Eden區(qū)與Survivor區(qū)的大小比值 PermSize ? ? ? ? = 21757952 (20.75MB) ?//對應(yīng)jvm啟動參數(shù)-XX:PermSize=<value>:設(shè)置JVM堆的‘永生代’的初始大小MaxPermSize ? ? ?= 85983232 (82.0MB)//對應(yīng)jvm啟動參數(shù)-XX:MaxPermSize=<value>:設(shè)置JVM堆的‘永生代’的最大大小G1HeapRegionSize = 0 (0.0MB)Heap Usage://堆內(nèi)存使用情況 PS Young Generation Eden Space://Eden區(qū)內(nèi)存分布capacity = 33030144 (31.5MB)//Eden區(qū)總?cè)萘縰sed ? ? = 1524040 (1.4534378051757812MB) ?//Eden區(qū)已使用free ? ? = 31506104 (30.04656219482422MB) ?//Eden區(qū)剩余容量4.614088270399305% used //Eden區(qū)使用比率 From Space: ?//其中一個Survivor區(qū)的內(nèi)存分布capacity = 5242880 (5.0MB)used ? ? = 0 (0.0MB)free ? ? = 5242880 (5.0MB)0.0% used To Space: ?//另一個Survivor區(qū)的內(nèi)存分布capacity = 5242880 (5.0MB)used ? ? = 0 (0.0MB)free ? ? = 5242880 (5.0MB)0.0% used PS Old Generation //當(dāng)前的Old區(qū)內(nèi)存分布capacity = 86507520 (82.5MB)used ? ? = 0 (0.0MB)free ? ? = 86507520 (82.5MB)0.0% used PS Perm Generation//當(dāng)前的 “永生代” 內(nèi)存分布capacity = 22020096 (21.0MB)used ? ? = 2496528 (2.3808746337890625MB)free ? ? = 19523568 (18.619125366210938MB)11.337498256138392% used670 interned Strings occupying 43720 bytes.查看堆內(nèi)存(histogram)中的對象數(shù)量及大小。執(zhí)行命令:??jmap -histo 3331
num ? ? #instances ? ? ? ? #bytes ?class name 編號 ? ? 個數(shù) ? ? ? ? ? ? ? ?字節(jié) ? ? 類名 ----------------------------------------------1: ? ? ? ? ? ? 7 ? ? ? ?1322080 ?[I2: ? ? ? ? ?5603 ? ? ? ? 722368 ?<methodKlass>3: ? ? ? ? ?5603 ? ? ? ? 641944 ?<constMethodKlass>4: ? ? ? ? 34022 ? ? ? ? 544352 ?java.lang.Integer5: ? ? ? ? ? 371 ? ? ? ? 437208 ?<constantPoolKlass>6: ? ? ? ? ? 336 ? ? ? ? 270624 ?<constantPoolCacheKlass>7: ? ? ? ? ? 371 ? ? ? ? 253816 ?<instanceKlassKlass>jmap -histo:live 這個命令執(zhí)行,JVM會先觸發(fā)gc,然后再統(tǒng)計信息。
將內(nèi)存使用的詳細(xì)情況輸出到文件,執(zhí)行命令:
?jmap -dump:format=b,file=heapDump 6900
然后用jhat命令可以參看?jhat -port 5000 heapDump?在瀏覽器中訪問:http://localhost:5000/?查看詳細(xì)信息
這個命令執(zhí)行,JVM會將整個heap的信息dump寫入到一個文件,heap如果比較大的話,就會導(dǎo)致這個過程比較耗時,并且執(zhí)行的過程中為了保證dump的信息是可靠的,所以會暫停應(yīng)用。
總結(jié)
1.如果程序內(nèi)存不足或者頻繁GC,很有可能存在內(nèi)存泄露情況,這時候就要借助Java堆Dump查看對象的情況。 2.要制作堆Dump可以直接使用jvm自帶的jmap命令 3.可以先使用jmap -heap命令查看堆的使用情況,看一下各個堆空間的占用情況。 4.使用jmap -histo:[live]查看堆內(nèi)存中的對象的情況。如果有大量對象在持續(xù)被引用,并沒有被釋放掉,那就產(chǎn)生了內(nèi)存泄露,就要結(jié)合代碼,把不用的對象釋放掉。 5.也可以使用?jmap -dump:format=b,file=<fileName>命令將堆信息保存到一個文件中,再借助jhat命令查看詳細(xì)內(nèi)容 6.在內(nèi)存出現(xiàn)泄露、溢出或者其它前提條件下,建議多dump幾次內(nèi)存,把內(nèi)存文件進(jìn)行編號歸檔,便于后續(xù)內(nèi)存整理分析。
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,解決方式如下:
echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope 該方法在下次重啟前有效。
永久有效方法 sudo vi /etc/sysctl.d/10-ptrace.conf 編輯下面這行: kernel.yama.ptracescope = 1 修改為: kernel.yama.ptracescope = 0 重啟系統(tǒng),使修改生效。
總結(jié)
以上是生活随笔為你收集整理的Java命令学习系列(三)——Jmap的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 尘埃2的配置要求?
- 下一篇: Java命令学习系列(二)——Jstac