5. JVM调优工具详解及调优实战(这里有我的实战案例预制构件生产管理平台)
1. Jmap,Jstack,Jinfo命令详解
1.1 Jmap
此命令可以用来查看内存信息,实例个数以及占用内存大小
jps 先查看有哪些java程序
- jmap -histo 16492 > ./log.txt
- jmap -heap 16492
查看堆的信息
查看堆年轻代老年代的使用情况
- 堆内存dump (导一个快照出来)
jmap -dump:format=b,file=eureke.hprof 16492
这里生成了一个文件
然后我们使用jvisualvm
主要看这里
这里我们可以设置内存溢出自动导入dump文件(内存很大的时候,可能会导不出来)
- -XX:+HeapDumpOnOutOfMemoryError
- -XX:HeapDumpPath=./(路径)
这里生成了一个dump文件,将他载入jvisualvm
这里我们就可以看到user很多
1.2 Jstack
用Jstack加进程ID查找死锁
代码如下
pubilc class test{
private static Object lock1 = new Object();
private static Object lock2 = new Object();
public static void main(String[] args) {
new Thread(()->{
synchronized (lock1){
try {
System.out.println("thread1 begin");
Thread.sleep(5000);
}catch (InterruptedException e){
}
synchronized (lock2){
System.out.println("thread1 end");
}
}
}).start();
new Thread(()->{
synchronized (lock2){
try {
System.out.println("thread2 begin");
Thread.sleep(5000);
}catch (InterruptedException e){
}
synchronized (lock1){
System.out.println("thread2 end");
}
}
}).start();
System.out.println("main thread end");
}
}
这里就死锁了
这个是我死锁的线程
使用jstack
死锁的位置
这里对应代码的行数 有些许区别
用jvisualvm也可以识别死锁
- jstack找出CPU占用最高的堆栈信息
这里举个例子
package com.qm.boot.web.part.controller;
import com.qm.boot.web.admin.entity.SysUser;
public class Test {
public static final int initData = 666;
public static SysUser sysUser = new SysUser();
public int compute(){ //每一个方法对应一块栈帧内存区域
int a = 1;
int b = 1;
int c = (a+b)+10;
return c;
}
public static void main(String[] args) {
Test test = new Test();
while (true){
test.compute();
}
}
}
这个代码不断死循环,一定会让cpu变高
1.3Jinfo
查看正在运行的java程序的扩展参数
查看JVM参数
1.4 Jstat (用的最多的)
jstat 命令可以查看堆得各部分使用情况,以及加载类的数量
jstat -gc pid 最常用,可以评估程序内存使用及GC压力整体情况
- YGC :从启动开始执行的youngGc
- YGCT:从启动开始花费了多少秒
- FGC:从启动开始发生了多少次fullGc
- FGCT:从启动开始fullGc花费了多少秒
- GCT:youngGc和fullGc花费时间之和
jstat -gc 14904 1000 10
这里我们可以看到元空间基本被使用完了
这里有个问题 我们发现刚刚启动项目 我们发现做了35次minorJc 4次full Gc 那么肯定有问题,
那么我们怎么处理一下呢,
首先画一个内存模型
几乎实在20秒内,这肯定不可以,那么我们处理一下
- 我估计是开启了动态年轻判断机制,就是s0太小了 每次超过了50% 那么就会想old区域 放入数据,old 放满之后触发fullGC
- 那么我觉得可以调大新生代的内存 开始占了堆内存的3分之1 ,那么我调成三分之二,然后确实fullGC 没了
- 然后我估计为什么频繁的出发了minor Jc ,那么在调大点比例
这个方法可以修改-XX:NewRatio=4,表示新生代占1,老年代占4,新生代占整个堆的1/5,
当然开发人员可以通过选项“-XX :SurvivorRatio”调整这个空间比例。比如-XX : SurvivorRatio=8
然后扩大一下内存那么最后变成了
这是最后的调优参数
-Xmx1024M -Xms1024M -Xmn768M -Xss1M -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M