JVM参数升级提示工具:jacoline.dev/inspectJVM参数字典:chriswhocodes.comRevolut(英国支付巨头)升级Java17实战:https://www.bilibili.com/vide...目前,普通微服务的综合内存占用+延迟+吞吐量还是优于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:-UseBiasedInterfeantSize=50-XX:-UseBiasedInterfeantLocking参数0-XX:+UseCountedLoopSafepoints-XX:+SafepointTimeout-XX:SafepointTimeoutDelay=1000-XX:StartFlightRecording=disk=true,maxsize=4096m,maxage=3d-XX:FlightRecorderOptions=maxchunksize=128m--添加打开java.base/java.lang=ALL-UNNAMED--add-opensjava.base/java.io=ALL-UNNAMED--add-opensjava.base/java.math=ALL-UNNAMED--add-opensjava.base/java.net=ALL-UNNAMED--add-opensjava.base/java.nio=ALL-UNNAMED--add-opensjava.base/java.security=ALL-UNNAMED--add-opensjava.base/java.text=ALL-UNNAMED--add-opensjava.base/java.time=ALL-UNNAMED--add-opensjava.base/java.util=ALL-UNNAMED--add-opensjava.base/jdk.internal.access=ALL-UNNAMED--add-opensjava.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-opensjava.base/java.lang=ALL-未命名--add-opensjava.base/java.io=ALL-UNNAMED--add-opensjava.base/java.math=ALL-UNNAMED--add-opensjava.base/java.net=ALL-UNNAMED--add-opensjava.base/java.nio=ALL-UNNAMED--add-opensjava.base/java.security=ALL-UNNAMED--add-opensjava.base/java.text=ALL-UNNAMED--add-打开java.base/java.time=ALL-UNNAMED--add-opensjava.base/java.util=ALL-UNNAMED--add-opensjava.base/jdk.internal.access=ALL-UNNAMED--add-opensjava.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/...需要异步输出日志,防止JVM卡死:-Xlog:asyncGClog:-Xlog:gc*=debug:file=${LOG_PATH}/gc%t.log:utctime,level,tags:filecount=50,filesize=100MJIT编译日志:-Xlog:jit+compilation=info:file=${LOG_PATH}/jit_compile%t。log:utctime,level,tags:filecount=10,filesize=10MSafepointlog:-Xlog:safepoint=debug:file=${LOG_PATH}/safepoint%t.log:utctime,level,tags:filecount=10,filesize=10M关闭stackomission:这样只会省略JDK内部的异常,比如NullPointerException:-XX:-OmitStackTraceInFastThrow,我们的应用在大量报错的时候已经输出了大量的stack,导致性能压力优化,参考:https://zhuanlan.zhihu.com/p/...系统属性(环境变量)启动参数:-Dfile.encoding=UTF-8:指定编码为UTF-8。其实Java18之后默认的编码是UTF-8,这样可以避免不同的操作由于系统编译造成的差异(Windows默认为GB2312,Linux默认为UTF-8),参考:https://openjdk.java.net/jeps...-Djava.security.egd=file:/dev/./urandom:将random替换为urandom避免高并发加密证书通信(如高并发https请求、高并发mysql连接通信)时产生随机数造成的阻塞,参考:https://zhuanlan.zhihu.com/p/...-Dnetworkaddress.cache.ttl=10:减少DNS缓存在10s后过期。k8s内部我们有很多域名解析资源(通过k8s的coreDNS)。解析出来的ip可能会过期,漂移到新的ip。默认的30s有点长。改成10s,但是这样会增加coreDNS的压力内存控制相关:下面需要做成环境变量可以外部配置:堆内存控制:-Xms2048m-Xmx2048m-Xmn1280m线程栈大小控制:-Xss512k直接内存(各种DirectBuffer)大小控制:-XX:MaxDirectMemorySize=1024mMetaspace控制:-XX:MetaspaceSize=384mJIT即时编译(C1C2编译优化)代码占用内存:-XX:ReservedCodeCacheSize=256m除以上memory,JVM有其他Memory占用,无法通过显示配置限制,参考:https://www.zhihu.com/questio...GC控制相关:通用参数:-XX:+DisableExplicitGC:DisabledisplayGC(由System.gc()FullGC触发)以防止netty误检测内存泄漏。显示调用G1GC参数:Java9之后,默认GC为G1GC,不需要指定使用G1GC。在Java14之后,G1GC有了巨大的突破。目前Java17不需要调整很复杂的参数,你可以只调整目标最大STW(Stop-the-world)时间来平衡CPU占用、内存占用和延迟。-XX:MaxGCPauseMillis=50:目标最大STW(Stop-the-world)时间,这个越小,GC占用CPU资源越多,内存资源占用越多,微服务吞吐量越小,但是越低潜伏。这个需要做成一个可配置的ZGC参数:ZGC不用调,自适应-XX:+UseZGC:使用ZGC安全点控制安全点可以查看这篇文章:https://zhuanlan.zhihu.com/p/...-XX:-UseBiasedLocking:DisablebiasedLocking,以后会彻底去掉偏向锁(参考:),目前我们处于高并发环境,偏向锁基本没什么用,有负面影响effects-XX:GuaranteedSafepointInterval=0:Disablescheduledsafepointtasks,没必要,我们不是那种热代码变化频繁,资源宝贵的场景,如果是ZGC本身,会定时进入safepoint进行GC检查,更不用说-XX:+UseCountedLoopSafepoints:防止进入安全点时由于大的boundedloop造成的延迟,导致GCSTW时间过长太长,这里的配置是1s。但AbortVMOnSafepointTimeout未指定为true,因此它对您的jmap和jstack命令没有影响。JFR配置JFR使用请参考:https://zhuanlan.zhihu.com/p/...-XX:StartFlightRecording=disk=true,maxsize=4096m,maxage=3d-XX:FlightRecorderOptions=maxchunksize=128mmodularlimit--add-opensjava.base/java.lang=ALL-UNNAMED--add-opensjava.base/java.io=ALL-UNNAMED--add-opensjava.base/java.math=ALL-UNNAMED--add-opensjava.base/java.net=ALL-UNNAMED--add-opensjava.base/java.nio=ALL-UNNAMED--add-打开java.base/java.security=ALL-UNNAMED--add-opensjava.base/java.text=ALL-UNNAMED--add-opensjava.base/java.time=ALL-UNNAMED--add-opensjava.base/java.util=ALL-UNNAMED--add-opensjava.base/jdk.internal.access=ALL-UNNAMED--add-opensjava.base/jdk.internal.misc=ALL-UNNAMEDJava16将--非法访问的默认值从允许更改为拒绝(JEP:https://openjdk.java.net/jeps...),Java17直接去掉了这个选项(JEP:https://openjdk.java.net/jeps...),所以现在要打破模块化封装,你必须通过此命令专门打破某些模块对某些模块的暴露。下面是java.base下一些可能被反射访问到的常用包,暴露给所有未命名的模块(我们自己的项目一般不指定模块名,如果指定了,替换成你具体的模块名)这样也可以从如下报错可以看出:Unabletomakeprotectedfinaljava.lang.Classjava.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain)throwsjava.lang.ClassFormatErroraccessible:modulejava.basedoesnot"opensjava.lang"tounnamedmodule@7586beff现在启动参数配置有点复杂,无法指定某个模块下的所有包都暴露给某个模块,以后我也没有这样的打算,参考:https://jigsaw-dev.openjdk.ja...微信搜索“满张散列的干货”关注公众号,加作者微信,天天刷卡,轻松提升技术,收获各种优惠:我会经常发一些官方社区各种框架的好消息视频素材,并添加个人翻译字幕到以下地址(包括上面公众号),欢迎关注:知乎:https://www.zhihu.com/people/...B站:https://space.bilibili.com/31...
