事先本地启动一个web应用,通过jps查看其进程id,接着用各种jdk自带命令优化应用
JMap
查看内存信息,实例个数及占用内存大小
打开log.txt,内容如下:
- num:序号
- instances:实例数量
- bytes:占用空间大小
- class name:类名称,[C is a char[], [S is a short[], [I is a int[], [B is a byte[], [[I is a int [][]
堆信息
堆内存dump
jmap -dump:format=b,file=eureka.hprof 26584
也可以通过添加环境参数设置内存溢出自动导出dump文件(内存很大的时候,可能会导不出)
- -XX:+HeapDumpOnOutOfMemoryError
- -XX:HeapDumpPath=./ (路径)
实例代码
// jvm设置
// -Xms10M
// -Xmx10M
// -XX:+PrintGCDetails
// -XX:+HeapDumpOnOutOfMemoryError
// -XX:HeapDumpPath=D:\jvm.dump
public class OOMTest {
public static List<Object> list = new ArrayList<>();
public static void main(String[] args) {
List<Object> objects = new ArrayList<>();
int i = 0;
int j = 0;
while (true){
list.add(new User(UUID.randomUUID().toString(),i++));
new User(UUID.randomUUID().toString(), j--);
}
}
}
可以通过jvisualvm命令工具装入该dump文件分析
Jstack
用jstack加进程id查找死锁,见如下示例
Thread2:线程名
prio=5 优先级=5
tid =0x00000296c0107800 线程16进制id
nid = 0x3870 线程对应本地线程标识nid
java.lang.Thread.State:BLOCKED线程状态
可以通过jvisualVM自动检测死锁
Jstack找出占用CPU最高的线程堆栈信息
1、使用命令top -p ,显示你的java进程的内存情况,pid是你的java进程号,比如196632、按H,获取每个线程的内存情况
3,找到内存和cpu占用最高的线程tid,比如19664
4,转为十六进制得到 0x4cd0,此为线程id的十六进制表示
5,执行 jstack 19663|grep -A 10 4cd0,得到线程堆栈信息中 4cd0 这个线程所在行的后面10行,从堆栈中可以发现导致cpu飙高的调用方法
Jinfo
查看正在运行的Java应用程序的扩展参数
查看Java系统参数
jinfo -sysprops pid
Jstat
Jstat命令可以查看堆内存各部分的使用量,以及加载类的数量。命令的格式如下:
jstat [-命令选项] [vmid] [间隔时间(毫秒)][查询次数]
垃圾回收统计
jstat -gc pid最常用,可以评估程序内存使用及GC压力整体情况
- S0C:第一个幸存区的大小,单位KB
- S1C:第二个幸存区的大小
- S0U:第一个幸存区的使用大小
- S1U:第二个幸存区的使用大小
- EC:Eden区的大小
- EU:Eden区的使用大小
- OC:老年代大小
- OU:老年代的使用大小
- MC:元空间的大小
- MU:元空间的使用大小
- CCSC:压缩类空间大小
- CCSU:压缩类控件使用大小
- YGC:年轻代回收次数
- YGCT:年轻代回收消耗时间,单位s
- FGC:老年代回收次数
- FGCT:老年代垃圾回收消耗时间,单位s
- GCT:垃圾回收消耗总时间,单位s
堆内存统计
- NGCMN:新生代最小容量
- NGCMX:新生代最大容量
- NGC:当前新生代容量
- S0C:第一个幸存区大小
- S1C:第二个幸存区的大小
- EC:伊甸园区的大小
- OGCMN:老年代最小容量
- OGCMX:老年代最大容量
- OGC:当前老年代大小
- OC:当前老年代大小
- MCMN:最小元数据容量
- MCMX:最大元数据容量
- MC:当前元数据空间大小
- CCSMN:最小压缩类空间大小
- CCSMX:最大压缩类空间大小
- CCSC:当前压缩类空间大小
- YGC:年轻代gc次数
- FGC:老年代GC次数