JDK的命令行工具系列 (二) javap、jinfo、jmap
javap: 反編譯工具, 可用來查看java編譯器生成的字節碼
參數摘要:
- -help 幫助
- -l 輸出行和變量的表
- -public 只輸出public方法和域
- -protected 只輸出public和protected類和成員
- -package 只輸出包,public和protected類和成員,這是默認的
- -p -private 輸出所有類和成員
- -s 輸出內部類型簽名
- -c 輸出分解後的代碼,例如,類中每一個方法內,包含java字節碼的指令
- -verbose 輸出棧大小,方法參數的個數
- -constants 輸出靜態final常量
代碼清單:
importjava.awt.*; import java.applet.*; public class DocFooter extends Applet { String date; String email; public void init() { resize(500,100); date = getParameter("LAST_UPDATED"); email = getParameter("EMAIL"); }public void paint(Graphics g) { g.drawString(date + " by ",100, 15); g.drawString(email,290,15); } }
命令行下輸入javap DocFooter, 結果如下:
D:\cn\javaCommand>javap DocFooter Compiled from "DocFooter.java" public class DocFooter extends java.applet.Applet { java.lang.String date; java.lang.Stringemail; public DocFooter(); public void init(); public void paint(java.awt.Graphics); }
jinfo: Java配置信息工具
慣例, 先啟動一個java應用程序, 通過jps命令查看java進程的pid為14568, 命令行下輸入jinfo -J-d64 -sysprops 14568。這裏的 -J-d64 參數對應64位虛擬機。
C:\Users\liqingshan>jinfo -J-d64 -sysprops 14568 Attaching to process ID 14568, please wait... Debugger attached successfully. Server compiler detected. JVM version is 25.161-b12 java.runtime.name = Java(TM) SE Runtime Environment java.vm.version = 25.161-b12 sun.boot.library.path = E:\javaTools\jre\bin java.vendor.url = http://java.oracle.com/ java.vm.vendor = Oracle Corporation path.separator = ; file.encoding.pkg = sun.io java.vm.name = Java HotSpot(TM) 64-Bit Server VM sun.os.patch.level = sun.java.launcher = SUN_STANDARD user.script = user.country = CN user.dir = D:\cn\javaCommand java.vm.specification.name = Java Virtual Machine Specification java.runtime.version = 1.8.0_161-b12 java.awt.graphicsenv = sun.awt.Win32GraphicsEnvironment os.arch = amd64 java.endorsed.dirs = E:\javaTools\jre\lib\endorsed line.separator = java.io.tmpdir = C:\Users\LIQING~1\AppData\Local\Tempjava.vm.specification.vendor = Oracle Corporation user.variant = os.name = Windows 10 sun.jnu.encoding = GBK java.library.path = C:\ProgramData\Oracle\Java\javapath;C:\WINDOWS\Sun\Java\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\ProgramData\Oracle\Java\javapath;C:\oracle\product\10.2.0\db_1\bin;E:\javaTools\jdk1.8.0_161\bin;C:\Program Files (x86)\Intel\iCLS Client\;C:\Program Files\Intel\iCLS Client\;C:\windows\system32;C:\windows;C:\windows\System32\Wbem;C:\windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;c:\Program Files\Intel\WiFi\bin\;C:\Java\MySQL\MySQL Server 5.5\bin;c:\Program Files\Common Files\Intel\WirelessCommon\;C:\Java\VisualSVN Server\bin;C:\Java\apache-maven-3.3.9\bin;E:\javaTools\apache-cxf-3.1.9\bin;E:\javaTools\Git\cmd;E:\javaTools\TortoiseGit\bin;E:\javaTools\mongodb\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\Program Files\Intel\WiFi\bin\;C:\Program Files\Common Files\Intel\WirelessCommon\;C:\WINDOWS\System32\OpenSSH\;C:\Program Files\TortoiseSVN\bin;E:\javaTools\nodejs\;E:\Program Files\Bandizip\;C:\Users\liqingshan\AppData\Local\Microsoft\WindowsApps;C:\Users\liqingshan\AppData\Roaming\npm;. java.specification.name = Java Platform API Specification java.class.version = 52.0 sun.management.compiler = HotSpot 64-Bit Tiered Compilers os.version = 10.0 user.home = C:\Users\liqingshan user.timezone = java.awt.printerjob = sun.awt.windows.WPrinterJob file.encoding = GBK java.specification.version = 1.8 user.name = qingshan java.class.path = . java.vm.specification.version = 1.8 sun.arch.data.model = 64 sun.java.command = JpsDemo java.home = E:\javaTools\jre user.language = zh java.specification.vendor = Oracle Corporation awt.toolkit = sun.awt.windows.WToolkit java.vm.info = mixed mode java.version = 1.8.0_161 java.ext.dirs = E:\javaTools\jre\lib\ext;C:\WINDOWS\Sun\Java\lib\ext sun.boot.class.path = E:\javaTools\jre\lib\resources.jar;E:\javaTools\jre\lib\rt.jar;E:\javaTools\jre\lib\sunrsasign.jar;E:\javaTools\jre\lib\jsse.jar;E:\javaTools\jre\lib\jce.jar;E:\javaTools\jre\lib\charsets.jar;E:\javaTools\jre\lib\jfr.jar;E:\javaTools\jre\classes java.vendor = Oracle Corporation sun.stderr.encoding = ms936 file.separator = java.vendor.url.bug = http://bugreport.sun.com/bugreport/ sun.io.unicode.encoding = UnicodeLittle sun.cpu.endian = little sun.stdout.encoding = ms936 sun.desktop = windows sun.cpu.isalist = amd64
另外網上找到的相關博客以及官方文檔都指明 JDK 1.8 之後已經不再支持jinfo命令, 但是在我本地 1.8 環境下卻支持, 這個先在這裏做個記錄, 待以後找到原因再完善本篇文章。
jmap: 生成heapdump文件
在JDK的命令行工具系列 (一) jps、jstat中, 我們已經介紹過heapdump文件, 所以這裏就直接對jmap的命令和參數做個演示。其中關於具體參數的摘要說明轉載自H大的博客: Java命令學習系列(三)——Jmap-HollisChuang‘s Blog。
命令格式
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)
參數摘要
- option 選項參數是互斥的(不可同時使用)。想要使用選項參數,直接跟在命令名稱後即可。
- pid 需要打印配置信息的進程ID。該進程必須是一個Java進程。想要獲取運行的Java進程列表,你可以使用jps。
- executable 產生核心dump的Java可執行文件。
- core 需要打印配置信息的核心文件。
- remote server IP or hostname 遠程調試服務器的(請查看jsadebugd)主機名或IP地址。
- server-id 可選的唯一id,如果相同的遠程主機上運行了多臺調試服務器,用此選項參數標識服務器。
option
- <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堆的摘要信息: jmap -heap 11392
C:\Users\liqingshan>jps -m 11392 JpsDemo 12816 14352 Bootstrap start 6392 Jps -m 10060 Launcher C:/Java/IDEA/lib/guava-21.0.jar;C:/Java/IDEA/lib/jps-builders-6.jar;C:/Java/IDEA/lib/log4j.jar;C:/Java/IDEA/lib/httpcore-4.4.5.jar;C:/Java/IDEA/lib/netty-all-4.1.13.Final.jar;C:/Java/IDEA/lib/commons-codec-1.9.jar;C:/Java/IDEA/lib/annotations.jar;C:/Java/IDEA/lib/snappy-in-java-0.5.1.jar;C:/Java/IDEA/lib/trove4j.jar;C:/Java/IDEA/lib/jdom.jar;C:/Java/IDEA/lib/httpclient-4.5.2.jar;C:/Java/IDEA/lib/util.jar;C:/Java/IDEA/lib/openapi.jar;C:/Java/IDEA/lib/jps-model.jar;C:/Java/IDEA/lib/aether-dependency-resolver.jar;C:/Java/IDEA/lib/oromatcher.jar;C:/Java/IDEA/lib/forms_rt.jar;C:/Java/IDEA/lib/idea_rt.jar;C:/Java/IDEA/lib/resources_en.jar;C:/Java/IDEA/lib/protobuf-java-2.5.0.jar;C:/Java/IDEA/lib/asm-all.jar;C:/Java/IDEA/lib/jna.jar;C:/Java/IDEA/lib/jgoodies-forms.jar;C:/Java/IDEA/lib/javac2.jar;C:/Java/IDEA/lib/jps-builders.jar;C:/Java/IDEA/lib/slf4j-api-1.7.10.jar;C:/Java/IDEA/lib/aether-1.1.0-all.jar;C:/Java/IDEA/lib/commons-logging-1.2.jar;C:/Java/IDEA/lib/jna-platform.jar;C:/J C:\Users\liqingshan>jmap -heap 11392 Attaching to process ID 11392, please wait... Debugger attached successfully. Server compiler detected. JVM version is 25.161-b12 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 = 2118123520 (2020.0MB) //對應jvm啟動參數-XX:MaxHeapSize=設置JVM堆的最大大小 NewSize = 44564480 (42.5MB) //對應jvm啟動參數-XX:NewSize=設置JVM堆的‘新生代’的默認大小 MaxNewSize = 705691648 (673.0MB) //對應jvm啟動參數-XX:MaxNewSize=設置JVM堆的‘新生代’的最大大小 OldSize = 89653248 (85.5MB) //對應jvm啟動參數-XX:OldSize=<value>:設置JVM堆的‘老生代’的大小 NewRatio = 2 //對應jvm啟動參數-XX:NewRatio=:‘新生代’和‘老生代’的大小比率 SurvivorRatio = 8 //對應jvm啟動參數-XX:SurvivorRatio=設置年輕代中Eden區與Survivor區的大小比值 MetaspaceSize = 21807104 (20.796875MB) //對應jvm啟動參數-XX:MetaspaceSize=<value>:設置JVM堆的‘元空間’的初始大小 CompressedClassSpaceSize = 1073741824 (1024.0MB) //對應jvm啟動參數-XX:CompressedClassSpaceSize=<value>:設置類指針壓縮空間大小 MaxMetaspaceSize = 17592186044415 MB //對應jmv啟動參數-XX:MaxMetaspaceSize=<value>:設置JVM堆的‘元空間‘的最大大小 G1HeapRegionSize = 0 (0.0MB) Heap Usage: //堆內存使用情況 PS Young Generation Eden Space: //Eden區內存分布 capacity = 24641536 (23.5MB) //總容量 used = 492872 (0.47003936767578125MB) //已使用容量 free = 24148664 (23.02996063232422MB) //剩余容量 2.000167522024601% used //使用比例 From Space: //其中一個Survivor區的內存分布 capacity = 524288 (0.5MB) used = 0 (0.0MB) free = 524288 (0.5MB) 0.0% used To Space: //另一個Survivor區的內存分布 capacity = 524288 (0.5MB) used = 0 (0.0MB) free = 524288 (0.5MB) 0.0% used PS Old Generation //當前的老年代內存分布 capacity = 34603008 (33.0MB) used = 674280 (0.6430435180664062MB) free = 33928728 (32.356956481933594MB) 1.9486167214133523% used 1577 interned Strings occupying 146816 bytes.
查看java堆的對象數量、內存大小、類的全限定名: jmap -histo:live 11392。其中 :live 參數會指定JVM先觸發一次GC之後, 再統計堆的柱狀圖。
C:\Users\liqingshan>jmap -histo:live 11392 num #instances #bytes class name ---------------------------------------------- 1: 2336 397136 [C 2: 497 56704 java.lang.Class 3: 2065 49560 java.lang.String 4: 792 31680 java.util.TreeMap$Entry 5: 529 30224 [Ljava.lang.Object; 6: 10 25032 [B 7: 388 9312 java.util.LinkedList$Node 8: 195 8896 [Ljava.lang.String; 9: 228 7296 java.util.HashMap$Node 10: 195 6240 java.util.LinkedList 11: 256 4096 java.lang.Integer 12: 99 3960 java.lang.ref.SoftReference 13: 117 3744 java.util.Hashtable$Entry 14: 93 3616 [I 15: 13 3088 [Ljava.util.HashMap$Node; 16: 7 2632 java.lang.Thread 17: 2 2080 [[C 18: 38 1824 sun.util.locale.LocaleObjectCache$CacheEntry 19: 51 1632 java.util.concurrent.ConcurrentHashMap$Node 20: 20 1600 java.lang.reflect.Constructor .................................................. // 實際測試按num編號有187條記錄, 這裏只貼出了前20條記錄 Total 8528 674328
將Java堆的內存映像輸出到指定名稱的文件中: jmap -dump:format=b,file=qingshanli 11392, 然後輸入jhat命令啟動一個HTTP/HTML服務器: jhat -port 10000 qingshanli
C:\Users\liqingshan>jmap -dump:format=b,file=qingshanli 11392 Dumping heap to C:\Users\liqingshan\qingshanli ... Heap dump file created C:\Users\liqingshan>jhat -port 10000 qingshanli Reading from qingshanli... Dump file created Mon Jul 16 19:50:18 GMT+08:00 2018 Snapshot read, resolving... Resolving 562831 objects... Chasing references, expect 112 dots................................................................................................................ Eliminating duplicate references................................................................................................................ Snapshot resolved. Started HTTP server on port 10000 Server is ready.
在瀏覽器中輸入地址: http://localhost:10000, 就可以在頁面查看堆轉儲快照詳細信息。
參考資料
Java命令學習系列(七)——javap-HollisChuang‘s Blog
Java命令學習系列(六)——jinfo-HollisChuang‘s Blog
Java命令學習系列(三)——Jmap-HollisChuang‘s Blog
《深入理解Java虛擬機》
JDK的命令行工具系列 (二) javap、jinfo、jmap