目录
参考资料:
JDK工具官网文档:
Java Development Kit Version 17 Tool Specifications
JDK17 java指令官网文档:
JDK8 java指令官网文档:
https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html
1 JVM有哪些参数可以调
1.1 标准参数
- 以-开头,所有HotSpot都支持
- 使用java -help或者java -?查看
- 常用的标准参数
- --list-modules:查看当前Java进程中的模块
- --show-module-resolution:查看当前Java进程中各个模块的依赖关系
- -verbose:class:显示类加载信息
- -verbose:gc:显示GC事件
1.2 非标准参数
- 以-X开头,特定HotSpot版本支持的指令
- 使用java -X查看
- 这类参数一般比较稳定,除非有重大版本升级,一般不会有太大变化
- 常用的非标准参数
- -Xms:堆空间大小
- -Xmx:堆空间最大大小
- -Xint:采用解释执行
- -Xcomp:采用编译执行
- -Xmixed:两种执行引擎混合方式执行
1.3 不稳定参数
- 以-XX开头,此类参数数量最多
- 这些参数是跟特定的HotSpot版本对应的,容易变动
- 查看最终生效的不稳定指令 java -XX:+PrintFlagsFinal -version
- 查看默认的不稳定指令java -XX:+PrintFlagsInitial -version
- 当前命令的不稳定指令java -XX:+PrintCommandLineFlags -version
- 对于数值类型参数,通过 -XX:参数名=值,设置值
- 对于Boolean类型参数,通过 -XX:+/-参数名,设置值,+代表开启,-代表关闭
2 从开源框架学习GC调优
- 可以观察一些开源java中间件服务在启动时JVM参数如何调整的
- 从而调制自己系统特有的JVM参数
- 整体分为如下三方面
- 调整内存布局
- 选择具体的GC垃圾回收器,并定制少部分GC参数
- 打印GC日志
3 基于JDK17优化JVM内存布局
- jvm整体内存布局如下
- 堆区是JVM管理内存最大的一块,只要用于存放各种对象实例,GC活动的主要区域
- 堆内存的管理方式,由于垃圾回收器的不同,从而有很大差距
3.1 定制堆内存大小
- 堆内存的大小决定了JAVA程序执行的性能
- 更大的内存,能存下更多的对象,但是随之带来的是GC线程的压力
堆内存的主要参数
- -Xms:堆内存的初始大小
- 默认单位是bytes,必须为1024的整数,并且大于1M
- 其数据后面可以跟内存单位,KB,MB,GB等
- 如果不设置该值时,JVM会默认将堆内存初始大小设置为老年代和年轻代的内存之和
- 也可通过参数-XX:InitalHeapSize设置
- -Xmx:设置堆内存的最大大小
- 默认值为运行是操作系统位数以及物理内存大小自行决定
- 也可通过参数-XX:MaxHeapSize设置
- 通常部署服务时将最大内存和初始内存设置为相同的值,避免jvm在运行过程中内存动态伸缩的性能损耗
- -XX:MinHeapFreeRatio:GC后所允许的堆空间的最⼩比例。如果剩余的堆空间降落到这个阈值之下,这时堆空间就会启动⼀次扩充。
- -XX:MinHeapSize:GC后所允许的堆空间的最⼩值。如果剩余的堆空间降落到这个阈值之下,这时堆空间就会启动⼀次扩充。
3.2 设置非堆空间
3.2.1 设置元空间
- MetaSpace元空间主要存储的是类元信息,运行时常量池,方法字节码等
- 类的元信息包括类的结构信息,如字段,方法,注释等
- MetaSpace直接使用本地内存
- -XX:MetaspaceSize:元空间大小
- 当元空间使用大小超过该阈值时,就会触发一次GC
- 后续运行过程中,触发GC的阈值会根据元空间使用情况自动调整
- -XX:MaxMetaspaceSize:元空间最大值
- 设置元空间大小的最大值,默认元空间是无限的
- 元空间的大小取决于应用本身以及操作系统可提供的内存大小
- 元空间的数据大小不应该经常发生变动
3.2.2 设置线程栈空间
- JAVA进程在运行是,会为每一个线程开辟一块内存,用来执行线程中对应的指令
- 线程中执行的每一个方法对应栈空间中的一个方法栈
- 方法栈中主要包含了程序计数器,操作数栈,局部变量表,返回地址等几个标准部分
- 另外具体的虚拟机实现还会添加一些附加信息,例如HotSpot添加了动态链接库以及一些自定义的附加信息
- 线程栈空间会随着方法结束而释放
- -Xss:设置线程栈空间大小
- Linux和MacOS系统中默认值为1MB,Windows中根据配置的虚拟内存大小决定
- 也可通过参数-XX:ThreadStackSize配置
3.2.3 设置热点代码缓存空间
- java中,-server表示JVM以服务器模式运行
- 在服务器模式下,HotSpot虚拟机会将执行频率高的热点代码识别出来,
- 提前进行编译,并将编译结果缓存,后续执行时,会以编译方式直接执行编译好的代码
- -XX:InitialCodeCacheSIze=size:设置代码缓存空间初始大小
- -XX:ReservedCodeSize=size:设置代码缓存空间的最大大小
- 默认值为240MB
- 禁止提前编译时(-XX:-TiereadCompilation)默认值为48MB
- -XX:+SegmentedCodeCache:启用代码缓存分割
- jdk17新增参数,主要作用是优化代码缓存空间的内存使用
- 开启该参数时,需要启用提前编译-XX:+TieredCompilation并且-XX:ReservedCodeCacheSIze >= 240MB
3.2.4 应用程序类数据分享
- Application Class Data Sharing(应用程序列数据共享)
- 旨在提高运行相同代码的多个JVM启动时间,并减少他们的内存占用的一种优化机制
- 在JVM第一次启动时,将加载过的类数据收集归档到指定文件中
- 之后JVM启动时,优先从该文件中加载类,可以节省JVM初始化过程中的时间和资源
#将类信息归档到hello.jsa文件中
java -Xshare:dump -XX:SharedArchiveFile=hello.jsa -version
#使用归档文件启动,并打印加载日志
java -XX:SharedArchiveFile=hello.jsa -Xlog:class+load -version
- 归档类信息
- 启动JVM时读取归档文件
4 基于JDK17定时JVM的GC参数
4.1 G1 gc参数
- G1的内存模型
- G1 GC是一种分代,并发的,基于区域的垃圾回收器
- G1将内存划分为了多个独立的区域(Region)
- 每个Region可以是Eden区,Survivor区或者Old区,并且每个Region是属于哪个分代是随着GC变化的
- 为了保证系统的响应性,G1 GC会尽量在达到用户设定的停顿时间目标前进行垃圾回收
- 目标停顿时间由参数-XX:MaxGCPauseMillis设置,默认200ms
G1 gc的核心参数
- -XX:UseG1GC:启用g1
- -Xmx:堆内存大小
- -XX:MaxGCPauseMillils:期望G1达到的最大停顿时间,默认200ms
- -XX:G1HeapRegionSize=size:设置每个region的大小
- 必须是2的N次幂,并且范围在1MB~32MB之间
- 默认值=堆内存大小/2048
- 较大的Region区域可以减少GC的频率,但是会影响单次GC的耗时
- -XX:G1ReservePercent=percent
- 预留多少比例的堆空间作为空闲,避免内存突增从而发生OOM的问题
- 默认值10%
- -XX:InitiatingHeapOccupancyPercent=precent
- 默认值45
- 当region的使用达到该阈值是,G1就会开始并发标记周期
- -XX:+/-G1UseAdaptivelHOP:是否自动调整触发GC的阈值
- 开启时,前面几次gc会按照预设的阈值触发gc,后续根据系统运行情况动态调整该值
- -XX:G1AdaptiveIHOPNumInitialSamples:表示根据预设的阈值触发gc的次数
- 默认为3
- -XX:ParallelGCThreads=num:设置gc的工作线程数
- 默认值取决于CPU核心数
- -XX:G1HeapWastePercent=percent:设置堆空间的浪费比例
- HotSpot在堆空间使用比例低于这个值时不会启动GC
- 默认值5%
- -XX:G1OldSetRegionThresholdPercent=percent
- 设置一次混合GC中需要经历的old区的内存比例
- 默认是堆空间的10%
- 调大该值会降低gc执行的频率,但是会延长每一次gc执行的时间
- -XX:G1MixedGCCountTarget=number
- 设置G1垃圾回收器的线程上限
- HotSpot会为了达到清理目标内存比例的目的,自动计算需要启动的G1回收器,但是上限不会超过该值,
- 默认是8
4.2 ZGC gc参数
- ZGC的设计更多的会根据运行环境而自适应的调整运行参数
- 因此,只需要启用ZGC并且指定堆大小即可
5 GC日志处理
- 配置打印gc日志
-Xlog:gc*:file=${GC_LOG_DIR}/rmq_srv_gc_%p_%t.log:time,tags:filecount=5,filesize=30M
- gc日志分析平台
Universal JVM GC analyzer - Java Garbage collection log analysis made easy