导出内存映像文件并使用MAT工具定位内存溢出问题

问题分析

当在生产环境中发生内存溢出时,需要找出内存溢出的问题所在。当处于生产环境中,需要对内存镜像文件进行分析,进而找出导致内存溢出的原因。那么如何来到处内存镜像文件呢。
有两种方法,下面一一介绍。

内存溢出自动导出

-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=./
./表示当发生内存溢出的时候自动到处到当前路径

使用jmap命令手动导出

jmap -dump:format=b,file=heap.hprof 进程ID

演示自动导出

首先设置VM options

-Xmx32M -Xms32M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./
导出内存映像文件并使用MAT工具定位内存溢出问题_第1张图片

访问controller

http://localhost:8080/heap

查看异常信息
java.lang.OutOfMemoryError: GC overhead limit exceeded
Dumping heap to ./\java_pid7612.hprof ...
Heap dump file created [43321403 bytes in 0.143 secs]
Exception in thread "http-nio-8080-exec-1" java.lang.OutOfMemoryError: GC overhead limit exceeded
	at java.lang.StringCoding$StringDecoder.decode(StringCoding.java:149)
	at java.lang.StringCoding.decode(StringCoding.java:193)
	at java.lang.String.<init>(String.java:426)
	at java.util.jar.Attributes.read(Attributes.java:418)
	at java.util.jar.Manifest.read(Manifest.java:199)
	at java.util.jar.Manifest.<init>(Manifest.java:69)
	at java.util.jar.JarFile.getManifestFromReference(JarFile.java:199)
查看生成的文件

导出内存映像文件并使用MAT工具定位内存溢出问题_第2张图片

演示手动导出:使用jmap

其中-dump中的format和file比较重要
format=b binary format
file= dump heap to

C:\Users\Administrator>jmap -help
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

从 7612 com.imooc.monitor_tuning.MonitorTuningApplication 可知进程的ID为7612
然后使用jmap -dump:format=b,file=heap.hprof 7612进行导出

C:\Users\Administrator\Desktop>jps -l
3536 sun.tools.jps.Jps
7712 org.jetbrains.idea.maven.server.RemoteMavenServer
7908 org.jetbrains.jps.cmdline.Launcher
1852
7612 com.imooc.monitor_tuning.MonitorTuningApplication

C:\Users\Administrator\Desktop>jmap -dump:format=b,file=heap.hprof 7612
Dumping heap to C:\Users\Administrator\Desktop\heap.hprof ...
Heap dump file created

C:\Users\Administrator\Desktop>

可以查看,桌面已经生成了heap.hprof文件
导出内存映像文件并使用MAT工具定位内存溢出问题_第3张图片

jmap命令的其他参数

option: -heap, -clstats, -dump:, -F

手动导出和自动导出的对比

当内存比较大的时候,自动导出可能会失去作用,所以这时可以使用jmap来手动导出内存镜像文件。
如使用jmap -heap 进程Id查看内存中很多个区块占用的内存

C:\Users\Administrator\Desktop>jmap -heap 7612
Attaching to process ID 7612, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.181-b13

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

Heap Configuration:
   MinHeapFreeRatio         = 0
   MaxHeapFreeRatio         = 100
   MaxHeapSize              = 33554432 (32.0MB)
   NewSize                  = 11010048 (10.5MB)
   MaxNewSize               = 11010048 (10.5MB)
   OldSize                  = 22544384 (21.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 = 6815744 (6.5MB)
   used     = 6815744 (6.5MB)
   free     = 0 (0.0MB)
   100.0% used
From Space:
   capacity = 2097152 (2.0MB)
   used     = 0 (0.0MB)
   free     = 2097152 (2.0MB)
   0.0% used
To Space:
   capacity = 2097152 (2.0MB)
   used     = 0 (0.0MB)
   free     = 2097152 (2.0MB)
   0.0% used
PS Old Generation
   capacity = 22544384 (21.5MB)
   used     = 22129496 (21.104331970214844MB)
   free     = 414888 (0.39566802978515625MB)
   98.15968358239462% used

13540 interned Strings occupying 1329080 bytes.

C:\Users\Administrator\Desktop>

进行问题定位

MAT分析内存溢出

在eclipse中安装MAT插件,可以参考:https://blog.csdn.net/jiuweideqixu/article/details/99994536

查看对象的数量

Objects表示对象实例的数量。shallow Heap表示结构占用的内存(如List结构实例占用的内存),Retained Heap表示结构中存放的内容占用的内存(如List结构中存放的所有对象User的实例占用的内存)。
导出内存映像文件并使用MAT工具定位内存溢出问题_第4张图片

查看是哪一个GC root引用了这个对象

在某个对象的那一栏右击->Merge Shortest Paths to GC Roots->exclude all phantom/weak/soft etc. references
这里只查看强引用
从下图可以看出,tomcat Thread引用了一个MemoryController,MemoryController引用了userList,userList里面就是所有的User对象了。
GC root到某一个对象,排除所有的虚引用,只看强引用。
导出内存映像文件并使用MAT工具定位内存溢出问题_第5张图片

查看对象占用的字节数

同样,点击某一个对象,可以进行展开。
导出内存映像文件并使用MAT工具定位内存溢出问题_第6张图片

后记

在真正的生产环境中,场景可能要复杂得多,因此,更要使用好MAT工具来进行内存使用情况的分析。通过分别查看对象和数量和对象占用的内存基本上就可以定位出是哪里发生了内存溢出。

你可能感兴趣的:(导出内存映像文件并使用MAT工具定位内存溢出问题)