当在生产环境中发生内存溢出时,需要找出内存溢出的问题所在。当处于生产环境中,需要对内存镜像文件进行分析,进而找出导致内存溢出的原因。那么如何来到处内存镜像文件呢。
有两种方法,下面一一介绍。
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=./
./表示当发生内存溢出的时候自动到处到当前路径
jmap -dump:format=b,file=heap.hprof 进程ID
-Xmx32M -Xms32M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./
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)
其中-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>
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>
在eclipse中安装MAT插件,可以参考:https://blog.csdn.net/jiuweideqixu/article/details/99994536
Objects表示对象实例的数量。shallow Heap表示结构占用的内存(如List结构实例占用的内存),Retained Heap表示结构中存放的内容占用的内存(如List结构中存放的所有对象User的实例占用的内存)。
在某个对象的那一栏右击->Merge Shortest Paths to GC Roots->exclude all phantom/weak/soft etc. references
这里只查看强引用
从下图可以看出,tomcat Thread引用了一个MemoryController,MemoryController引用了userList,userList里面就是所有的User对象了。
GC root到某一个对象,排除所有的虚引用,只看强引用。
在真正的生产环境中,场景可能要复杂得多,因此,更要使用好MAT工具来进行内存使用情况的分析。通过分别查看对象和数量和对象占用的内存基本上就可以定位出是哪里发生了内存溢出。