参考此文,在本机实践: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
第二步找出该进程内最耗费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消耗信息