Jmap
用途:
使用方法
查看实例个数以及所占用的内存大小
# 输出到控制条
jmap -histo pid
# 输出到文件
jmap -histo pid > ./log.txt
输出结果
列名参数解释:
- num:序号
- instances:所包含的实例数
- bytes:所占用的内存大小(byte)
- class name:该内存所对应的类名
- ([代表一维数组,[[ 代表二维数组)
- [I 是int 数组,[C是char数组,[B 是byte数组
- [[I是int[][]数组
查看堆内存的信息
jmap -heap pid
输出结果
Attaching to process ID 4084, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.60-b23
using thread-local object allocation.
# 并行垃圾收集器的线程(默认是CPU核数)
Parallel GC with 2 thread(s)
Heap Configuration:
MinHeapFreeRatio = 0
MaxHeapFreeRatio = 100
MaxHeapSize = 994050048 (948.0MB) //最大的堆空间,默认1/4 -Xmx
NewSize = 20971520 (20.0MB) // 新生代的空间
MaxNewSize = 331350016 (316.0MB) // 最大的新生代空间,默认整个堆的1/3
OldSize = 41943040 (40.0MB) // 老年代的大小
NewRatio = 2 // 新生代的比例与老年代的比例
SurvivorRatio = 8 // 伊甸园与幸存者区的比例
MetaspaceSize = 21807104 (20.796875MB) // 元空间的大小,默认21M
CompressedClassSpaceSize = 1073741824 (1024.0MB) // 类指针压缩空间大小,默认1G
MaxMetaspaceSize = 17592186044415 MB // 最大的元空间大小,默认无限大。。。
G1HeapRegionSize = 0 (0.0MB) // G1垃圾收集器的每块region的大小
Heap Usage:
PS Young Generation
Eden Space: // 伊甸园的容量
capacity = 80740352 (77.0MB)
used = 42850680 (40.86559295654297MB)
free = 37889672 (36.13440704345703MB)
53.072198644861% used
From Space: // from 区的幸存者区
capacity = 524288 (0.5MB)
used = 294912 (0.28125MB)
free = 229376 (0.21875MB)
56.25% used
To Space: // to 区的幸存者区
capacity = 524288 (0.5MB)
used = 0 (0.0MB)
free = 524288 (0.5MB)
0.0% used
PS Old Generation // 老年代
capacity = 76021760 (72.5MB)
used = 26281512 (25.064002990722656MB)
free = 49740248 (47.435997009277344MB)
34.57103860789332% used
19613 interned Strings occupying 1885552 bytes
dump 堆内存
[root@localhost ~]# jmap -dump:format=b,file=test.hprof 4084
Dumping heap to /root/test.hprof ...
Heap dump file created
除了手动到处dump文件之外,还可以通过设置内存溢出(OOM)时自动导出Dump文件,用于分析OOM时的内存情况
- -XX:+HeapDumpOnOutOfMemoryError
- -XX:HeapDumpPath=./ (指定dump导入的路径)
导出的Dump文件,可以通过jvisualvm工具打开,分析其中的内存情况
Jstack
Jstack 命令可以用来查询进程中的死锁
详细的步骤如下
死锁代码演示
public class Test2 {
public static void main(String[] args) {
String lockA = "lockA";
String lockB = "lockB";
new Thread(new MyDeadLock(lockA, lockB), "threadA").start();
new Thread(new MyDeadLock(lockB, lockA), "threadB").start();
}
}
class MyDeadLock implements Runnable {
private final String lockA;
private final String lockB;
public MyDeadLock(String lockA, String lockB) {
this.lockA = lockA;
this.lockB = lockB;
}
@Override
public void run() {
synchronized (lockA) {
System.out.println(Thread.currentThread().getName() + "\t持有" + lockA);
System.out.println(Thread.currentThread().getName() + "\t尝试获取" + lockB);
synchronized (lockB) {
}
}
}
}
通过Jstack命令进行查询死锁
jstack pid
输出结果
"threadB" #13 prio=5 os_prio=0 tid=0x0000000023a69000 nid=0x43d4 waiting for monitor entry [0x00000000249df000]
java.lang.Thread.State: BLOCKED (on object monitor)
at test.MyDeadLock.run(Test2.java:43)
- waiting to lock <0x0000000740aea228> (a java.lang.String)
- locked <0x0000000740aea260> (a java.lang.String)
at java.lang.Thread.run(Thread.java:748)
"threadA" #12 prio=5 os_prio=0 tid=0x0000000023a65800 nid=0x5c84 waiting for monitor entry [0x00000000248df000]
java.lang.Thread.State: BLOCKED (on object monitor)
at test.MyDeadLock.run(Test2.java:43)
- waiting to lock <0x0000000740aea260> (a java.lang.String)
- locked <0x0000000740aea228> (a java.lang.String)
at java.lang.Thread.run(Thread.java:748)
- threadB: 线程名字
- prio: 优先级
- os_prio:操作系统的优先级
- tid:线程id
- nid:线程标识
- BLOCKED:线程状态
```shell
Found one Java-level deadlock:
“threadB”: waiting to lock monitor 0x0000000021ab0a78 (object 0x0000000740aea228, a java.lang.String), which is held by “threadA” “threadA”: waiting to lock monitor 0x0000000023a6be18 (object 0x0000000740aea260, a java.lang.String), which is held by “threadB”
Java stack information for the threads listed above:
“threadB”: at test.MyDeadLock.run(Test2.java:43)
- waiting to lock <0x0000000740aea228> (a java.lang.String)
- locked <0x0000000740aea260> (a java.lang.String)
at java.lang.Thread.run(Thread.java:748)
“threadA”: at test.MyDeadLock.run(Test2.java:43)
- waiting to lock <0x0000000740aea260> (a java.lang.String)
- locked <0x0000000740aea228> (a java.lang.String)
at java.lang.Thread.run(Thread.java:748)
Found 1 deadlock.
找出了一个Java级别的死锁,具体的堆栈信息也已经打印,可以快速准确的定位到死锁的位置<br />**另外,也可以通过jvisualvm工具,找到对应的java进程,jvisualvm可以自动的监测死锁**<br />![image.png](https://cdn.nlark.com/yuque/0/2020/png/1538293/1601350916141-31109e65-a707-4009-aa0e-5dad3305309f.png#align=left&display=inline&height=493&margin=%5Bobject%20Object%5D&name=image.png&originHeight=493&originWidth=1609&size=65748&status=done&style=none&width=1609)<br />点击线程Dump之后,会看到与上述命令行中打印的信息相同,也可准确的定位到死锁的位置<br />![image.png](https://cdn.nlark.com/yuque/0/2020/png/1538293/1601351030339-7a5ddd6a-13a2-41e1-ae93-edd968ff2772.png#align=left&display=inline&height=937&margin=%5Bobject%20Object%5D&name=image.png&originHeight=937&originWidth=678&size=65415&status=done&style=none&width=678)
<a name="sJvXv"></a>
## Jstack查询CPU占用最高的线程
<a name="dPXKV"></a>
### 面试题:生产服务器**出现CPU占用过高,请谈谈你的分析思路和定位**
1. 通过top 命令查询出占用cpu最高的进程
![image.png](https://cdn.nlark.com/yuque/0/2020/png/1538293/1601351940395-a9b3e752-3acf-49cc-b9d0-cdc31a8980e1.png#align=left&display=inline&height=89&margin=%5Bobject%20Object%5D&name=image.png&originHeight=89&originWidth=1240&size=41369&status=done&style=none&width=1240)
2. ps -mp 进程编号 -o Thread.tid,time 查询出这个线程所占用的线程,找出cpu占用高的线程
![image.png](https://cdn.nlark.com/yuque/0/2020/png/1538293/1601351860515-5672e4ea-869b-4258-83d1-7c90b412938e.png#align=left&display=inline&height=468&margin=%5Bobject%20Object%5D&name=image.png&originHeight=468&originWidth=938&size=231682&status=done&style=none&width=938)
3. 将查询出来的线程id转成16进制
![image.png](https://cdn.nlark.com/yuque/0/2020/png/1538293/1601351873891-4b78cffc-c9ab-4a28-8be1-6a8941e5d170.png#align=left&display=inline&height=76&margin=%5Bobject%20Object%5D&name=image.png&originHeight=76&originWidth=670&size=20599&status=done&style=none&width=670)
4. 通过jstack命令,找出对应的堆栈
公式: jstack 进程id |grep 线程16进制 -A 行数
```shell
jstack 3896|grep f39 -A 60
JInfo
查看JVM运行时的参数 jinfo -flags pid
[root@localhost ~]# jinfo -flags 4084
Attaching to process ID 4084, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.60-b23
Non-default VM flags: -XX:CICompilerCount=2 -XX:InitialHeapSize=62914560
-XX:MaxHeapSize=994050048 -XX:MaxNewSize=331350016 -XX:MinHeapDeltaBytes=524288
-XX:NewSize=20971520 -XX:OldSize=41943040 -XX:+UseCompressedClassPointers
-XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:+UseParallelGC
Command line:
查看JVM的系统参数 jinfo -sysprops pid
可以查看jdk版本啊,jdk所在目录啊,操作系统啊等等信息。
Jstat
用于查询堆内存中各个区中的使用情况
公式:jstat [-option] [进程id] [时间间隔(毫秒)] [查询次数]
jstat -gc pid interval count
可以用来获取当前内存的使用情况,可以GC垃圾回收的次数以及时间
[root@localhost ~]# jstat -gc 4084 1000 5
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
512.0 512.0 0.0 256.0 84480.0 45960.3 74240.0 25809.5 65712.0 62406.9 8700.0 8114.6 3491 9.827 4 0.338 10.166
512.0 512.0 0.0 256.0 84480.0 45960.3 74240.0 25809.5 65712.0 62406.9 8700.0 8114.6 3491 9.827 4 0.338 10.166
512.0 512.0 0.0 256.0 84480.0 45968.9 74240.0 25809.5 65712.0 62406.9 8700.0 8114.6 3491 9.827 4 0.338 10.166
512.0 512.0 0.0 256.0 84480.0 45968.9 74240.0 25809.5 65712.0 62406.9 8700.0 8114.6 3491 9.827 4 0.338 10.166
512.0 512.0 0.0 256.0 84480.0 47031.8 74240.0 25809.5 65712.0 62406.9 8700.0 8114.6 3491 9.827 4 0.338 10.166
各个参数解释:
- SOC(survivors 0 count):幸存者0区的总大小
- S1C(survivors 1 count):幸存者1区的总大小
- S0U(survivors 0 used):幸存者0区的已使用大小
- S1U(survivors 1 used):幸存者1区的已使用大小
- EC(eden count):伊甸园的总大小
- EU(edeb used):伊甸园的已使用大小
- OC(old count):老年代的总大小
- OU(old used):老年代的已使用大小
- MC(metaspace count):元空间的总大小
- MU(metaspace used):元空间的已使用大小
- CCSC(compress class space count):压缩类的总空间大小
- CCSU(compress class space used):压缩类的已使用大小
- YGC(young gc count):Young GC的次数
- YGCT(young gc time):Young GC的总耗时
- FGC(full gc count):FULL GC的次数
- FGCT(full gc time): FULL GC的总耗时
-
jstat -gccapacity pid
用来获取当前堆的内存情况
[root@localhost ~]# jstat -gccapacity 4084
NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC
20480.0 323584.0 236032.0 512.0 512.0 89088.0 40960.0 647168.0 74240.0 74240.0 0.0 1105920.0 65712.0 0.0 1048576.0 8700.0 3500 4
各个参数解释:
NGCMN:新生代的最小容量
- NGCNX: 新生代的最大容量
- NGC: 新生代当前的容量
- S0C: 幸存者0区当前的容量
- S1C: 幸存者1区当前的容量
- EC: 伊甸园区当前的容量
- OGCMN:老年代的最小容量
- OGCMX:老年代的最大容量
- OGC: 老年代的当前大小
- OC: 老年代的当前大小
- MCMN: 元空间的最小容量
- MCMX: 元空间的最大容量
- MC: 元空间的当前大小
- CCSMN:压缩类空间的最小容量
- CCSMX: 压缩类空间的最大容量
- CCSC: 压缩类空间的当前大小
- YGC: Young GC 的次数
-
jstat -gcnew pid
用于新生代垃圾回收统计
[root@localhost ~]# jstat -gcnew 4084
S0C S1C S0U S1U TT MTT DSS EC EU YGC YGCT
512.0 512.0 352.0 0.0 15 15 512.0 90112.0 84565.4 3502 9.860
各个参数解释:
S0C: 幸存者0区的容量
- S1C: 幸存者1区的容量
- S0U: 幸存者0区已使用的大小
- S1U: 幸存者1区已使用的大小
- TT: 对象在新生代的存活次数
- MTT:对象在新生代的最大存活次数
- DSS: 期望的幸存者区大小
- EC: 伊甸园的大小
- EU: 伊甸园的使用大小
- YGC: Young GC的次数
-
jstat -gcnewcapacity pid
新生代的内存统计
NGCMN NGCMX NGC S0CMX S0C S1CMX S1C ECMX EC YGC FGC
20480.0 323584.0 236032.0 107520.0 512.0 107520.0 512.0 322560.0 90624.0 3503 4
各个参数解释:
NGCMN:新生代的最小容量
- NGCMX:新生代的最大容量
- NGC: 新生代的当前容量
- S0CMX: 幸存者0区的最大容量
- S0C: 幸存者0区的当前容量
- S1CMX: 幸存者1区的最大容量
- S1C: 幸存者1区的当前容量
- ECMX: 伊甸园区的最大容量
- EC: 伊甸园区的当前容量
- YGC: Young GC的次数
-
jstat -gcold pid
用于老年代垃圾回收统计
MC MU CCSC CCSU OC OU YGC FGC FGCT GCT
65712.0 62406.9 8700.0 8114.6 74240.0 26025.5 3504 4 0.338 10.205
各个参数解释:
MC: 元空间的容量
- MU: 元空间的已使用大小
- CCSC: 压缩类空间的容量
- CCSU: 压缩类空间的已使用大小
- OC: 老年代的容量
- OU: 老年代的已使用大小
- YGC: Young GC的次数
- FGC: FULL GC的次数
- FGCT: FULL GC的总耗时
-
jstat -gcoldcapacity pid
老年代内存统计
OGCMN OGCMX OGC OC YGC FGC FGCT GCT
40960.0 647168.0 74240.0 74240.0 3505 4 0.338 10.207
各个参数解释:
OGCMN: 老年代的最小容量
- OGCMX: 老年代的最大容量
- OGC: 老年代的当前容量
- OC: 老年代的当前容量
- YGC: Young GC的次数
- FGC: FULL GC的次数
- FGCT: FULL GC的消耗时间
-
jstat -gcmetacapacity pid
元数据的空间统计
MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC FGCT GCT
0.0 1105920.0 65712.0 0.0 1048576.0 8700.0 3505 4 0.338 10.207
各个参数解释:
MCMN: 元空间的最小容量
- MCMX: 元空间的最大容量
- MC: 元空间的当前使用容量
- CCSMN: 压缩类空间的最小容量
- CCSMX: 压缩类空间的最大容量
- CCSC: 压缩类空间的当前容量
- YGC: Young GC的次数
- FGC: FULL GC的次数
- FGCT: FULL GC的消耗时间
-
jstat -gcutil pid
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0.00 68.75 86.91 35.08 94.97 93.27 3505 9.869 4 0.338 10.207
各个参数解释:
S0: 幸存者0区的大小
- S1: 幸存者1区的大小
- E: 伊甸园区的大小
- O: 老年代的大小
- M: 元空间的大小
- CCS: 压缩类空间的大小
- YGC: Young GC的次数
- YGCT: Young GC的消耗时间
- FGC: FULL GC的次数
- FGCT: FULL GC的消耗时间
- GCT: 垃圾回收的总时间