JVM最佳实践

JVM示意图:https://extremeautomation.io/cheatsheets/jvm-cheatsheet2/
前要
本建议主要是针对pod总内存为4G的情况进行分析,正常情况下,一个pod上只会部署一个java应用程序,不建议再混不其他应用。非4G内存情况也可参考本建议,特别需要注意,如果java内存设置大于32G,将不会开启指针压缩。

内存参数设置建议
1、内存布局及建议
除java本身占用的内存外,还需要评估:
系统、容器进程占用的内存
监控程序占用的内存
java堆外:java metaspace(java8) + code cache + 线程栈(开辟线程占用的内存,默认1M每线程) + 其他
对于系统容器进程、监控程序、java metaspace和java code cache占用的内存,一般评估不超过256M。建议java应用不要申请直接内存。
如果java线程总数小于600,那么除java堆外预留的内存则为 600M + 256M ≈ 1G。此种情况可以考虑将java启动参数-Xmx和-Xms设置为3G,新生代可以使用默认值。另外强烈建议设置metaspace相关参数。
如果java线程总数大于600,那么除java堆外预留的内存则需要高于1G。此种情况可以考虑将java启动参数-Xmx和-Xms设置为2G。
补充说明:
a. java线程占用实际上并不是一开始上来就占用1M,但是如果预留不够,开辟线程会失败。
b. 正常情况下我们会预留一部分给系统缓存,但是正常java应用不需要预留太多系统缓存。
c.一般来说,绝大部分项目的线程数不会超过600
d.垃圾收集的时候系统什么事情都干不了

2、内存调大的优缺点
优点:
可以减少新生代和老年代GC频次,提高系统吞吐(新生代GC停顿时间和内存大小非线性关系)。一般而言,一个正常的、优秀的java应用程序,主要以新生代GC为主,绝大部分对象一般不会存活到进入老年代。
可以适当增加能够容纳的合理的大对象数量。
缺点:
调大内存,默认情况下也会增加新生代大小,虽然减少了GC次数,但是会提高每次GC STW的时间,对于时延比较敏感的不是很建议,或者另想其他方法。
对使用很多线程的应用可能会有创建线程失败的风险。

3、对GC时延敏感的建议
To C 应用一般比较在乎用户体验,对GC时延比较敏感,对于此种情况,可以考虑:
增大整个java堆内存的同时适当调小新生代内存大小。新生代小的话gc频率会变高,总体的gc耗时会变多,但是对于单次请求来说处理会变快
java8可以考虑使用G1GC。G1有个优化点是GC超过100毫秒就暂停,目前默认还是使用的CMS,GC时间不可控
升级jdk版本。更高版本对GC做了很多优化。

其他建议
1、线程尽量使用线程池。
2、对于使用mq类应用,尤其是有很多消费者组的,需要调整默认参数,避免开辟过多线程和一次性拉取过多消息占用大量内存。

Metaspace:存储类的结构信息、方法信息、字段信息、注解信息、方法计数器等

组件统一配置
机器生产都是2C4G
参数含义
Xms: -Xms2048M  表示初始化JAVA堆的大小及该进程刚创建出来的时候,他的专属JAVA堆的大小,一旦对象容量超过了JAVA堆的初始容量,JAVA堆将会自动扩容到-Xmx大小,默认物理内存的1/64
Xmx: -Xmx2048M  表示java堆可以扩展到的最大值,在很多情况下,通常将-Xms和-Xmx设置成一样的,因为当堆不够用而发生扩容时,会发生内存抖动影响程序运行时的稳定性,超出这个值会报outofmemory,默认物理内存的1/4
Xmn: -Xmn1024M  年轻代大小,整个堆大小=年轻代大小+老年代大小+常量池,增大年轻代的话会减少老年代,Sun官方推荐配置为堆的3/8
#Xss:规定了每个线程虚拟机栈及堆栈的大小,一般情况下,256k是足够的,此配置将会影响此进程中并发线程数的大小,默认1M每线程,一般不太关心此参数

-XX:SurvivorRatio=22             幸存者比例设置,设置年轻代中Eden区和1个Survivor区的比例为22:1,一共有两个Survivor区,设置的比较大能尽量保证对象在Eden区gc掉,减少对象进入Survivor区
-XX:MetaspaceSize=64M            元空间,不在虚拟机中,使用本地内存,大小受本地内存限制,当达到MetaspaceSize的时候触发full gc
-XX:MaxMetaspaceSize=512M        默认值无限
-XX:+HeapDumpOnOutOfMemoryError   导出内存溢出的堆信息
每个组件的dump文件名不一样
-XX:HeapDumpPath=/wls/applogs/组件名.hprof

使用jdk的jvisualvm.exe可以打开dump文件
Metaspace说明:
JDK8及以后:可以使用-XX:MetaspaceSize和-XX:MaxMetaspaceSize设置元空间初始大小以及最大可分配大小。
例子:设置初始大小是100M,最大可分配空间也是100M。-XX:MetaspaceSize=100m -XX:MaxMetaspaceSize=100m。
1.如果不指定元空间的大小,默认情况下,元空间最大的大小是系统内存的大小,元空间一直扩大,虚拟机可能会消耗完所有的可用系统内存。
2.如果元空间内存不够用,就会报OOM。
3.默认情况下,对应一个64位的服务端JVM来说,其默认的MaxMetaspaceSize值为-1,-XX:MetaspaceSize值为21MB,这就是初始的高水位线,一旦元空间的大小触及这个高水位线,
就会触发Full GC并会卸载没有用的类(即这些类对应的类加载器不再存活),然后高水位线的值将会被重置增大(不超过MaxMetaspaceSize)。
4.从第3点可以知道,如果初始化的高水位线设置过低,会频繁的触发Full GC,高水位线会被多次调整。所以为了避免频繁GC以及调整高水位线,建议将-XX:MetaspaceSize设置为较高的值,而-XX:MaxMetaspaceSize不进行设置

YGC:对年轻代GC,EDEN空间不足时执行
FGC:OLD或者METASPACE空间不足时执行
STW: Stop-The-World: 是在垃圾回收算法执行过程当中,将JVM内存冻结丶应用程序停顿的一种状态。 在STW 状态下,JAVA的所有线程都是停止执行的 -> GC线程除外,每次GC都会STW,系统吞吐量下降

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值