文章目录
一、JVM常用指令实例详解
前期准备:首先将提前准备的jar包启动起来,如下图示
1.1、Jmap
此JVM指令是查看当前指定进程ID的实例个数,以及占用的内存大小信息:如下图示
除此之外,可以查看指定进程ID堆的内存信息:如下图示
同时,也可以通过生成出dump文件,可以通过设置相关的运行参数:-Xms10M -Xmx10M -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:\jvm.dump方式生成文件,再导入到jvisualvm进行分析:
1.2、Jstack
此JVM是查看进程信息,如果CPU飙高,我们可以利用Jstack,如示例:
前期准备:
package com.practice.jvm;
public class HightCPUTest {
public int add() { //一个方法对应一块栈帧内存区域
int a = 1;
int b = 2;
int c = (a + b) * 10;
return c;
}
public static void main(String[] args) {
HightCPUTest hightCPUTest = new HightCPUTest();
while (true){
hightCPUTest.add();
}
}
}
操作的步骤为:
1、使用命令top -p pid ,显示java进程的内存情况,pid是java进程号,例如这里是6535:top -p 6535
2、按H,获取每个线程的内存情况,找到内存和cpu占用最高的线程tid,比如6536
3、将6536转为十六进制,因为此为线程id都是以十六进制表示==>1988
4、执行 jstack 6535|grep -A 20 1988,得到线程堆栈信息中1988 这个线程所在行的后面20行,从堆栈中可以发现导致cpu飙高的调用方法
5、查看对应的堆栈信息找出可能存在问题的代码
可以通过此指令分析进程死锁问题,如下图示:
1.3、Jinfo
JVM的jinfo指令可以查看JVM配置信息,如下图示:
1.4、Jstat
jstat指令可以查看堆内存各部分的使用量,以及加载类的数量信息,其指令格式如下:jstat [-命令选项] [vmid] [间隔时间(毫秒)] [查询次数],如下图示:
其中各个参数的含义如下:
- S0C:在JVM内存模型中,年轻代分为Survivor区域和Eden去,这个参数就是Survivor区域中的一个区,这个参数值表示Survivor其中一个区域占用的内存;
- S1C:这个参数值表示==>Survivor另外一个区域占用的内存;
- S0U和S1U:这两个参数值代表==>Survivor的两个区域使用的情况;
- EC和EU:这两个参数值代表==>新生代的Eden区分布情况和使用情况;
- OC和OU:这两个参数值代表==>老年代内存分布情况和使用情况;
- MC和MU:这两个参数值代表==>元空间内存分布情况和使用情况;
- CCSCC和CCSU:这两个参数值代表==>压缩类空间内存分布情况和使用情况;
- YGC和YGCT:这两个参数值代表==>表示程序启动后,YoungGC的次数和YoungGC的总时长信息;
- FGC和FGCT:这两个参数值代表==>表示程序启动后,FullGC的次数和FullGC的总时长信息;
- GCT:这两个参数值代表==>表示程序启动后,GC的总时长信息;
二、JVM优化思路(实例内容待更新)
2.1、JVM运行情况预估—年轻代对象增长的速率
可以使用jstat -gc pid 1000 2000查看堆栈的动态使用内存数据情况(表示每隔1000ms,需要将gc情况打印,需要打印两千次),再结合这些数据查看新生代和老年代的JVM内存使用情况,我们就可以大概知道新生代在每秒新增多少对象,如下图示:
2.2、JVM运行情况预估—Young GC的触发频率和每次的耗时
上一步知道了新生代在一秒新增多少对象后,我们就能根据eden区的大小推算出Young GC大概多久触发一次,Young GC的平均耗时可以通过 YGCT/YGC 公式算出,根据结果我们大概就能知道系统大概多久会因为Young GC的执行而卡顿多久。
2.3、JVM运行情况预估—每次Young GC后有多少对象存活和进入老年代
我们在之前的步骤中,已经知道了Young GC的频率,那结合这个频率,我们可以结合第一步,用相同的命令,指定时间,查看Eden区,Survivor区和老年代的内存变化情况,从而可以大概推断出老年代的对象增长速率==>在每次GC后Eden区的使用一般会减少,Survivor区和old区域可能会增长,增长的部分就是存活下来的对象
2.4、JVM运行情况预估—Full GC的触发频率和每次耗时
在上一步如果推断出老年代对象的增长速率,就可以推算出Full GC的触发频率,Full GC的每次耗时可以用公式 FGCT/FGC 计算得出
三、JVM优化示例(待更新)
四、小结
这章节我们是通过先引入JVM常见的命令,通过这些命令来查看应用程序在运行时,JVM内存的使用情况,特别是jstat命令,在优化时,经常会用和这个命令查看指定时间间隔的JVM内存使用情况,结合这些数据,推算出对象创建频率以及YoungGC和FullGC的频率,其实总的
优化思路其实简单来说:就是尽量让每次Young GC后的存活对象小于Survivor区域的50%,都留存在年轻代里。尽量别让对象进入老年代。尽量减少Full GC的频率,避免频繁Full GC对JVM性能的影响。