JVM之jmap的使用以及内存溢出分析

举报
共饮一杯无 发表于 2023/02/11 19:19:28 2023/02/11
【摘要】 基本概念jmap(Java Virtual Machine Memory Map)是JDK提供的一个可以生成Java虚拟机的堆转储快照dump文件的命令行工具。除此以外,jmap命令还可以查看finalize执行队列、Java堆和方法区的详细信息,比如空间使用率、当前使用的什么垃圾回收器、分代情况等等。之前写过通过jstat可以对jvm堆的内存进行统计分析,而jmap可以获取到更加详细的内...

基本概念

jmap(Java Virtual Machine Memory Map)是JDK提供的一个可以生成Java虚拟机的堆转储快照dump文件的命令行工具。除此以外,jmap命令还可以查看finalize执行队列、Java堆和方法区的详细信息,比如空间使用率、当前使用的什么垃圾回收器、分代情况等等。
之前写过通过jstat可以对jvm堆的内存进行统计分析,而jmap可以获取到更加详细的内容,如:内存使用情况的汇总、对内存溢出的定位与分析。
还有几种方式获取dump文件:

  • 使用JVM参数选项-XX:+HeapDumpOnOutOfMemoryError参数,可以让虚拟机在OOM异常出现之后自动生成dump文件,通过-XX:HeapDumpPath=path 设置dump文件路径(有时候dump文件比较大的时候可能无法自动导出,这时候就需要使用jmap -dump手动导出了);
  • 通过-XX:+HeapDumpOnCtrlBreak参数则可以使用[Ctrl]+[Break]键让虚拟机生成dump文件;
  • 或者在Linux系统下通过Kill -3命令发送进程退出信号,也能拿到dump文件。

jhat是java虚拟机自带的一种虚拟机堆转储快照分析工具。jhat命令与jmap命令搭配使用,用于分析jmap生成的heap dump文件(堆转储快照)。jhat内置了一个微型的HTTP/HTML服务器,对生成的dump文件分析后,可以在浏览器中查看分析结果。
使用jhat命令,会启动一个http服务,默认端口7000。
注:jhat命令在JDK9、JDK10中已经被删除,官方建议用VisualVM代替。

查看内存使用情况

C:\Users\zjq>jmap -heap 21180
Attaching to process ID 21180, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.171-b11

using thread-local object allocation.
Parallel GC with 8 thread(s)

Heap Configuration: #堆内存配置
   MinHeapFreeRatio         = 0
   MaxHeapFreeRatio         = 100
   MaxHeapSize              = 4263510016 (4066.0MB)
   NewSize                  = 89128960 (85.0MB)
   MaxNewSize               = 1420820480 (1355.0MB)
   OldSize                  = 179306496 (171.0MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 21807104 (20.796875MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 0 (0.0MB)

Heap Usage: #堆内存使用情况
PS Young Generation #年轻代
Eden Space:
   capacity = 266338304 (254.0MB)
   used     = 182061632 (173.62750244140625MB)
   free     = 84276672 (80.37249755859375MB)
   68.35728442575049% used
From Space:
   capacity = 28835840 (27.5MB)
   used     = 0 (0.0MB)
   free     = 28835840 (27.5MB)
   0.0% used
To Space:
   capacity = 30932992 (29.5MB)
   used     = 0 (0.0MB)
   free     = 30932992 (29.5MB)
   0.0% used
PS Old Generation #老年代
   capacity = 118489088 (113.0MB)
   used     = 27846344 (26.55634307861328MB)
   free     = 90642744 (86.44365692138672MB)
   23.501188565144496% used

14751 interned Strings occupying 1962648 bytes.

查看内存中对象数量及大小

查看所有对象,包括活跃以及非活跃的

jmap ‐histo  | more

查看活跃对象

jmap ‐histo:live  | more
C:\Users\dell>jmap -histo:live 21180 | more

 num     #instances         #bytes  class name
----------------------------------------------
   1:         44820        9393464  [C
   2:          2280        3998688  [B
   3:          4834        1915136  [I
   4:         42374        1016976  java.lang.String
   5:         21879         700128  java.util.HashMap$Node
   6:          7375         448040  [Ljava.lang.Object;
   7:          3718         420672  java.lang.Class
   8:          1227         362648  [Ljava.util.HashMap$Node;
   9:          7387         236384  java.util.concurrent.ConcurrentHashMap$Node
  10:          2382         152448  java.net.URL
  11:          1269         112128  [Ljava.lang.String;
  12:          4176         100224  java.util.ArrayList
  13:          2072          99456  java.util.HashMap
  14:          2033          97584  org.apache.tomcat.util.digester.CallMethodRule
  15:            78          96192  [Ljava.util.concurrent.ConcurrentHashMap$Node;
  16:          5694          91104  java.lang.Object
  17:          2216          88640  java.util.LinkedHashMap$Entry
  18:          2425          77600  com.sun.org.apache.xerces.internal.xni.QName
  19:          2806          63400  [Ljava.lang.Class;
  20:          1282          61536  org.apache.catalina.loader.ResourceEntry
  21:           100          54784  [Ljava.util.WeakHashMap$Entry;
  22:          1658          53056  java.util.Hashtable$Entry
  23:           654          52320  java.lang.reflect.Constructor
  24:           555          48840  java.lang.reflect.Method
  25:          1131          45240  java.lang.ref.SoftReference
  26:          1352          43264  java.lang.ref.WeakReference
  27:           878          42144  org.apache.tomcat.util.modeler.AttributeInfo
  28:          1021          40840  java.util.TreeMap$Entry
  29:          1601          38424  java.util.LinkedList$Node
  30:           133          33672  [[C
  31:           421          30312  java.util.logging.Logger
-- More --

#对象说明
B byte
C char
D double
F	float
I int
J long
Z	boolean
[	数组,如[I表示int[] [L+类名 其他对象

将内存使用情况dump到文件中

有些时候我们需要将jvm当前内存中的情况dump到文件中,然后对它进行分析,jmap也是支持dump到文件中的

#用法:
jmap -dump:format=b,file=dumpFileName <pid>

#示例
C:\Users\zjq>jmap -dump:format=b,file=E:\dump.dat 21180
Dumping heap to E:\dump.dat ...
Heap dump file created

说明:

  • live参数是可选的,如果指定,则只转储堆中的活动对象;如果没有指定,则转储堆中的所有对象。
  • format=b表示以hprof二进制格式转储Java堆的内存。
  • file=<filename>用于指定快照dump文件的文件名。

可以看到已经在E盘下生成了dump.dat的文件。

通过jhat对dump文件进行分析

我们将jvm的内存dump到文件中,这个文件是一个二进制的文件,不方便查看,这时我们可以借助于jhat工具进行查看。

#用法:
jhat ‐port <port> <file>

#示例:
C:\Users\dell>jhat -port 8080 E:\dump.dat
Reading from E:\dump.dat...
Dump file created Sun Jul 25 20:46:58 CST 2021
Snapshot read, resolving...
Resolving 584829 objects...
Chasing references, expect 116 dots....................................................................................................................
Eliminating duplicate references....................................................................................................................
Snapshot resolved.
Started HTTP server on port 8080
Server is ready.

打开浏览器进行访问:http://localhost:8080/
image.png

在最后面有OQL查询功能。
image.png

image.png

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。