【openJDK系列3】java OOM 分析(mat工具的使用)

背景

在java应用开发中 我们难免会遇到java stack和heap的分析,在此记录一下对于发生OOM时候,该怎么进行分析

分析

  • 首先我们得会几个工具,
jps
jmap -heap
jmap -histo:live
jmap -dump:format=b,file=dump.hprof
mat(Memory Analyzer Tool)

  • jps 用来看运行的应用是哪个pid
  • jmap -heap 用来查看该应用堆内存总体分布情况
  • jmap -histo:live 用来查看
  • jmap -dump 用来dump 应用整个堆的明细情况,便于具体分析oom的对象
  • mat 用来分析dump出来的文件的可视化软件,下载网址,根据自己的系统进行安装对应的软件就行

举个例子

$ jps
8727 DemoApplication
7914 Jps
$ jmap -heap 8727
Debugger attached successfully.
Server compiler detected.
JVM version is 25.151-b12

using parallel threads in the new generation.
using thread-local object allocation.
Concurrent Mark-Sweep GC

Heap Configuration:
  MinHeapFreeRatio         = 40
  MaxHeapFreeRatio         = 70
  MaxHeapSize              = 1073741824 (1024.0MB)
  NewSize                  = 1073676288 (1023.9375MB)
  MaxNewSize               = 1073676288 (1023.9375MB)
  OldSize                  = 65536 (0.0625MB)
  NewRatio                 = 2
  SurvivorRatio            = 1
  MetaspaceSize            = 21807104 (20.796875MB)
  CompressedClassSpaceSize = 1073741824 (1024.0MB)
  MaxMetaspaceSize         = 17592186044415 MB
  G1HeapRegionSize         = 0 (0.0MB)

Heap Usage:
New Generation (Eden + 1 Survivor Space):
  capacity = 715784192 (682.625MB)
  used     = 463683480 (442.2030258178711MB)
  free     = 252100712 (240.4219741821289MB)
  64.7797877045041% used
Eden Space:
  capacity = 357892096 (341.3125MB)
  used     = 357892096 (341.3125MB)
  free     = 0 (0.0MB)
  100.0% used
From Space:
  capacity = 357892096 (341.3125MB)
  used     = 105791384 (100.8905258178711MB)
  free     = 252100712 (240.4219741821289MB)
  29.559575409008193% used
To Space:
  capacity = 357892096 (341.3125MB)
  used     = 0 (0.0MB)
  free     = 357892096 (341.3125MB)
  0.0% used
concurrent mark-sweep generation:
  capacity = 65536 (0.0625MB)
  used     = 65536 (0.0625MB)
  free     = 0 (0.0MB)
  100.0% used

这里我们能看到jvm队的各个分区的内存大小以及使用情况,以及堆的配置情况

为了分析导致OOM的对象,执行

$jmap -histo:live 8727

 num     #instances         #bytes  class name
----------------------------------------------
   1:        105666       12543792  [C
   2:          5671        2608472  [B
   3:        104224        2501376  java.lang.String
   4:         17232        1902336  java.lang.Class
   5:         55156        1764992  java.util.concurrent.ConcurrentHashMap$Node
   6:         19700        1733600  java.lang.reflect.Method
   7:         20805        1210960  [Ljava.lang.Object;
   8:            27         885168  [Ljava.util.concurrent.ForkJoinTask;
   9:         19971         798840  java.util.LinkedHashMap$Entry
  10:          9524         710520  [Ljava.util.HashMap$Node;
  11:         20654         660928  java.util.HashMap$Node
  12:         10754         602224  java.util.LinkedHashMap
  13:           319         530688  [Ljava.util.concurrent.ConcurrentHashMap$Node;
  14:         27608         441728  java.lang.Object
  15:          6672         351288  [I
  16:         13947         307648  [Ljava.lang.Class;
  17:         10444         250656  java.util.ArrayList
  18:          3884         217504  java.lang.invoke.MemberName
  19:          4444         175624  [Ljava.lang.String;
  20:          4328         173120  java.lang.ref.SoftReference
  21:          3317         159216  java.util.HashMap
  22:           105         137344  [J
  23:          5262         126288  org.springframework.core.MethodClassKey
  24:          1447         115760  java.lang.reflect.Constructor
  25:          3580         114560  java.util.LinkedList
  26:          1491         107352  org.springframework.core.annotation.AnnotationAttributes
  27:          1079         103584  org.springframework.beans.GenericTypeAwarePropertyDescriptor
  28:          2540         101600  java.lang.invoke.MethodType
  29:          3154         100928  java.lang.ref.WeakReference
  30:          2437          97480  java.util.TreeMap$Entry
  31:          3018          96576  java.lang.invoke.DirectMethodHandle
  32:          1450          92800  java.net.URL
  33:          3791          90984  sun.reflect.generics.tree.SimpleClassTypeSignature
  34:          2546          81472  java.lang.invoke.MethodType$ConcurrentWeakInternSet$WeakEntry
  35:          3175          76200  java.util.LinkedList$Node
  36:          3791          72048  [Lsun.reflect.generics.tree.TypeArgument;
  37:          2951          70824  java.beans.MethodRef

其中,
num 代表占用字节的大小排名
instances 代表实例的数目
bytes 代表占用的字节数
class name的具体含义如下:
B代表byte
C代表char
D代表double
F代表float
I代表int
1J代表long
Z代表boolean
前边有[代表数组,[I 就相当于int[]
这里其实就能看出个到底是哪个对象占用了太多导致了OOM

为了进一步分析,我们得dump出具体的堆明细

jmap -dump:format=b,file=dump.hprof

拿到dump.hprof文件,我们假设你已经安装了mat(如安装出现问题见下方注意),

  • 按照 文件-》open heap Dump,倒入文件
  • 选择Leak Suspects Report
  • 选择Overview下的Histogram可以看到每个类的实例的数量大小,默认按照数量大小从大到小排列
  • 选择你认为有可能OOM的对象,右击,选择List objects -》 with incoming references,则可以看到对应的代码的调用情况

注意:

如果在运行mat的过程中出现

java.lang.IllegalStateException: The platform metadata area could not be written: /private/var/folders/1l/mwvs7rf563x72kqcv7l6rb840000gn/T/AppTranslocation/F5D8FB45-D694-4157-BDAF-1D58A9B350BC/d/mat.app/Contents/MacOS/workspace/.metadata.  By default the platform writes its content
under the current working directory when the platform is launched.  Use the -data parameter to
specify a different content area for the platform.

找到对应mat下的Contents/Eclipse/MemoryAnalyzer.ini文件
增加

-data
## /Users/path/to/dir为可写权限的目录
/Users/path/to/dir

即可解决

你可能感兴趣的:(【openJDK系列3】java OOM 分析(mat工具的使用))