JDK神器之jmap(java内存映射工具)

背景介绍

jdk安装后会自带一些小工具,jmap命令(Memory Map for Java)是其中之一。主要用于打印指定Java进程(或核心文件、远程调试服务器)的共享对象内存映射或堆内存细节。

jmap命令可以获得运行中的jvm的堆的快照,从而可以离线分析堆,以检查内存泄漏,检查一些严重影响性能的大对象的创建,检查系统中什么对象最多,各种对象所占内存的大小等等。可以使用jmap生成Heap Dump。

如果不想使用jmap命令,要想获取Java堆转储快照还有一些比较“暴力”的手段:譬如在前面用过的 -XX:+HeapDumpOnOutOfMemoryError参数,可以让虚拟机在OOM异常出现之后自动生成dump文件,通过-XX:+HeapDumpOnCtrlBreak参数可以使用[ctrl]+[Break]键让虚拟机生成dump文件,又或者在Linux系统下通过Kill -3 命令发送进程退出信息“恐吓”一下虚拟机,也能拿到dump文件。

jmap的作用并不仅仅是为了获取dump文件,他还可以查询finalize执行队列,java堆和永久代的详细信息,如空间使用率、当前用的是哪种收集器等。

命令格式

C:\Users\kino>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
    -clstats             to print class loader statistics
    -finalizerinfo       to print information on objects awaiting finalization
    -dump:<dump-options> to dump java heap in hprof binary format
                         dump-options:
                           live         dump only live objects; if not specified,
                                        all objects in the heap are dumped.
                           format=b     binary format
                           file=<file>  dump heap to <file>
                         Example: jmap -dump:live,format=b,file=heap.bin <pid>
    -F                   force. Use with -dump:<dump-options> <pid> or -histo
                         to force a heap dump or histogram when <pid> does not
                         respond. The "live" suboption is not supported
                         in this mode.
    -h | -help           to print this help message
    -J<flag>             to pass <flag> directly to the runtime system

主要选项:

选项作用
-dump生成java堆转储快照,格式为:-dump:[live,]format=b,file=<filename>,其中live子参数说明是否只dump出存活对象
-finalizerinfo显示在F-Queue中等待Finalizer线程执行finalize方法的对象,只在linux/solaris平台下有效
-heap显示堆详细信息,如使用哪种回收期、参数配置、分带状况等,只在linux/solaris平台下有效
-histo显示堆中对象统计信息,包括类、实例数量和合计容量
-permstat以ClassLoader为统计口径显示永久代内存状况,只在linux/solaris平台下有效
-F当虚拟机进程对-dump选项没有响应时,可以使用这个选项强制生成dump快照,只在linux/solaris平台下有效

参数说明

jmap -dump:生成java堆转储快照

生成java对转存快照,格式:jmap -dump:[live,]format=b,file=文件名 <pid>

C:\Users\kino>jmap -dump:live,format=b,file=D:/1.hprof 26280
Dumping heap to D:\1.hprof ...
Heap dump file created

 可以使用jdk提供的jvisualvm.exe查看hprof文件,文件——装入

 

jmap -heap:显示堆详细信息

显示堆详细信息

命令格式:jmap -heap <pid>

C:\Users\kino>jmap -heap 26280
Attaching to process ID 26280, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.202-b08

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

Heap Configuration:
   MinHeapFreeRatio         = 0
   MaxHeapFreeRatio         = 100
   MaxHeapSize              = 4246732800 (4050.0MB)
   NewSize                  = 88604672 (84.5MB)
   MaxNewSize               = 1415577600 (1350.0MB)
   OldSize                  = 177733632 (169.5MB)
   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 = 696254464 (664.0MB)
   used     = 560183024 (534.2321624755859MB)
   free     = 136071440 (129.76783752441406MB)
   80.45665097523884% used
From Space:
   capacity = 38273024 (36.5MB)
   used     = 0 (0.0MB)
   free     = 38273024 (36.5MB)
   0.0% used
To Space:
   capacity = 41943040 (40.0MB)
   used     = 0 (0.0MB)
   free     = 41943040 (40.0MB)
   0.0% used
PS Old Generation
   capacity = 364904448 (348.0MB)
   used     = 111581752 (106.41265106201172MB)
   free     = 253322696 (241.58734893798828MB)
   30.578348006325207% used

39846 interned Strings occupying 4039512 bytes.

jmap -histo:显示堆中对象统计信息

显示堆中对象统计信息,包括类、实例数量和合计容量

命令格式:jmap -histo[:live] <pid>

C:\Users\kino>jmap -histo 26280

 num     #instances         #bytes  class name
----------------------------------------------
   1:       2654443      595971784  [C
   2:         13834       45925552  [I
   3:       1610027       38640648  java.lang.String
   4:        366673       14666920  java.util.LinkedHashMap$Entry
   5:        248400        9936000  org.springframework.boot.devtools.filewatch.FileSnapshot
   6:        294814        9434048  java.io.File
   7:        107135        9427880  java.lang.reflect.Method
   8:         50199        6990904  [Ljava.util.HashMap$Node;
   9:        107073        6884568  [Ljava.lang.String;
  10:        105708        6441048  [Ljava.lang.Object;
  11:        155185        4965920  java.util.concurrent.ConcurrentHashMap$Node
  12:        121191        3878112  java.util.HashMap$Node
  13:         73628        3534144  org.aspectj.weaver.reflect.ShadowMatchImpl
  14:        117849        2828376  java.util.ArrayList
  15:         73628        2356096  org.aspectj.weaver.patterns.ExposedState
  16:         47234        2031792  [Ljava.io.File;
  17:         35823        2006088  java.util.LinkedHashMap
  18:         40210        1930080  java.util.HashMap
.
.
.
.
.
6834:             1             16  sun.rmi.transport.DGCImpl_Stub
6835:             1             16  sun.rmi.transport.proxy.RMIDirectSocketFactory
6836:             1             16  sun.rmi.transport.tcp.TCPTransport$1
6837:             1             16  sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$$Lambda$71/931120364
6838:             1             16  sun.security.provider.NativeSeedGenerator
6839:             1             16  sun.security.util.ByteArrayLexOrder
6840:             1             16  sun.security.util.ByteArrayTagOrder
6841:             1             16  sun.text.normalizer.NormalizerBase$Mode
6842:             1             16  sun.text.normalizer.NormalizerBase$NFCMode
6843:             1             16  sun.text.normalizer.NormalizerBase$NFDMode
6844:             1             16  sun.text.normalizer.NormalizerBase$NFKCMode
6845:             1             16  sun.text.normalizer.NormalizerBase$NFKDMode
6846:             1             16  sun.util.calendar.Gregorian
6847:             1             16  sun.util.locale.provider.AuxLocaleProviderAdapter$NullProvider
6848:             1             16  sun.util.locale.provider.CalendarDataUtility$CalendarWeekParameterGetter
6849:             1             16  sun.util.locale.provider.SPILocaleProviderAdapter
6850:             1             16  sun.util.locale.provider.TimeZoneNameUtility$TimeZoneNameGetter
6851:             1             16  sun.util.resources.LocaleData
6852:             1             16  sun.util.resources.LocaleData$LocaleDataResourceBundleControl
Total       7255510      804288504

项目实践注意事项

权限问题

确保你有足够的权限来执行 jmap 命令,特别是在生产环境中,可能需要以 root 用户或具有相应权限的用户身份运行。

性能影响

生成堆转储文件是一个比较耗时的操作,可能会对 Java 进程的性能产生一定的影响,因此建议在非业务高峰期进行操作。

文件大小

堆转储文件可能会非常大,需要确保磁盘有足够的空间来存储该文件。

实现原理

jmap 工具主要基于 Java 虚拟机工具接口(Java Virtual Machine Tool Interface,简称 JVMTI)和服务性代理(Serviceability Agent,简称 SA)来实现。JVMTI 是一组丰富的编程接口,允许外部工具与 Java 虚拟机(JVM)进行交互,获取虚拟机的运行时信息;SA 则是基于 JVMTI 开发的一组库和工具,为开发者提供了更高级的功能,方便对 JVM 进行调试和分析。

核心技术之一:JVMTI

JVMTI 是 JVM 提供的一个 native 编程接口,它允许外部工具监控和控制 JVM 的行为。通过 JVMTI,jmap 可以获取以下信息:

  • 堆内存信息:包括堆的大小、各个代(新生代、老年代等)的使用情况、对象的分布等。
  • 对象信息:可以获取对象的类型、数量、占用内存大小等信息。
  • 类加载信息:了解类的加载情况、类的数量等。

核心技术之二:服务性代理(SA)

SA 是 JVM 提供的一个高级调试工具,它基于 JVMTI 实现了更复杂的功能。jmap 在获取堆转储快照时,通常会借助 SA 来完成。SA 可以直接访问 JVM 的内部数据结构,将堆中的对象信息以二进制格式保存到文件中,生成堆转储文件(.hprof 文件)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

十五001

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值