常见JVM调优工具及实战
1、Jdk自带的常见命令
一般通过命令行工具查询某个进程的信息,都需要进程号。
[root@VM-0-8-centos ~]# jps
14084 Launcher
14136 Csdn
12172 RemoteMavenServer36
7724 Jps
1.1 java -heap (pid)
查看垃圾收集器信息,初始化堆内存配置,堆空间内存占用情况
C:\Users\Administrator>jmap -heap 14136
Attaching to process ID 14136, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.152-b16
using thread-local object allocation.
Parallel GC with 6 thread(s)
Heap Configuration:
MinHeapFreeRatio = 0
MaxHeapFreeRatio = 100
MaxHeapSize = 4282384384 (4084.0MB)
NewSize = 89128960 (85.0MB)
MaxNewSize = 1427111936 (1361.0MB)
OldSize = 179306496 (171.0MB)
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 = 67108864 (64.0MB)
used = 64722984 (61.724647521972656MB)
free = 2385880 (2.2753524780273438MB)
96.44476175308228% used
From Space:
capacity = 11010048 (10.5MB)
used = 0 (0.0MB)
free = 11010048 (10.5MB)
0.0% used
To Space:
capacity = 11010048 (10.5MB)
used = 0 (0.0MB)
free = 11010048 (10.5MB)
0.0% used
PS Old Generation
capacity = 179306496 (171.0MB)
used = 0 (0.0MB)
free = 179306496 (171.0MB)
0.0% used
7197 interned Strings occupying 679784 bytes.
1.2 jmap(java memory map) 查看内存问题
1.2.1 jmap -histo (pid) >./log.txt
查看进程的内存信息,实例个数及所占空间
C:\Users\Administrator>jmap -histo 14136
num #instances #bytes class name
----------------------------------------------
1: 67958 35515848 [B
2: 95675 6862512 [C
3: 22976 5717688 [I
4: 68342 1640208 java.lang.String
5: 40269 1288608 java.util.HashMap$Node
6: 24330 973200 java.util.HashMap$KeyIterator
7: 11248 889968 [Ljava.util.HashMap$Node;
8: 11974 574752 java.util.HashMap
9: 12713 568792 [Ljava.lang.Object;
10: 7151 457664 java.util.regex.Matcher
11: 11897 409448 [Ljava.lang.String;
12: 10051 321632 sun.security.util.DerInputBuffer
13: 11023 264552 sun.security.util.DerInputStream
14: 7174 229568 sun.security.util.DerValue
15: 9527 228648 java.util.ArrayList
16: 9411 225864 sun.security.x509.X509AttributeName
17: 1843 211448 java.lang.Class
18: 9530 152480 java.util.HashSet
备注:
- num :序号
- instances: 实例数量
- bytes :占用空间大小
- class name :类名称([C is a char[],[S is a short[],[I is a int[],[B is a byte[])
1.2.2 jmap -dump:live,format=b,file=jvm.hprof (pid)
生成的jvm.hprof文件,可以下载下来放入jvisualvm.exe文件,来分析生成文件的时刻JVM内存的情况。更好的实践则是在环境中运行时,设置参数. -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./jvm.dump ,保证内存异常时,生产该文件以便分析异常的原因。
1.3 jstack 查看虚拟机栈问题
1.3.1 jstack 查找死锁
先找到运行进程的进程号,本机:5516 JstackFountDealLock。下方代码运行,线程0和线程1各自先锁住1个对象,5秒后再去锁另一个对象,此时会造成死锁。
public class JstackFountDealLock {
private static Object lock1 = new Object();
private static Object lock2 = new Object();
public static void main(String[] args) {
new Thread(()->{
synchronized (lock1){
System.out.println("锁对象lock1");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock2){
System.out.println("锁对象lock2");
}
}
}).start();
new Thread(()->{
synchronized (lock2){
System.out.println("锁对象lock2");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock1){
System.out.println("锁对象lock1");
}
}
}).start();
System.out.println("main线程结束");
}
}
查看Jstack 5516 ,省略其中无用信息。Found 1 deadlock.
2021-08-22 22:04:06
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.152-b16 mixed mode):
"Thread-1" #12 prio=5 os_prio=0 tid=0x000000001f04c800 nid=0x1048 waiting for monitor entry [0x000000001f9ee000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.huawei.jvm.JstackFountDealLock.lambda$main$1(JstackFountDealLock.java:40)
- waiting to lock <0x000000076b0a3308> (a java.lang.Object)
- locked <0x000000076b0a3318> (a java.lang.Object)
at com.huawei.jvm.JstackFountDealLock$$Lambda$2/2074407503.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
"Thread-0" #11 prio=5 os_prio=0 tid=0x000000001f04c000 nid=0x34a8 waiting for monitor entry [0x000000001f8ee000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.huawei.jvm.JstackFountDealLock.lambda$main$0(JstackFountDealLock.java:25)
- waiting to lock <0x000000076b0a3318> (a java.lang.Object)
- locked <0x000000076b0a3308> (a java.lang.Object)
at com.huawei.jvm.JstackFountDealLock$$Lambda$1/558638686.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
Found one Java-level deadlock:
=============================
"Thread-1":
waiting to lock monitor 0x00000000030fbb88 (object 0x000000076b0a3308, a java.lang.Object),
which is held by "Thread-0"
"Thread-0":
waiting to lock monitor 0x00000000030fe418 (object 0x000000076b0a3318, a java.lang.Object),
which is held by "Thread-1"
Java stack information for the threads listed above:
===================================================
"Thread-1":
at com.huawei.jvm.JstackFountDealLock.lambda$main$1(JstackFountDealLock.java:40)
- waiting to lock <0x000000076b0a3308> (a java.lang.Object)
- locked <0x000000076b0a3318> (a java.lang.Object)
at com.huawei.jvm.JstackFountDealLock$$Lambda$2/2074407503.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
"Thread-0":
at com.huawei.jvm.JstackFountDealLock.lambda$main$0(JstackFountDealLock.java:25)
- waiting to lock <0x000000076b0a3318> (a java.lang.Object)
- locked <0x000000076b0a3308> (a java.lang.Object)
at com.huawei.jvm.JstackFountDealLock$$Lambda$1/558638686.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
Found 1 deadlock.
用jvisualvm看也是一样的结果。
1.3.1 jstack 查看CPU飙升问题
1、准备环境
准备一个无限循环的方法,保持CPU不停运算。
public class Math4Cpu {
public static final int initData = 666;
public static User user = new User();
public int compute() {
//一个方法对应一块栈帧内存区域 12
int a = 1;
int b = 2;
int c = (a + b) * 10;
return c;
}
public static void main(String[] args) {
Math4Cpu math = new Math4Cpu();
while (true){
math.compute();
}
}
}
在linux中运行java的字节码文件
java com.asky.jvm.Math4Cpu
通过top命令 #实时查看系统运行情况,检测CPU、内存、进程等。发现此时PID:24400 的进程CPU占用高达97.3%
2、检查问题所在
top -p <pid> #(21508) 查看单进程的恶性西情况
查看当前进程的详细线程情况
按住shift+h —> H
拿到CPU占用超高的线程号PID 24401(十进制) —> 转化为十六进制 —> 5f51 (十六进制)
执行jstack查看
jstack 24400|grep -A 10 5f51 #jstack (进程pid) | grep -A 100 pid(java线程号)
从报错中的代码行数,可见端谜。
1.4 jinfo 查看系统属性
1.4.1 jinfo -flags pid 查看JVM启动命令
[root@VM-0-8-centos /]# jinfo -flags 26611
Attaching to process ID 26611, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.302-b08
Non-default VM flags: -XX:CICompilerCount=2 -XX:InitialHeapSize=31457280 -XX:MaxHeapSize=482344960 -XX:MaxNewSize=160759808 -XX:MinHeapDeltaBytes=196608 -XX:NewSize=10485760 -XX:OldSize=20971520 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops
Command line:
1.4.2 jinfo -sysprops pid 查看java系统参数
1.5 Jstat 最常用命令
jstat命令可以查看堆内存各部分的使用量,以及加载类的数量。
命令的格式如下: jstat [-命令选项] [vmid] [间隔时间(毫秒)] [查询次数]
注意:使用的jdk版本是jdk8
1.5.1 Jstat -gc pid 查看垃圾回收情况
1)单次查看gc回收情况
S0C :suvivor0区容量(单位KB)
S0U :suvivor0使用量
EC:Eden区容量
EU:Eden区使用量
OC:老年代容量
OU:老年代使用量
MC:元空间容量
MU:元空间使用量
CCSC:压缩类空间大小
CCUS:压缩类空间使用大小
YGC:Young gc自启动后执行的次数
YGCT:young gc耗费的时间,单位s
FGC:full gc的次数
FGCT:full gc耗费的时间,单位s
GCT:young gc和full gc话费的时间之和,单位s
[root@VM-0-8-centos /]# jstat -gc 26611
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
1024.0 1024.0 0.0 0.0 8192.0 507.9 20480.0 0.0 4480.0 875.6 384.0 76.6 0 0.000 0 0.000 0.000
2)每个1000毫秒运行1次,累计运行10次
stat -gc pid 1000 10
[root@VM-0-8-centos /]# jstat -gc 30343 1000 10
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
1024.0 1024.0 0.0 0.0 8192.0 507.9 20480.0 0.0 4480.0 875.6 384.0 76.6 0 0.000 0 0.000 0.000
1024.0 1024.0 0.0 0.0 8192.0 507.9 20480.0 0.0 4480.0 875.6 384.0 76.6 0 0.000 0 0.000 0.000
1024.0 1024.0 0.0 0.0 8192.0 507.9 20480.0 0.0 4480.0 875.6 384.0 76.6 0 0.000 0 0.000 0.000
1024.0 1024.0 0.0 0.0 8192.0 507.9 20480.0 0.0 4480.0 875.6 384.0 76.6 0 0.000 0 0.000 0.000
1024.0 1024.0 0.0 0.0 8192.0 507.9 20480.0 0.0 4480.0 875.6 384.0 76.6 0 0.000 0 0.000 0.000
1024.0 1024.0 0.0 0.0 8192.0 507.9 20480.0 0.0 4480.0 875.6 384.0 76.6 0 0.000 0 0.000 0.000
1024.0 1024.0 0.0 0.0 8192.0 507.9 20480.0 0.0 4480.0 875.6 384.0 76.6 0 0.000 0 0.000 0.000
1024.0 1024.0 0.0 0.0 8192.0 507.9 20480.0 0.0 4480.0 875.6 384.0 76.6 0 0.000 0 0.000 0.000
1024.0 1024.0 0.0 0.0 8192.0 507.9 20480.0 0.0 4480.0 875.6 384.0 76.6 0 0.000 0 0.000 0.000
1024.0 1024.0 0.0 0.0 8192.0 507.9 20480.0 0.0 4480.0 875.6 384.0 76.6 0 0.000 0 0.000 0.000
Full GC的频率应该控制在几个小时-几天发生/1次。