使用方法
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
- jmap -heap :当前堆内存分布信息,如From space, To Space等占用内存大小
- jmap -histo : 当前堆中对象占用内存大小情况,柱状图数据结构组织。可以简单得定位下当前占用内存最大的几个对象
- jmap -histo:live:先触发一次gc , 再统计对象占用内存情况。可以简单得定位下当前占用内存最大的几个对象以及对象是否可以被gc回收
- jmap -dump:format=b,file=heapDump <pid>: 导出堆详细使用信息,b表示二进制文件,之后采用其他工具分析,如jhat,mat.非常详细,可分析到对象之间的引用关系等。
示例
代码
package com.xxx; import java.util.ArrayList; import java.util.List; /** * * 这是一个Person类,我用它来撑满heap * @author zcluo * */ public class Person { private String name; private String sex; private int age; public Person( String name,String sex,int age){ this.name=name; this.sex=sex; this.age=age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public static void main(String[] args){ //无限往一个List中加对象,因为List是强引用,所以不会被GC,从而导致memory溢出 List<Person> persons = new ArrayList<Person>(); while( 1>0){ persons.add( new Person("fakeperson","male",25)); } } }
运行参数
VM options: -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:\dump -Xmx200M -Xms200M
初步排查问题
#查询JAVA进程所在的进程 jps 15296 11672 Jps 15832 11628 Person 7372 Launcher
#打印进程的堆栈配置和使用情况 jmap -heap 11628 Attaching to process ID 11628, please wait... Debugger attached successfully. Server compiler detected. JVM version is 25.91-b14 using thread-local object allocation. Parallel GC with 4 thread(s) Heap Configuration: MinHeapFreeRatio = 0 MaxHeapFreeRatio = 100 MaxHeapSize = 2147483648 (2048.0MB) NewSize = 69730304 (66.5MB) MaxNewSize = 715653120 (682.5MB) OldSize = 139984896 (133.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 = 238551040 (227.5MB) used = 238551024 (227.49998474121094MB) free = 16 (1.52587890625E-5MB) 99.99999329283997% used From Space: capacity = 238551040 (227.5MB) used = 0 (0.0MB) free = 238551040 (227.5MB) 0.0% used To Space: capacity = 238551040 (227.5MB) used = 0 (0.0MB) free = 238551040 (227.5MB) 0.0% used PS Old Generation capacity = 1431830528 (1365.5MB) used = 1431418832 (1365.1073760986328MB) free = 411696 (0.3926239013671875MB) 99.97124687650185% used 1755 interned Strings occupying 156904 bytes.
#打印该进程堆中对象占用字节从大到小排序 jmap -histo:live 5808 num #instances #bytes class name ---------------------------------------------- 1: 54248921 1301974104 com.ccb.Person 2: 592 280397992 [Ljava.lang.Object; 3: 2462 328864 [C 4: 605 69200 java.lang.Class 5: 2302 55248 java.lang.String 6: 24 33544 [B 7: 833 33320 java.util.TreeMap$Entry 8: 113 8136 java.lang.reflect.Field 9: 201 8120 [Ljava.lang.String; 10: 73 4672 java.net.URL 11: 105 4200 java.lang.ref.SoftReference 12: 105 4176 [I 13: 256 4096 java.lang.Integer 14: 116 3712 java.util.Hashtable$Entry 15: 115 3680 java.util.HashMap$Node 16: 90 2880 java.util.concurrent.ConcurrentHashMap$Node 17: 7 2632 java.lang.Thread 18: 18 2016 [Ljava.util.HashMap$Node; 19: 38 1824 sun.util.locale.LocaleObjectCache$CacheEntry 20: 22 1760 java.lang.reflect.Constructor 21: 36 1728 sun.misc.URLClassPath$JarLoader 22: 38 1520 java.util.LinkedHashMap$Entry 23: 37 1480 java.io.ObjectStreamField 24: 24 1344 java.lang.Class$ReflectionData 25: 81 1296 java.lang.Object 26: 15 1200 [Ljava.util.WeakHashMap$Entry; 27: 24 1152 java.util.HashMap 28: 2 1064 [Ljava.lang.invoke.MethodHandle; 29: 7 1056 [Ljava.util.Hashtable$Entry; 30: 1 1040 [Ljava.lang.Integer; 31: 1 1040 [[C 32: 5 912 [Ljava.util.concurrent.ConcurrentHashMap$Node;
#dump堆内存 jmap -dump:format=b,file=d:\dump\dump.bin 5808 Dumping heap to D:\dump\dump.bin ... Heap dump file created
eclipse MAT工具进行内存分析
基本概念
- Strong reference : 就是我们new出来的对象,但是还是被持有的应用,垃圾回收时不会回收这个应用
- soft reference : 我们new出来的对象,但是已经不被具体对象持有,常见的就是缓存中的对象引用,垃圾回收在内存还够的时候不会回收该部分内存信息,只有在内存不够时才会回收这块引用的对象
- weak reference : 当对象不在有强引用时候,垃圾回收时立刻回收。
- Phantom reference : 不会在内存中出现,因为它一般是同ReferenceQueue一起出现,来跟踪对象是否还是保持强引用。
- shallow size:对象自身中有的内存大小
- retained size:对象自身大小 + 该对象直接或是间接引用对象的shallow size
- GC Roots:所有的对象引用refer chains的起点。
- MAT工具帮助中对于shallow size和retained size的解释Shallow vs. Retained HeapShallow heap is the memory consumed by one object. An object needs 32 or 64 bits (depending on the OS architecture) per reference, 4 bytes per Integer, 8 bytes per Long, etc. Depending on the heap dump format the size may be adjusted (e.g. aligned to 8, etc…) to model better the real consumption of the VM.
Retained set of X is the set of objects which would be removed by GC when X is garbage collected.
Retained heap of X is the sum of shallow sizes of all objects in the retained set of X, i.e. memory kept alive by X.
Generally speaking, shallow heap of an object is its size in the heap and retained size of the same object is the amount of heap memory that will be freed when the object is garbage collected.
The retained set for a leading set of objects, such as all objects of a particular class or all objects of all classes loaded by a particular class loader or simply a bunch of arbitrary objects, is the set of objects that is released if all objects of that leading set become unaccessible. The retained set includes these objects as well as all other objects only accessible through these objects. The retained size is the total heap size of all objects contained in the retained set.
分析步骤
1、导入dump文件
2、基本信息
Details:
Size: 164.8 MB Classes: 559 Objects: 6.2m Class Loader: 3
3、Retained Size排序的大对象饼状图
- list objects — with outgoing references : 查看这个对象持有的外部对象引用。
- list objects — with incoming references : 查看这个对象被哪些外部对象引用。
- show objects by class — with outgoing references :查看这个对象类型持有的外部对象引用
- show objects by class — with incoming references :查看这个对象类型被哪些外部对象引用
- paths to gc root : 显示不同类型引用(上文中提到的Strong ,soft,weak )到跟节点的路径。
- merge shorest path to gc root : 合并最短路径到root节点
- java basics:
- — classloader 该对象对应的classloader信息 。
- — thread details :线程信息
- — thread stacks :线程堆栈
- — find String : 在这个对象中查询需要的字符串
- — group by : 根据某个字段统计出现的个数
- leak Identification — top consumers :几个大消耗内存的对象
4、获取大对象持有的外部对象应用
结果如下:
5、定位大对象产生的代码
结果如下:
6、代码分析