编写版本:v3.3.7
适用版本:所有版本
Jvm介绍
JVM内存区域的划分,年轻代和老年代,他们都发生gc行为,对应young gc(ygc)和full gc(fgc)
年轻代-ygc,程序不会挂起
eden-伊甸园,变量的出生地
s0-幸存代0,
s1-幸存代1,
以上三个都是年轻代的区域,无论哪个满了都会发生ygc行为,
eden是变量的出生地,发生ygc就会把还存在引用的变量转移到s0或s1,同时变量还有个类似年龄的值加1
s0或s1是变量的生活区,两者空间一样大,eden发生gc后的变量就转移到这里,但是两者有且只有一个在工作,
每当发生ygc,无论当前区域是否满都会把所有变量转移到另一区域,幸存代的所有变量年龄加1,当年龄增加到一定程度(默认为15岁),就将会被晋升到老年代中老年代-fgc,程序会挂起,等待gc完成
老年代只有一个区域,满了就会发生fgc,因为fgc的过程中导致程序挂起,必须降低发生次数
JVM调试
JVM调试工具-jvisulVM
jvisualVM,jdk自带工具,位置在${JAVA_HOME}/bin下,服务器和本地都要安装jdk,注意jre不包含该工具,jdk环境变量JAVA_HOME需要设置好,jdk9及以上的需要另外下载
- jvisualVM安装GC插件,插件界面如下图,插件安装步骤参考以下链接:
https://blog.csdn.net/dong_chl/article/details/93045620
调试模式
远程调试模式有两种,jmx和jstat模式,jmx稍微麻烦点,但能可以在jvisualVm中看到CPU的使用情况
jstat模式简介:
- 服务器上需要安装jdk,并在jdk的bin目录下创建jstatd.all.policy文件,需要全局变量设置有JAVA_HOME
文件内容如下:
grant codebase “file:${java.home}/lib/tools.jar” {
permission java.security.AllPermission “*”, “read,write”;
}; - 在bin目录下执行以下命令,hostname填入服务器ip
jstatd -J-Djava.security.policy=jstatd.all.policy -J-Djava.rmi.server.hostname=192.168.3.240 &
jstatd -J-Djava.security.policy=${JAVA_HOME}/bin/jstatd.all.policy -J-Djava.rmi.server.hostname=192.168.3.220 & - 启动jvisualVM,然后添加远程主机,输入服务器ip点击确定,最后选择目标应用
更加具体调试的信息请参考以下链接:
https://www.cnblogs.com/jhxxb/p/13279201.html
jmx模式简介:
- jvm启动添加参数”-Djava.rmi.server.hostname=192.168.3.220 -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=8050 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false”
- 启动jvisualVM,然后添加远程主机,输入服务器ip点击确定,右键主机添加JMX连接
- 双击”192.168.3.220:8050”进入应用监控界面
导出jvm Head Dump
jmap -dump:format=b,file=文件名.hprof 进程号
jmap -dump:format=b,file=business.20220104.hprof 899071
调试方式:控制变量法
通过执行同一段压力测试脚本,保持每次变量一致,然后改动一个内存参数,查看内存和gc时间的变化
- 调试建议:
- eden区域一直都会ygc,所以eden和gc time的图形应该是山峰式波形;
- eden、s0、s1无论是哪个满了都会发生ygc,导致年轻代变量的年龄加一;
- s0和s1应该关注最大值和当前使用最大值,如果当前没有达到最大值,而老年代一直增加,说明gc过于频繁导致变量年龄过快增长,那需要检查年轻代空间过小或者事务过长导致;
- 老年代的full gc不应该很频繁甚至应该没有,每次发生的间隔最好以天为单位。
Jvm参数
以下是常用的参数,加在jar的运行命令中
性能参数
• -XX:NewRatio=2 新生代内存容量与老生代内存容量的比例
• -XX:SurvivorRatio=8 新生代eden和s0内存容量的比例,jdk8默认是3
• -Xms等价于-XX:InitialHeapSize初始化堆内存大小
• -Xmx等价于-XX:MaxHeapSize最大的堆内存大小
• -Xmn等价于-XX:NewSize=size设置初始的年轻代的大小
调试参数
• -XX:-CITime 打印消耗在JIT编译的时间
• -XX:ErrorFile=./hs_err_pid
• -XX:HeapDumpPath=./java_pid
• -XX:-HeapDumpOnOutOfMemoryError 当首次遭遇OOM时导出此时堆中相关信息
• -XX:-PrintGC 每次GC时打印相关信息
• -XX:-PrintGC Details 每次GC时打印详细信息
• -XX:-PrintGCTimeStamps 打印每次GC的时间戳
更详细参数请看以下链接:
https://docs.oracle.com/javase/8/docs/technotes/tools/windows/java.html