JVM常用命令汇总:
jps:
查看各个应用对应进程ID
Jmap:
查看内存信息,实例个数以及占用内存大小
jmap -heap 10200(进程ID)
查看堆信息
jmap -dump:format=b,file=dump.hprof 10200(进程ID)
手动转储堆内存信息
jvisualvm:
启动jvisualvm,使用JvisualVM工具查看堆信息
启动jvisualvm
装载dump文件
查看
内存溢出的时候自动打印转存堆栈
‐XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:\heapDump.dump
示例代码:
JVM设置:-Xms10M -Xmx10M -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:\heapDump.dump
import java.util.ArrayList;
import java.util.List;
public class TestAutoDump {
public static void main(String args[]) {
List<byte[]> lists = new ArrayList<>();
while(true) {
byte[] bytes = new byte[1000*1024];
lists.add(bytes);
}
}
}
// 运行结果如下:
[GC (Allocation Failure) [PSYoungGen: 1734K->488K(2560K)] 1734K->740K(9728K), 0.0007782 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 1548K->504K(2560K)] 1800K->1780K(9728K), 0.0008307 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 2541K->488K(2560K)] 3817K->3780K(9728K), 0.0009803 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 2534K->504K(2560K)] 5826K->5804K(9728K), 0.0006492 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Ergonomics) [PSYoungGen: 504K->0K(2560K)] [ParOldGen: 5300K->5601K(7168K)] 5804K->5601K(9728K), [Metaspace: 3200K->3200K(1056768K)], 0.0045009 secs] [Times: user=0.16 sys=0.00, real=0.01 secs]
[Full GC (Ergonomics) [PSYoungGen: 2044K->1000K(2560K)] [ParOldGen: 5601K->6601K(7168K)] 7645K->7601K(9728K), [Metaspace: 3202K->3202K(1056768K)], 0.0047187 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
[Full GC (Ergonomics) [PSYoungGen: 2006K->2000K(2560K)] [ParOldGen: 6601K->6597K(7168K)] 8607K->8597K(9728K), [Metaspace: 3209K->3209K(1056768K)], 0.0050641 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Allocation Failure) [PSYoungGen: 2000K->2000K(2560K)] [ParOldGen: 6597K->6579K(7168K)] 8597K->8579K(9728K), [Metaspace: 3209K->3209K(1056768K)], 0.0049375 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
java.lang.OutOfMemoryError: Java heap space
Dumping heap to D:\heapDump.dump ...
Heap dump file created [9656073 bytes in 0.018 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at TestAutoDump.main(TestAutoDump.java:9)
[Full GC (Ergonomics) [PSYoungGen: 2048K->0K(2560K)] [ParOldGen: 6619K->602K(7168K)] 8667K->602K(9728K), [Metaspace: 3240K->3240K(1056768K)], 0.0045889 secs] [Times: user=0.02 sys=0.02, real=0.02 secs]
Heap
PSYoungGen total 2560K, used 20K [0x00000000ffd00000, 0x0000000100000000, 0x0000000100000000)
eden space 2048K, 1% used [0x00000000ffd00000,0x00000000ffd05228,0x00000000fff00000)
from space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
to space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
ParOldGen total 7168K, used 602K [0x00000000ff600000, 0x00000000ffd00000, 0x00000000ffd00000)
object space 7168K, 8% used [0x00000000ff600000,0x00000000ff696b30,0x00000000ffd00000)
Metaspace used 3246K, capacity 4496K, committed 4864K, reserved 1056768K
class space used 353K, capacity 388K, committed 512K, reserved 1048576K
Jstack:
用来查找死锁
// 示例代码如下:
public class DeadLockTest {
public static void main(String args[]) {
new Thread(new Runnable() {
@Override
public void run() {
synchronized(A.class) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (B.class) {
}
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
synchronized(B.class) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (A.class) {
}
}
}
}).start();
}
}
class A {}
class B {}
jstack 运行结果日志如下:jstack 14452
2019-11-09 13:08:54
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.201-b09 mixed mode):
"DestroyJavaVM" #14 prio=5 os_prio=0 tid=0x0000000000f6e800 nid=0x17c8 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Thread-1" #13 prio=5 os_prio=0 tid=0x000000001e982800 nid=0x3cd4 waiting for monitor entry [0x000000002062f000]
java.lang.Thread.State: BLOCKED (on object monitor)
at DeadLockTest$2.run(DeadLockTest.java:33)
- waiting to lock <0x000000076b423028> (a java.lang.Class for A)
- locked <0x000000076b6b2778> (a java.lang.Class for B)
at java.lang.Thread.run(Thread.java:748)
"Thread-0" #12 prio=5 os_prio=0 tid=0x000000001e971800 nid=0x45bc waiting for monitor entry [0x000000002052f000]
java.lang.Thread.State: BLOCKED (on object monitor)
at DeadLockTest$1.run(DeadLockTest.java:16)
- waiting to lock <0x000000076b6b2778> (a java.lang.Class for B)
- locked <0x000000076b423028> (a java.lang.Class for A)
at java.lang.Thread.run(Thread.java:748)
......
若程序是在本地运行,则我们可以使用jvisualvm自动检测死锁
程序运行期间,使用命令jvisualvm打开工具
jstack找出占用CPU最高的堆栈信息
使用命令top -p 14552(java进程ID) 显示java的内存情况
按H,获取每个线程的内存情况,找到占用CPU最高的线程tid
转为十六进制得到 0x1371 ,此为线程id的十六进制表示
执行 jstack 4977|grep -A 10 1371,得到线程堆栈信息中1371这个线程所在行的后面10行
查看对应的堆栈信息找出可能存在问题的代码
Jinfo
查看正在运行的java应用程序的扩展参数
Jstat
jstat命令可以查看堆内存各部分的使用量,以及加载类的数量。
命令的格式如下:jstat [-命令选项] [vmid] [间隔时间(毫秒)] [查询次数]
jstat -gc pid 最常用,可以评估程序内存使用及GC压力整体情况
S0C:第一个幸存区的大小
S1C:第二个幸存区的大小
S0U:第一个幸存区的使用大小
S1U:第二个幸存区的使用大小
EC:伊甸园区的大小
EU:伊甸园区的使用大小
OC:老年代大小
OU:老年代使用大小
MC:方法区大小(元空间)
MU:方法区使用大小
CCSC:压缩类空间大小
CCSU:压缩类空间使用大小
YGC:年轻代垃圾回收次数
YGCT:年轻代垃圾回收消耗时间,单位s
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间,单位
sGCT:垃圾回收消耗总时间,单位s
可以持续观察内存各部分的变化趋势,以及Young GC 和Full GC的频率,判断堆里面各个区域(Eden区域,S0,S1区域,以及Old区域)内存大小的合理性
持续观察命令示例:
jstat -gc 10200 1000 100
观察线程10200的各个区域内存变化,以及GC情况,每一秒中打印一条日志,打印100次
优化思路其实简单来说就是尽量让每次Young GC后的存活对象小于Survivor区域的50%,都留存在年轻代里。尽量别让对象进入老年代。尽量减少Full GC的频率,避免频繁Full GC对JVM性能的影响
内存泄露:
指的是对象已经不再使用,但是还在内存里面占用空间,且垃圾收集机制,无法回收该内存空间
如何分析GC日志:
GC日志的获取:
应用程序配置自动转储GC信息:‐XX:+PrintGCDetails ‐XX:+PrintGCTimeStamps ‐XX:+PrintGCDateStamps ‐Xloggc:./gc.log
GC 日志在线分析工具https://gceasy.io/
分析GC日志免费,查看调优方案收费
分析结果如下图: