jvm调优

Posted xcrj

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jvm调优相关的知识,希望对你有一定的参考价值。

参考

参考文章
参考文章

应用需求

IO应用,计算应用

IO要求,低延迟应用,增加响应速度,减少暂停时间
	比如一致诟病的android手机响应速度慢,指的是用户点击APP图表到应用程序打开,这段响应时间很长,需要着重减少单次GC的时间,不能在用户操作手机的过程中,一次GC的时间过长。
	对于涉及大量用户操作的系统,对外提供接口的系统,IO要求都较高,都尽量要求响应速度,需要GC重点减少单次GC的时间,减少GC暂停时间

计算要求,高吞吐量应用,提高吞吐量
	算法,重复创建对象,长时间存在的对象少
	较大年轻代,较小的老年代,减少触发minor GC,单位时间内的暂停时间最短
	对于AI等算法应用,其中涉及到大量计算,计算要求都较高,都尽量提高单位时间内计算线程运行的时间,需要GC重点减少单位时间内GC的时间,提高吞吐量

调优层次

架构调优(优先)
代码调优(优先)
JVM调优(其次)
数据库调优
操作系统调优

调优指标

GC频率,GC时间

GC频率,GC时间
时间(计算时间,IO时间),空间

吞吐量=应用线程运行时间/(应用线程运行时间+GC线程运行时间)
暂停时间:GC时工作线程被暂停的时间
内存占用:堆区内存大小

不可能三角,一款优秀的GC最多同时满足其中两项
- 吞吐量:单位时间内GC时间短
- 暂停时间:单次GC时间短

设计/使用GC时:
- 专注较大吞吐量或最小暂停时间
- 最大吞吐量和最小暂停时间的折衷

GC

GC串并行发作用位置算法特点场景
Serial串行新生代复制算法响应速度单CPU环境下client模式
ParNew并行新生代复制算法响应速度多CPU环境下Server模式下与CMS配合使用
Parallel Scavenge并行新生代复制算法吞吐量多运算,少IO
Serial Old串行老年代标记-整理响应速度单CPU环境下client模式
Parallel Old并行老年代标记-整理吞吐量多运算,少IO
CMS并发新生代,老年代标记-清除响应速度B/S业务
G1并发,并行新生代,老年代复制算法、标记-整理响应速度服务端应用
ZGC新生代,老年代复制算法服务端应用

GC概念

概念针对gc
young gc/minor gc年轻代的gc
old gc/major gc老年代gcCMS
full gc新生代、老年代、元空间gc
mixed gc年轻代、部分老年代gcG1

GC算法

标记-清除:
	过程:最初的算法,先标记再清除
	优点:基础算法
	缺点:新生代大多数对象都是朝生夕死,死亡对象多,标记对象多,清除对象多,执行次数越多效率越低;
				效率随对象数量增多而下降;产生大量外部碎片
	使用:CMS使用该算法收集老年代的垃圾
标记-复制算法:
	过程:内存分成两个区域,第1个区域使用完了,把幸存对象复制到第2个区域,再清空第1块内存
	优点:主要应用于新生代
	缺点:另一部分空间始终空闲;Eden区幸存对象无法放入s区,需要分配担保策略,直接进入老年代
	使用:Serial、ParNew、Parallel
标记-整理
	背景:标记-复制算法不适用与老年代存在大量幸存对象的情况
	过程:往内存的一端移动,清理掉边界以外的内存
	优点:解决标记-清除算法的外部碎片问题;解决标记-复制算法需要分配担保的问题
	使用:Serial Old、Parallell Old

	标记-清除:
	标记-整理:

对比 标记-清除 和 标记-整理:

算法移动内存
标记-清除对象不移动内存分配复杂
空间碎片化,触发GC,对象分配依赖于“空闲列表”,对象分配阶段耗时
标记-整理对象移动内存回收复杂
老年代大部分对象存活,GC时伴随大量的对象移动,对象回收阶段耗时

GC/Serial, ParNew, Parallel

都关注新生代,都使用标记-复制算法,因为新生代大部分对象都死的快,需要复制的对象少,效率就高

GC/CMS, Serial Old, Parallel Old

都关注老年代,老年代大部分对象都存活,
使用标记-整理算法,内存分配时间短,回收时间长
使用标记-清除算法,内存分配时间长,回收时间短

GC/CMS

GC/G1

面向服务端应用,针对具有大内存、多处理器的机器,在普通大小的堆里表现并不惊喜
需要低GC延迟并有大堆的应用程序(G1“增量式清理”来保证每次GC停顿时间不会过长)
在堆大小约6GB或更大时,可预测的暂停时间可以低于0.5秒

转移阶段要处理所有存活的对象,耗时会较长。因此,G1停顿时间的瓶颈主要是标记-复制中的转移阶段STW。为什么转移阶段不能和标记阶段一样并发执行呢?主要是G1未能解决转移过程中准确定位对象地址的问题。
与ZGC对比,G1的转移阶段完全STW的,且停顿时间随存活对象的大小增加而增加。

GC/ZGC

JDK11
停顿时间不超过10ms
停顿时间不会随着堆的大小,或者活跃对象的大小而增加
支持8MB~4TB级别的堆(未来支持16TB)

转移阶段也是并发执行的
ZGC几乎所有暂停都只依赖于GC Roots集合大小,停顿时间不会随着堆的大小或者活跃对象的大小而增加。与ZGC对比,G1的转移阶段完全STW的,且停顿时间随存活对象的大小增加而增加。

jdk/GC

jdk各个版本默认GC

jdk版本默认GC新生代GC老年代GC
jdk7u4-Parallel Scavenge + Serial OldParallel ScavengeSerial Old
jdk7u4+Parallel Scavenge + Parallel OldParallel ScavengeParallel Old
jdk8Parallel Scavenge + Parallel OldParallel ScavengeParallel Old
jdk11G1G1G1
jdk17默认GC新生代GC老年代GC
jdk21默认GC新生代GC老年代GC

jvm参数对应gc

参数代表GC
-XX:-UseSerialGCSerial + Serial Old
-XX:-UseParNewGCParNew + Serial Old
-XX:-UseParallelGCParallel Scavenge + Serial Old
-XX:-UseParallelOldGCParallel Scavenge + Parallel Old
-XX:-UseConcMarkSweepGCCMS + ParNew
-XX:-UseG1GCG1
参数代表GC

jdk7/GC

命令:java -XX:+PrintCommandLineFlags -version
结果:-XX:+UseParallelGC

JDK 7u4-

  • server模式默认采用 Parallel Scavenge + Serial Old(PS MarkSweep)
  • 新生代用 Parallel Scavenge 老年代用 Serial Old

JDK 7u4=+

  • server模式默认采用 Parallel Scavenge + Parallel Old(PS MarkSweep)
  • 新生代用 Parallel Scavenge 老年代用 Parallel Old

jdk8/GC

server模式默认采用 Parallel Scavenge + Parallel Old(PS MarkSweep)
新生代用 Parallel Scavenge 老年代用 Parallel Old

jdk11/GC

命令:java -XX:+PrintCommandLineFlags -version
结果:-XX:+UseG1GC

server模式默认采用 G1

jdk17/GC

jdk21/GC

调整

-Xms 等于 -Xmx 建议扩大3-4倍FullGC后老年代空间大小
过小:频繁GC
过大:GC时间过长

堆/新生代

-Xmn,1-1.5倍FullGC之后的老年代空间占用
过小:minor GC次数频繁;对象直接进入老年代,触发Full GC时工作线程被暂停的时间
过大:老年代变小,Full GC频繁执行;minor GC增加回收时间

堆/老年代

老年代使用并发收集器

方法区/元空间

-XX:MetaspaceSize 等于 -XX:MaxMetaspaceSize
1.2-1.5倍 Full GC后的元空间占用

调优过程

生成GC日志/dump文件/第三方可视化工具

分析判断

参数设置合理性
异常信息
GC频率
GC耗时,GC超过1秒,必须优化
吞吐量或响应时间异常
堆/老年代 持续上涨

确定目标

使用最小的硬件消耗来承载更大的吞吐量和更低的响应时间
- 堆内存使用率 <=70%
- 老年代内存使用率 <=70%
- 平均停止时间 <=1s
- Full GC调用次数接近于0 或 两次GC时间间隔>=24h

调整参数

调优工具

jps

以上是关于jvm调优的主要内容,如果未能解决你的问题,请参考以下文章

##超细##Java JVM调优篇

JVM内存和JVM调优--总结

[转] JVM 调优系列 & 高并发Java系列

JAVA JVM垃圾回收 JVM调优

Java开发经典实战!java代码编译过程

Java开发经典实战!在线学java培训网站