java 内存分析工具实践

参考此文,在本机实践:https://my.oschina.net/feichexia/blog/196575

jmap   可以用dump 再用jhat 查看使用

jstack  查看堆内存 加-heap 使用   各代内存大小 使用情况    查看各线程状态

jstat 查看各内存的使用情况,eden survior perment 使用/未使用

jprof 查看cpu使用情况

jmap -heap pid


top -Hp pid 查看各线程 


遇到下面的问题:

Exception in thread "main" java.lang.reflect.InvocationTargetException

搜索说是 java程序运行的版本跟jmap版本不一致,也就是我在终端中的java版本是1.7 idea里用的是1.8.把1.8改成了1.7

target需要调整

project structure 里source 的language level 也需要降到7

jmap -heap

jmap -dump

jmap -histo[:live]

查看堆内存使用情况:

lxxxxxxxx-pc:~$ jmap -heap 5362
Attaching to process ID 5362, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.60-b09


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


Heap Configuration:
   MinHeapFreeRatio = 0
   MaxHeapFreeRatio = 100
   MaxHeapSize      = 3072327680 (2930.0MB)
   NewSize          = 1310720 (1.25MB)
   MaxNewSize       = 17592186044415 MB
   OldSize          = 5439488 (5.1875MB)
   NewRatio         = 2
   SurvivorRatio    = 8
   PermSize         = 21757952 (20.75MB)
   MaxPermSize      = 85983232 (82.0MB)
   G1HeapRegionSize = 0 (0.0MB)


Heap Usage:
PS Young Generation
Eden Space:
   capacity = 48234496 (46.0MB)
   used     = 3873096 (3.6936721801757812MB)
   free     = 44361400 (42.30632781982422MB)
   8.029722130816916% used
From Space:
   capacity = 7864320 (7.5MB)
   used     = 0 (0.0MB)
   free     = 7864320 (7.5MB)
   0.0% used
To Space:
   capacity = 7864320 (7.5MB)
   used     = 0 (0.0MB)
   free     = 7864320 (7.5MB)
   0.0% used
PS Old Generation
   capacity = 127926272 (122.0MB)
   used     = 0 (0.0MB)
   free     = 127926272 (122.0MB)
   0.0% used
PS Perm Generation
   capacity = 22020096 (21.0MB)
   used     = 3648864 (3.479827880859375MB)
   free     = 18371232 (17.520172119140625MB)
   16.570608956473215% used


924 interned Strings occupying 63976 bytes.


查看堆内存中的对象数目(:live 只统计或对象)  对象很多就把少于250的都去掉了 算是个例子

类型对应情况

B  byte
C  char
D  double
F  float
I  int
J  long
Z  boolean
[  数组,如[I表示int[]
[L+类名 其他对象


jmap -histo:live 5497

 num     #instances         #bytes  class name
----------------------------------------------
   1:          7936        1022480  
   2:          7936         933672  
   3:           553         644480  
   4:           518         419168  
   5:           553         379896  
   6:          1073         352968  [B
   7:          1806         220088  [C
   8:           630          77176  java.lang.Class
   9:           880          56280  [[I
  10:           854          53072  [S
  11:          1777          42648  java.lang.String
  12:            60          32640  
  13:           407          21904  [Ljava.lang.Object;
  14:           353          14120  java.lang.ref.Finalizer
  15:           200          12800  java.net.URL
  16:           288           9216  java.util.HashMap$Entry
  17:            15           8872  
  18:           113           8136  java.lang.reflect.Field
  19:            91           7280  [Ljava.util.WeakHashMap$Entry;
  20:            83           6640  java.util.jar.JarFile$JarFileEntry
  21:            88           5632  java.util.jar.JarFile
  22:            72           5472  [Ljava.util.HashMap$Entry;
  23:            92           5152  java.util.zip.ZipFile$ZipFileInputStream
  24:            91           5096  java.util.WeakHashMap
  25:            99           4752  sun.misc.URLClassPath$JarLoader
  26:            93           4464  sun.nio.cs.UTF_8$Encoder
  27:            79           4424  java.util.zip.ZipFile$ZipFileInflaterInputStream
  28:             8           4352  
  29:           108           4320  java.util.LinkedHashMap$Entry
  30:            79           3792  java.util.zip.Inflater
  31:            78           3744  java.util.HashMap
  32:           113           3616  java.util.Hashtable$Entry
  33:           110           3520  java.util.concurrent.ConcurrentHashMap$HashEntry
  34:            98           3136  java.lang.ref.ReferenceQueue
  35:            92           3024  [Ljava.lang.String;
  36:            20           2880  [I
  37:            88           2816  java.util.zip.ZipCoder
  38:            65           2600  java.util.concurrent.ConcurrentHashMap$Segment
  39:           104           2496  java.io.ExpiringCache$Entry
  40:            11           2288  
  41:            88           2112  java.util.ArrayDeque
  42:            65           2080  java.util.concurrent.locks.ReentrantLock$NonfairSync
  43:            43           2064  sun.util.locale.LocaleObjectCache$CacheEntry
  44:            82           1968  java.util.jar.Attributes$Name
  45:            65           1928  [Ljava.util.concurrent.ConcurrentHashMap$HashEntry;
  46:            79           1896  java.util.zip.ZStreamRef
  47:            24           1728  java.lang.reflect.Constructor
  48:           100           1600  java.lang.ref.ReferenceQueue$Lock
  49:            99           1584  java.lang.Object
  50:            11           1312  [Ljava.util.Hashtable$Entry;
  51:            32           1280  java.lang.ref.SoftReference
  52:            30           1200  java.io.ObjectStreamField
  53:            49           1176  java.util.LinkedList$Node
  54:            11            880  [Ljava.util.concurrent.ConcurrentHashMap$Segment;
  55:            21            840  sun.util.locale.BaseLocale$Key
  56:            24            768  java.util.LinkedList
  57:            42            672  java.util.jar.Attributes
  58:            21            672  sun.util.locale.BaseLocale
  59:            11            656  [Ljava.lang.reflect.Field;
  60:             6            624  java.lang.Thread
  61:            11            528  java.util.concurrent.ConcurrentHashMap
  62:            21            504  java.util.Locale$LocaleKey
  63:            21            504  java.util.Locale
  64:            14            448  java.security.AccessControlContext
  65:             8            384  java.util.Hashtable
  66:             6            384  java.nio.DirectByteBuffer
  67:            12            344  [Ljava.io.ObjectStreamField;
  68:             6            336  java.nio.DirectLongBufferU
  69:             3            312  thread
  70:            17            304  [Ljava.lang.Class;
  71:            12            288  sun.reflect.NativeConstructorAccessorImpl
  72:            12            288  [Ljava.lang.reflect.Constructor;
  73:            11            264  java.io.FileDescriptor
  74:            11            264  java.util.ArrayList
  75:             8            256  java.util.Vector
  76:             8            256  java.lang.OutOfMemoryError
  77:             8            256  java.io.FileInputStream
还有一个很常用的情况是:用jmap把进程内存使用情况dump到文件中,再用jhat分析查看。jmap进行dump命令格式如下:

jmap -dump:format=b,file=dumpFileName pid

~$ jmap -dump:format=b,file=./dump.dat 5497
Dumping heap to /home/liupeizeng/dump.dat ...
Heap dump file created

dump出来的文件可以用MAT、VisualVM等工具查看,这里用jhat查看:

~$ jhat -port 9998 ./dump.dat 
Reading from ./dump.dat...
Dump file created Wed Aug 09 10:21:18 CST 2017
Snapshot read, resolving...
Resolving 10683 objects...
Chasing references, expect 2 dots..
Eliminating duplicate references..
Snapshot resolved.
Started HTTP server on port 9998
Server is ready.


这个时候就可以打开浏览器到 9998端口查看情况了。


超类/classloader/package等信息 All Members of the Rootset/Heap Histogram

jstack 的使用情况:


~$ jstack 5497
2017-08-09 10:30:10
Full thread dump Java HotSpot(TM) 64-Bit Server VM (24.60-b09 mixed mode):


"Attach Listener" daemon prio=10 tid=0x00007f7b74001000 nid=0x15fb waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE


"Service Thread" daemon prio=10 tid=0x00007f7ba03eb800 nid=0x1593 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE


"C2 CompilerThread1" daemon prio=10 tid=0x00007f7ba03e9800 nid=0x1592 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE


"C2 CompilerThread0" daemon prio=10 tid=0x00007f7ba03e6800 nid=0x1591 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE


"Monitor Ctrl-Break" daemon prio=10 tid=0x00007f7ba03e5000 nid=0x1590 runnable [0x00007f7b990dc000]
   java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:152)
at java.net.SocketInputStream.read(SocketInputStream.java:122)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:283)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:325)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:177)
- locked <0x0000000748e06c88> (a java.io.InputStreamReader)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:154)
at java.io.BufferedReader.readLine(BufferedReader.java:317)
- locked <0x0000000748e06c88> (a java.io.InputStreamReader)
at java.io.BufferedReader.readLine(BufferedReader.java:382)
at com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:64)


"Signal Dispatcher" daemon prio=10 tid=0x00007f7ba0154000 nid=0x158f runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE


"Finalizer" daemon prio=10 tid=0x00007f7ba013b800 nid=0x1588 in Object.wait() [0x00007f7b99ae9000]
   java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x0000000748e085a0> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:135)
- locked <0x0000000748e085a0> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:151)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)


"Reference Handler" daemon prio=10 tid=0x00007f7ba0139800 nid=0x1587 in Object.wait() [0x00007f7b99bea000]
   java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x0000000748e08418> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:503)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:133)
- locked <0x0000000748e08418> (a java.lang.ref.Reference$Lock)


"main" prio=10 tid=0x00007f7ba000e800 nid=0x157e waiting on condition [0x00007f7ba631b000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at thread.run(heh.java:15)
at heh.main(heh.java:36)


"VM Thread" prio=10 tid=0x00007f7ba0135000 nid=0x1586 runnable 


"GC task thread#0 (ParallelGC)" prio=10 tid=0x00007f7ba0024000 nid=0x157f runnable 


"GC task thread#1 (ParallelGC)" prio=10 tid=0x00007f7ba0026000 nid=0x1580 runnable 


"GC task thread#2 (ParallelGC)" prio=10 tid=0x00007f7ba0028000 nid=0x1581 runnable 


"GC task thread#3 (ParallelGC)" prio=10 tid=0x00007f7ba0029800 nid=0x1582 runnable 


"VM Periodic Task Thread" prio=10 tid=0x00007f7ba03ee800 nid=0x1594 waiting on condition 


dump 文件里,值得关注的线程状态有:
  1. 死锁,Deadlock(重点关注) 
  2. 执行中,Runnable   
  3. 等待资源,Waiting on condition(重点关注) 
  4. 等待获取监视器,Waiting on monitor entry(重点关注)
  5. 暂停,Suspended
  6. 对象等待中,Object.wait() 或 TIMED_WAITING
  7. 阻塞,Blocked(重点关注)  
  8. 停止,Parked



第二步找出该进程内最耗费CPU的线程,可以使用ps -Lfp pid或者ps -mp pid -o THREAD, tid, time或者top -Hp pid

top -Hp pid 查看各个线程,找到线程号,转成16禁止,然后 jstack 进程 |grep 线程 打印信息 看在哪里 

~$ jstack 5497| grep 1594
"VM Periodic Task Thread" prio=10 tid=0x00007f7ba03ee800 nid=0x1594 waiting on condition 

~$ jstack 5497| grep 157e
"main" prio=10 tid=0x00007f7ba000e800 nid=0x157e waiting on condition [0x00007f7ba631b000]



jstat 

语法格式如下:


jstat [ generalOption | outputOptions vmid [interval[s|ms] [count]] ]
    vmid是Java虚拟机ID,在Linux/Unix系统上一般就是进程ID。interval是采样时间间隔。count是采样数目。比如下面输出的是GC信息,采样时间间隔为250ms,采样数为4:

:~$ jstat -gc 5497 250 4
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       PC     PU    YGC     YGCT    FGC    FGCT     GCT   
7680.0 7680.0  0.0    0.0   47104.0   1884.3   48128.0     778.1    21504.0 3562.7      1    0.003   1      0.019    0.022
7680.0 7680.0  0.0    0.0   47104.0   1884.3   48128.0     778.1    21504.0 3562.7      1    0.003   1      0.019    0.022
7680.0 7680.0  0.0    0.0   47104.0   1884.3   48128.0     778.1    21504.0 3562.7      1    0.003   1      0.019    0.022
7680.0 7680.0  0.0    0.0   47104.0   1884.3   48128.0     778.1    21504.0 3562.7      1    0.003   1      0.019    0.022


S0C、S1C、S0U、S1U:Survivor 0/1区容量(Capacity)和使用量(Used)
EC、EU:Eden区容量和使用量
OC、OU:年老代容量和使用量
PC、PU:永久代容量和使用量
YGC、YGT:年轻代GC次数和GC耗时
FGC、FGCT:Full GC次数和Full GC耗时
GCT:GC总耗时

hprof(Heap/CPU Profiling Tool)

    hprof能够展现CPU使用率,统计堆内存使用情况。

    语法格式如下:

java -agentlib:hprof[=options] ToBeProfiledClass
java -Xrunprof[:options] ToBeProfiledClass
javac -J-agentlib:hprof[=options] ToBeProfiledClass
采集cpu消耗信息


你可能感兴趣的:(日常)