我所使用的生产 Java 17 启动参数

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 我所使用的生产 Java 17 启动参数
JVM 参数升级提示工具:jacoline.dev/inspectJVM 参数词典: chriswhocodes.comRevolut(英国支付巨头)升级 Java 17 实战: https://www.bilibili.com/video/bv1SA4y1d7sZ

目前正常微服务综合内存占用+延迟+吞吐量,还是 G1 更优秀。但是如果你的微服务本身压力没到机器极限,要求延迟低,那么 ZGC 最好。如果你是实现数据库那样的需求(大量缓存对象,即长时间生存对象,老年代很大,并且还会可能分配大于区域的对象),那么必须使用 ZGC。

使用 G1GC 启动参数:

-XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:-OmitStackTraceInFastThrow -Xlog:gc*=debug:file=${LOG_PATH}/gc%t.log:utctime,level,tags:filecount=50,filesize=100M -Xlog:jit+compilation=info:file=${LOG_PATH}/jit_compile%t.log:utctime,level,tags:filecount=10,filesize=10M -Xlog:safepoint=debug:file=${LOG_PATH}/safepoint%t.log:utctime,level,tags:filecount=10,filesize=10M -Dfile.encoding=UTF-8 -Djava.security.egd=file:/dev/./urandom -Dnetworkaddress.cache.ttl=10 -Xms2048m -Xmx2048m -Xmn1280m -Xss512k -XX:MaxDirectMemorySize=1024m -XX:MetaspaceSize=384m -XX:ReservedCodeCacheSize=256m -XX:+DisableExplicitGC -XX:MaxGCPauseMillis=50 -XX:-UseBiasedLocking -XX:GuaranteedSafepointInterval=0 -XX:+UseCountedLoopSafepoints -XX:+SafepointTimeout -XX:SafepointTimeoutDelay=1000 -XX:StartFlightRecording=disk=true,maxsize=4096m,maxage=3d -XX:FlightRecorderOptions=maxchunksize=128m --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED --add-opens java.base/java.math=ALL-UNNAMED --add-opens java.base/java.net=ALL-UNNAMED --add-opens java.base/java.nio=ALL-UNNAMED --add-opens java.base/java.security=ALL-UNNAMED --add-opens java.base/java.text=ALL-UNNAMED --add-opens java.base/java.time=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/jdk.internal.access=ALL-UNNAMED --add-opens java.base/jdk.internal.misc=ALL-UNNAMED

使用 ZGC 启动参数:

-XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:-OmitStackTraceInFastThrow -Xlog:gc*=debug:file=${LOG_PATH}/gc%t.log:utctime,level,tags:filecount=50,filesize=100M -Xlog:jit+compilation=info:file=${LOG_PATH}/jit_compile%t.log:utctime,level,tags:filecount=10,filesize=10M -Xlog:safepoint=debug:file=${LOG_PATH}/safepoint%t.log:utctime,level,tags:filecount=10,filesize=10M -Dfile.encoding=UTF-8 -Djava.security.egd=file:/dev/./urandom -Dnetworkaddress.cache.ttl=10 -Xms2048m -Xmx2048m -Xmn1280m -Xss512k -XX:MaxDirectMemorySize=1024m -XX:MetaspaceSize=384m -XX:ReservedCodeCacheSize=256m -XX:+DisableExplicitGC -XX:+UseZGC -XX:-UseBiasedLocking -XX:GuaranteedSafepointInterval=0 -XX:+UseCountedLoopSafepoints -XX:+SafepointTimeout -XX:SafepointTimeoutDelay=1000 -XX:StartFlightRecording=disk=true,maxsize=4096m,maxage=3d -XX:FlightRecorderOptions=maxchunksize=128m --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED --add-opens java.base/java.math=ALL-UNNAMED --add-opens java.base/java.net=ALL-UNNAMED --add-opens java.base/java.nio=ALL-UNNAMED --add-opens java.base/java.security=ALL-UNNAMED --add-opens java.base/java.text=ALL-UNNAMED --add-opens java.base/java.time=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/jdk.internal.access=ALL-UNNAMED --add-opens java.base/jdk.internal.misc=ALL-UNNAMED

其中,需要做成环境变量外部可以配置的是:

  • -Xms2048m -Xmx2048m -Xmn1280m -Xss512k -XX:MaxDirectMemorySize=1024m -XX:MetaspaceSize=384m -XX:ReservedCodeCacheSize=256m 里面的参数
  • -XX:StartFlightRecording=disk=true,maxsize=4096m,maxage=3d 其中的 4096m 以及 3d
  • -XX:MaxGCPauseMillis=50:这个只有使用 G1GC 的需要


JVM 日志相关:


JVM 日志配置请参考:https://zhuanlan.zhihu.com/p/111886882

0. 需要异步输出日志,防止卡死 JVM:-Xlog:async

  1. GC日志:-Xlog:gc*=debug:file=${LOG_PATH}/gc%t.log:utctime,level,tags:filecount=50,filesize=100M
  2. JIT 编译日志:-Xlog:jit+compilation=info:file=${LOG_PATH}/jit_compile%t.log:utctime,level,tags:filecount=10,filesize=10M
  3. Safepoint 日志:-Xlog:safepoint=debug:file=${LOG_PATH}/safepoint%t.log:utctime,level,tags:filecount=10,filesize=10M
  4. 关闭堆栈省略:这个只会省略 JDK 内部的异常,比如 NullPointerException 这种的:-XX:-OmitStackTraceInFastThrow,我们应用已经对于大量报错的时候输出大量堆栈导致性能压力的优化,参考:https://zhuanlan.zhihu.com/p/428375


系统属性(环境变量)启动参数:


  1. -Dfile.encoding=UTF-8:指定编码为 UTF-8,其实 Java 18 之后默认编码就是 UTF-8 了,这样避免不同操作系统编译带来的差异(Windows 默认是 GB2312,Linux 默认是 UTF-8),参考:https://openjdk.java.net/jeps/400
  2. -Djava.security.egd=file:/dev/./urandom:更换 random 为 urandom 避免高并发加密证书通信的时候的生成随机数带来的阻塞(例如高并发 https 请求,高并发 mysql 连接通信),参考:https://zhuanlan.zhihu.com/p/259874076
  3. -Dnetworkaddress.cache.ttl=10:将 DNS 缓存降低为 10s 过期,咱们 k8s 内部有很多通过域名解析的资源(通过 k8s 的 coreDNS),解析的 ip 可能会过期,漂移成新的 ip,默认的 30s 有点久,改成 10s,但是这会增加 coreDNS 的压力。


内存控制相关:


以下需要做成可以在外部配置的环境变量

  1. 堆内存控制:-Xms2048m -Xmx2048m -Xmn1280m
  2. 线程栈大小控制:-Xss512k
  3. 直接内存(各种 Direct Buffer)大小控制:-XX:MaxDirectMemorySize=1024m
  4. 元空间控制:-XX:MetaspaceSize=384m
  5. JIT 即时编译后(C1 C2 编译器优化)的代码占用内存:-XX:ReservedCodeCacheSize=256m

除了以上内存,JVM 还有其他内存占用,无法通过显示的配置限制,参考:https://www.zhihu.com/question/58943470/an

swer/2440458704

GC 控制相关:


通用参数:

  1. -XX:+DisableExplicitGC:关闭显示 GC(System.gc()触发的 FullGC),防止 netty 这种误检测内存泄漏显示调用

G1GC 参数:

Java 9 之后默认 GC 就是 G1GC,所以不用显示指定使用 G1GC

在 Java 14 之后 G1GC 有巨大突破,目前 Java 17 中已经不需要调非常复杂的参数了,可以只调整目标最大 STW(Stop-the-world) 时间来均衡 CPU 占用,内存占用与延迟。

  1. -XX:MaxGCPauseMillis=50:目标最大 STW(Stop-the-world) 时间,这个越小,GC 占用 CPU 资源,占用内存资源就越多,微服务吞吐量就越小,但是延迟低。这个需要做成可配置的

ZGC 参数:

ZGC 不用调优,是自适应的

  1. -XX:+UseZGC:使用 ZGC


安全点控制


关于安全点,可以查看这篇文章:https://zhuanlan.zhihu.com/p/161710652

  1. -XX:-UseBiasedLocking:禁用偏向锁,偏向锁其实未来会被完全移除(参考:),目前咱们都是高并发的环境,偏向锁基本没啥用并且还有负面影响
  2. -XX:GuaranteedSafepointInterval=0:禁用定时安全点任务,没必要,咱们不是那种热点代码经常改变,资源珍贵的场景,并且如果是 ZGC 本身就会定时进入安全点进行 GC 检查,更没必要了
  3. -XX:+UseCountedLoopSafepoints:防止大有界循环带来的迟迟不进入安全点导致 GC STW 时间过长
  4. -XX:+SafepointTimeout -XX:SafepointTimeoutDelay=1000:防止其他情况下导致进入安全点时间过长导致 STW 时间过长,这里配置的是 1s。但是没有指定 AbortVMOnSafepointTimeout 为 true,所以对你的 jmap 以及 jstack 命令没有影响


JFR 配置


JFR 使用请参考:https://zhuanlan.zhihu.com/p/161710652

-XX:StartFlightRecording=disk=true,maxsize=4096m,maxage=3d -XX:FlightRecorderOptions=maxchunksize=128m


模块化限制


--add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED --add-opens java.base/java.math=ALL-UNNAMED --add-opens java.base/java.net=ALL-UNNAMED --add-opens java.base/java.nio=ALL-UNNAMED --add-opens java.base/java.security=ALL-UNNAMED --add-opens java.base/java.text=ALL-UNNAMED --add-opens java.base/java.time=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/jdk.internal.access=ALL-UNNAMED --add-opens java.base/jdk.internal.misc=ALL-UNNAMED

Java 16 将 --illegal-access 的默认值从 permit 改成了 deny (JEP: https://openjdk.java.net/jeps/396),Java 17 直接移除了这个选项 (JEP: https://openjdk.java.net/jeps/403),所以现在要打破模块化封装,必须通过这个命令具体打破某些模块向某些模块的暴露。这里包含了一些常用的可能会被反射访问的 java.base 下的 package,向所有未命名模块暴露(我们自己的项目一般不会指定模块名,如果你指定了就换成具体你的模块名)

这个也能从下面的报错中看出:

Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to unnamed module @7586beff

现在启动参数配置有点复杂,没法指定某个模块下的所有包都向某个模块暴露,并且未来也没有这个打算,参考:https://jigsaw-dev.openjdk.java.narkive.com



相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
5月前
|
Java
解析Java线程池:参数详解与执行流程
解析Java线程池:参数详解与执行流程
58 1
|
4月前
|
Java API 编译器
Java编译器注解运行和自动生成代码问题之编译时通过参数设置选项值问题如何解决
Java编译器注解运行和自动生成代码问题之编译时通过参数设置选项值问题如何解决
|
4月前
|
缓存 安全 算法
Java面试题:如何通过JVM参数调整GC行为以优化应用性能?如何使用synchronized和volatile关键字解决并发问题?如何使用ConcurrentHashMap实现线程安全的缓存?
Java面试题:如何通过JVM参数调整GC行为以优化应用性能?如何使用synchronized和volatile关键字解决并发问题?如何使用ConcurrentHashMap实现线程安全的缓存?
45 0
|
1月前
|
存储 算法 Java
java制作海报六:Graphics2D的RenderingHints方法参数详解,包括解决文字不清晰,抗锯齿问题
这篇文章是关于如何在Java中使用Graphics2D的RenderingHints方法来提高海报制作的图像质量和文字清晰度,包括抗锯齿和解决文字不清晰问题的技术详解。
38 0
java制作海报六:Graphics2D的RenderingHints方法参数详解,包括解决文字不清晰,抗锯齿问题
|
1月前
|
Java
java构造方法时对象初始化,实例化,参数赋值
java构造方法时对象初始化,实例化,参数赋值
48 1
|
3月前
|
Java
【Azure 应用服务】如何查看App Service Java堆栈JVM相关的参数默认配置值?
【Azure 应用服务】如何查看App Service Java堆栈JVM相关的参数默认配置值?
【Azure 应用服务】如何查看App Service Java堆栈JVM相关的参数默认配置值?
|
3月前
|
消息中间件 Java 大数据
"深入理解Kafka单线程Consumer:核心参数配置、Java实现与实战指南"
【8月更文挑战第10天】在大数据领域,Apache Kafka以高吞吐和可扩展性成为主流数据流处理平台。Kafka的单线程Consumer因其实现简单且易于管理而在多种场景中受到欢迎。本文解析单线程Consumer的工作机制,强调其在错误处理和状态管理方面的优势,并通过详细参数说明及示例代码展示如何有效地使用KafkaConsumer类。了解这些内容将帮助开发者优化实时数据处理系统的性能与可靠性。
88 7
|
3月前
|
C# 开发者 Windows
震撼发布:全面解析WPF中的打印功能——从基础设置到高级定制,带你一步步实现直接打印文档的完整流程,让你的WPF应用程序瞬间升级,掌握这一技能,轻松应对各种打印需求,彻底告别打印难题!
【8月更文挑战第31天】打印功能在许多WPF应用中不可或缺,尤其在需要生成纸质文档时。WPF提供了强大的打印支持,通过`PrintDialog`等类简化了打印集成。本文将详细介绍如何在WPF应用中实现直接打印文档的功能,并通过具体示例代码展示其实现过程。
292 0
|
4月前
|
存储 Java
java 服务 JVM 参数设置配置
java 服务 JVM 参数设置配置
148 3
|
3月前
|
缓存 前端开发 Java
【Azure 应用服务】App Service 使用Tomcat运行Java应用,如何设置前端网页缓存的相应参数呢(-Xms512m -Xmx1204m)?
【Azure 应用服务】App Service 使用Tomcat运行Java应用,如何设置前端网页缓存的相应参数呢(-Xms512m -Xmx1204m)?