文前说明
作为码农中的一员,需要不断的学习,我工作之余将一些分析总结和学习笔记写成博客与大家一起交流,也希望采用这种方式记录自己的学习之旅。欢迎加入学习交流群:723288906 免费获取Dubbo、Redis、设计模式、 Netty、zookeeper、Spring cloud、分布式、高并发等架构技术视频资 料,完整架构思维导图,和BATJ面试题及答案。
1. 内存映射工具(Memory Map for Java)
- jmap 命令用于生成堆转储快照(heapdump 或者 dump 问文件)。
- 通过设置 -XX:+HeapDumpOnOutOfMemoryError 参数,可以让虚拟机在 OOM 异常出现之后自动生成 dump 文件。
- 通过 -XX:HeapDumpOutCtrlBreak 参数则可以使用 [Ctrl]+[Break] 键让虚拟机生成 dump 文件,又或者在 Linux 系统下通过 kill -3 命令发送进程退出信号拿到 dump 文件。
- jmap 命令的作用不仅仅是为了获取 dump 文件,还可以查询
finalize()
执行队列,Java 堆和永久代的详细信息,如空间使用率、当前使用收集器类型等。- 除 -dump 和 -histo 选项 在所有操作系统提供之外,其余选项都只能在 Linux / Solaris 下使用。
- 如果给定进程是在 64 位虚拟机上运行,那么需要指定参数 -J-d64。
- 该工具仅限于报告其 具有访问权限 的虚拟机进程。
- 可以通过 -J 方式,将虚拟机参数传递给 jmap 调用的启动程序。例如 -J-Xms48m。
1.1 命令格式
- jmap [ option ] pid
- jmap [ option ] executable core
-
jmap [ option ] [server-id@]remote-hostname-or-IP
- options 是选项相互排斥。选项(如果使用)应紧跟在命令名之后。
- pid 是需要打印配置信息的进程的 ID。这个进程必须是一个 Java 进程。为了获得在机器上运行的 Java 进程的列表可以使用 jps 命令。
- executable 是产生核心堆的 Java 可执行文件。
- core 是需要打印配置信息的核心文件。
- remote-hostname-or-IP 是远程调试服务器的主机名或 IP 地址。
- 不指定的情况下运行 jmap,将在本地主机上查找虚拟机进程。
- server-id 如果在同一远程主机上运行多个调试服务器,则为可选的唯一 ID。
选项 | 说明 |
---|---|
无选项 | 不使用任何选项,jmap 将打印共享对象映射。对于加载到目标虚拟机中的每个共享对象,将打印开始地址、映射大小和共享对象文件的完整路径。这类似于 Solaris PMAP 实用程序。 |
-dump:[live,]format=b,file=<filename> | 将 hprof 二进制格式的 Java 堆转储为 dump 文件。活动子选项是可选的,如果指定,则只转储堆中的活动对象。若要浏览堆转储文件,可以使用 jhat 查看。 |
-finalizerinfo | 打印等待完成的对象的信息。 |
-heap | 打印堆摘要。打印所使用堆的 GC 算法、堆配置、生成方式和使用情况。 |
-histo[:live] | 对于每个 Java 类,打印对象的数目、字节大小的内存大小和完全限定的类名。虚拟机内部类名打印有 " * "。如果指定了活动子选项,则只计算活动对象。 |
-F | 强制。使用 jmap -dump 或者 jmap -histo 选项,如果无响应,那么可以设置,该选项不支持活动子选项。 |
-h | 打印帮助信息。 |
-help | 打印帮助信息。 |
1.2 无选项
- 打印共享对象映射。
执行样例
[root@localhost ~]# sudo -u ovirt jmap 20595
Attaching to process ID 20595, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.191-b12
0x0000000000400000 7K /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.191.b12-1.el7_6.x86_64/jre/bin/java
0x00007f477aeec000 538K /usr/lib64/libfreeblpriv3.so
0x00007f477b175000 245K /usr/lib64/libnspr4.so
0x00007f477b3b3000 19K /usr/lib64/libplc4.so
0x00007f477b5b8000 15K /usr/lib64/libplds4.so
0x00007f477b7bc000 190K /usr/lib64/libnssutil3.so
0x00007f477b9eb000 1220K /usr/lib64/libnss3.so
0x00007f477bd18000 160K /usr/lib64/libsmime3.so
0x00007f477bf3f000 333K /usr/lib64/libssl3.so
......
输出格式
- [开始地址] [映射大小] [共享对象文件的完整路径]
1.3 -dump
- 将二进制格式的 Java 堆转储为 dump 文件。
- 可以设置 live 只转储堆中的活动对象。
执行样例
[root@localhost home]# sudo -u ovirt jmap -dump:format=b,file=/home/ovirt/dump.bin 28823
Dumping heap to /home/ovirt/dump.bin ...
Heap dump file created
[root@localhost home]# ll ovirt/
total 665480
-rw-------. 1 ovirt ovirt 681447732 Feb 28 01:25 dump.bin
1.4 -finalizerinfo
- 显示在 F-Queue 队列等待 Finalizer 线程执行
finalizer
方法的对象。
执行样例
[root@localhost ~]# sudo -u ovirt jmap -finalizerinfo 23175
Attaching to process ID 23175, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.161-b00
Number of objects pending for finalization: 0
1.5 -heap
- 打印所使用堆的 GC 算法、堆配置、生成方式和使用情况。
执行样例
[root@localhost ~]# sudo -u ovirt jmap -heap 20595
Attaching to process ID 20595, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.191-b12
using thread-local object allocation.
Mark Sweep Compact GC
Heap Configuration:
MinHeapFreeRatio = 40
MaxHeapFreeRatio = 70
MaxHeapSize = 255852544 (244.0MB)
NewSize = 5570560 (5.3125MB)
MaxNewSize = 85262336 (81.3125MB)
OldSize = 11206656 (10.6875MB)
NewRatio = 2
SurvivorRatio = 8
MetaspaceSize = 21807104 (20.796875MB)
CompressedClassSpaceSize = 1073741824 (1024.0MB)
MaxMetaspaceSize = 17592186044415 MB
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:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at sun.tools.jmap.JMap.runTool(JMap.java:201)
at sun.tools.jmap.JMap.main(JMap.java:130)
Caused by: java.lang.RuntimeException: unknown CollectedHeap type : class sun.jvm.hotspot.gc_interface.CollectedHeap
at sun.jvm.hotspot.tools.HeapSummary.run(HeapSummary.java:157)
at sun.jvm.hotspot.tools.Tool.startInternal(Tool.java:260)
at sun.jvm.hotspot.tools.Tool.start(Tool.java:223)
at sun.jvm.hotspot.tools.Tool.execute(Tool.java:118)
at sun.jvm.hotspot.tools.HeapSummary.main(HeapSummary.java:50)
... 6 more
- 出现错误,需要安装 openjdk-debuginfo,需要与 openjdk 版本一致。可以直接从 http://debuginfo.centos.org/7/x86_64/ 中下载。
[root@localhost ~]# sudo -u ovirt jmap -heap 20595
Attaching to process ID 20595, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.191-b12
using thread-local object allocation.
Mark Sweep Compact GC
Heap Configuration:
MinHeapFreeRatio = 40
MaxHeapFreeRatio = 70
MaxHeapSize = 482344960 (460.0MB)
NewSize = 10485760 (10.0MB)
MaxNewSize = 160759808 (153.3125MB)
OldSize = 20971520 (20.0MB)
NewRatio = 2
SurvivorRatio = 8
MetaspaceSize = 21807104 (20.796875MB)
CompressedClassSpaceSize = 1073741824 (1024.0MB)
MaxMetaspaceSize = 17592186044415 MB
G1HeapRegionSize = 0 (0.0MB)
Heap Usage:
New Generation (Eden + 1 Survivor Space):
capacity = 48758784 (46.5MB)
used = 42933176 (40.94426727294922MB)
free = 5825608 (5.555732727050781MB)
88.05218768376176% used
Eden Space:
capacity = 43384832 (41.375MB)
used = 42933176 (40.94426727294922MB)
free = 451656 (0.43073272705078125MB)
98.95895413401624% used
From Space:
capacity = 5373952 (5.125MB)
used = 0 (0.0MB)
free = 5373952 (5.125MB)
0.0% used
To Space:
capacity = 5373952 (5.125MB)
used = 0 (0.0MB)
free = 5373952 (5.125MB)
0.0% used
tenured generation:
capacity = 108146688 (103.13671875MB)
used = 64887344 (61.88139343261719MB)
free = 43259344 (41.25532531738281MB)
59.99938158069159% used
21962 interned Strings occupying 2552376 bytes.
输出格式
显示 | 说明 |
---|---|
MinHeapFreeRatio | 可以通过 -XX:MinHeapFreeRatio 设置的虚拟机堆最小空闲比率。 |
MaxHeapFreeRatio | 可以通过 -XX:MaxHeapFreeRatio 设置虚拟机堆最大空闲比率。 |
MaxHeapSize | 可以通过 -XX:MaxHeapSize 设置虚拟机堆的最大大小。 |
NewSize | 可以通过 -XX:NewSize 设置虚拟机新生代的默认大小。 |
MaxNewSize | 可以通过 -XX:MaxNewSize 设置虚拟机新生代的最大大小。 |
OldSize | 可以通过 -XX:OldSize 设置虚拟机堆的老年代的大小。 |
NewRatio | 可以通过 -XX:NewRatio 设置新生代和老年代的大小比率。 |
SurvivorRatio | 可以通过 -XX:SurvivorRatio 设置新生代中 Eden 区与 Survivor 区的大小比值。 |
MetaspaceSize | 可以通过 -XX:MetaspaceSize 设置虚拟机元空间的初始大小。 |
MaxMetaspaceSize | 可以通过 -XX:MaxPermSize 设置虚拟机元空间的最大大小。 |
CompressedClassSpaceSize | 类指针压缩空间大小,可以通过 -XX:CompressedClassSpaceSize 设定。 |
G1HeapRegionSize | 一个 Region 的大小,可以通过参数 -XX:G1HeapRegionSize 设定。 |
New Generation | 新生代内存空间信息。 |
Eden Space | Eden 区内存空间信息。 |
From Space | From Survivor 区内存空间信息。 |
To Space | To Survivor 区内存空间信息。 |
tenured generation | 老年代内存空间信息。 |
1.6 -histo
- 打印 Java 类的对象的数目、字节大小的内存大小和完全限定的类名。
- 可以设置 live 只统计活动对象。
执行样例
[root@localhost ~]# sudo -u ovirt jmap -histo 20595
num #instances #bytes class name
----------------------------------------------
1: 1549699 49590368 java.util.HashMap$Node
2: 74984 45077048 [I
3: 527030 44391304 [C
4: 155685 29635872 [B
5: 552365 26513520 java.util.HashMap
6: 161447 21706560 [Ljava.util.HashMap$Node;
7: 158388 13938144 java.lang.reflect.Method
......
输出格式
- [Java 类的对象的数目] [字节大小] [内存大小] [完全限定的类名]。