【Java 虚拟机笔记】jmap 内存映射工具相关整理

文前说明

作为码农中的一员,需要不断的学习,我工作之余将一些分析总结和学习笔记写成博客与大家一起交流,也希望采用这种方式记录自己的学习之旅。欢迎加入学习交流群: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
[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 类的对象的数目] [字节大小] [内存大小] [完全限定的类名]



 

上一篇:将java进程转移到“解剖台”之前,法医都干了什么?


下一篇:html5 file 上传文件