JAVA性能问题排查-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

  • 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、代码分析

发表评论

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据