一、jmap介绍
jmap是JDK自带的一款用于获取Java应用的heap或类信息快照的命令行工具,它能够让我们更好地了解内存中对象的使用情况,从而方便优化应用程序。
二、jmap常用选项
jmap有多个选项,我们通常会用到以下几个:
-heap
该选项可以让我们获得应用程序的heap大小、占用率等内存信息。例如:
jmap -heap 19321
这条命令会输出进程号19321对应的Java应用的heap信息,例如:
Attaching to process ID 19321, please wait... Debugger attached successfully. Server compiler detected JVM version is 25.102-b14 using thread-local object allocation. Parallel GC with 4 thread(s) Heap Configuration: MinHeapFreeRatio = 40 MaxHeapFreeRatio = 70 MaxHeapSize = 2147483648 (2048.0MB) // 最大可用heap大小 NewSize = 1048576 (1.0MB) // 新生代大小 MaxNewSize = 33554432 (32.0MB) // 新生代最大大小 OldSize = 4194304 (4.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 = 279183360 (266.125MB) // Eden区域容量 used = 36645336 (34.925048828125MB) // 已使用空间 free = 242538024 (231.199951171875MB) // 未使用空间 13.11123171556415% used //空间使用率 ...
-histo[:live]
该选项会输出Java堆内存中的对象信息,包括对象的数量、占用内存大小、类名等。如果加上”:live”参数,则只统计存活对象的信息。例如:
jmap -histo 19321
这条命令会输出进程号19321对应的Java应用中对象的统计信息,例如:
num #instances #bytes class name ---------------------------------------------- 1: 183765 474534880 [C // char数组对象 2: 8749 274628312 [B // byte数组对象 3: 21869 164735880 java.lang.String 4: 9350 57402584 [I // int数组对象 5: 310942 49910872 java.util.LinkedHashMap$Entry ...
-dump:[live,]format=b,file=filename
该选项可以生成一个Java堆的dump文件,我们可以用jhat、MAT等工具来解析这个文件,进行一些内存分析。例如:
jmap -dump:live,format=b,file=heapdump.bin 19321
这条命令会生成进程号19321对应Java应用的存活对象的dump文件heapdump.bin。我们可以使用jhat工具来解析这个文件:
jhat heapdump.bin
然后在浏览器中访问http://localhost:7000/即可查看内存分析报告。
三、jmap的优化实践
1. 分析内存泄漏
使用jmap可以针对Java应用程序进行内存泄漏分析。如果应用程序出现了内存泄漏,就可以借助jmap管理Java堆中的对象,通过GC日志、堆转储文件等方式来确定内存泄漏的类型和原因。
下面是一个jmap分析内存泄漏的示例代码:
public class MemoryLeak { private static List
在运行该程序之后,我们可以使用如下命令来获取Java进程的pid:
jps -l
得到pid之后,我们可以使用如下命令来生成堆转储文件:
jmap -dump:live,format=b,file=heapdump.bin pid
使用MAT等工具,可以分析堆转储文件,找到内存泄漏的对象。例如,我们可以在MAT的Histogram视图中查看对象数量排名前100的对象,如下图所示:
可以看到,LinkedList$Entry对象数量排名第一,说明LinkedList中的节点占用了大量的内存。打开该对象的histogram视图,可以查看该对象的实例数量、大小、引用关系等信息,如下图所示:
可以看到,可以直接从该对象的链表、size属性追寻到具体的对象,从而找到内存泄漏的原因。
2. 分析OOM
jmap可以用于定位一个Java进程的OOM问题,步骤与上面类似。首先,需要在发生OOM的时候,使用jmap生成一个堆映射文件。这个文件可以与MAT等工具一起使用,从而进行内存分析。
下面是OOM的一些示例代码:
public class OOMTest { private static List
在运行该程序之后,我们可以使用如下命令来获取Java进程的pid:
jps -l
得到pid之后,我们可以使用如下命令来生成堆转储文件:
jmap -dump:live,format=b,file=heapdump.bin pid
使用MAT等工具,可以分析堆转储文件,找到OOM的原因。例如,我们可以在MAT的Histogram视图中查看对象数量排名前10的对象,如下图所示:
可以看到,Object实例的数量是最多的,Java应用在运行过程中创建了非常多的Object实例,使得堆内存被耗尽,从而发生了OOM。
四、jmap小结
jmap是一个非常强大的工具,可以帮助我们更好地了解Java应用程序的内存使用情况,从而进行优化。在实践中,我们可以使用jmap分析内存泄漏、OOM等问题,从而根据分析结果对应用程序进行优化。
原创文章,作者:KTDSR,如若转载,请注明出处:https://www.506064.com/n/369467.html