网站首页 > 教程文章 正文
一、99.9%的人没有JVM调优经验
其实,JVM调优并不是每个开发者都会接触到的技能,原因很简单:JVM通常不需要调优!
如果你的 JVM 真的出现了严重的 GC 压力,第一步想到的应该是优化代码,而不是直接上手去调整 JVM 参数。因为调整 JVM 可能带来以下问题:
- 不可维护:调优后,可能下一个维护者难以理解这些修改。
- 不可拓展:假设当前流量已经优化好了,但未来流量大幅变化时,这些参数可能失效。
尽管如此,面试时常常会有面试官问起 JVM 调优。那么,他们真的在问 JVM 调优的经验吗?
二、面试官实际上想问什么?
他们更多的是在考察以下方面:
- 你对 JVM GC 的理解
- 你对不同 GC 回收器的熟悉度
- 你是否了解常见的 JVM GC 参数配置
接下来我们以 Java 17 中的G1垃圾回收器为例,来看一些常见的 GC 相关参数。
在 G1 垃圾回收器中,堆内存被划分为多个Region,虽然这些 Region 的大小是相同的,但是它们属于不同的代。了解这些原理有助于我们更好地优化 JVM 的 GC 性能。
内存区域划分:
- E(Eden)区:存放新创建的对象
- S(Survivor)区:存放从Eden区存活下来的对象
- O(Old)区:存放长期存活的对象
- H(Humongous)区:专门存放超大对象
大对象的判定标准: 当一个对象的大小超过单个 Region(内存区域) 大小的 50%(0.5个Region)时,它就被视为大对象(Humongous对象)
三、常见的垃圾回收器
目前常见的垃圾回收器包括下面 3 种:
- CMS (Concurrent Mark-Sweep): JDK 14之后不再支持
- G1 (Garbage First): JDK 8-17版本的默认垃圾回收器
- ZGC (Z Garbage Collector): 从JDK 21开始,成为默认的垃圾回收器。
在启动 JVM 时,可以通过指定参数来使用不同的垃圾回收器。
-XX:+UseZGC
-XX:+UseG1GC
-XX:+UseConcMarkSweepGC
四、常见的调优策略
1. 设置堆大小
一般来说,我们建议将 JVM 的堆内存大小进行固定,避免堆内存发生动态扩缩容。
# 例如固定为2GB
-Xms 2048M -XMx 2048M
固定堆内存的好处:
- 避免堆的扩缩容:堆内存的扩缩容会影响 GC 的时间,带来更多的停顿时间,尤其是 G1这 种需要预测停顿时间的垃圾回收器,会导致预测变得不准确。
- 减少内存碎片:在 G1 中,堆内存被划分为多个 Region,如果堆大小不固定,Region 的大小也会不固定,可能导致内存浪费。
2. 设置Region大小
G1 将堆内存划分为多个大小相等的 Region,Region 的大小一般是 2 的幂,从 1MB 到 32MB 不等。
合理调整Region大小能更好地配合应用的实际需求,提升性能表现,减少停顿时间,并且优化堆内存管理。
对于较小的堆内存,建议设置较小的 Region 大小,例如2MB或4MB。 对于较大的堆内存,建议设置较大的Region大小。
# 例如设置Region 为4M
-XX:G1HeapRegionSize=4M
3. 设置最大目标停顿时间
上面说过 G1 垃圾回收器的最大特点是停顿预测模型。默认的停顿时间为 200ms。
因此我们可以设置一个目标停顿时间:
# 设置目标停顿时间为 100 ms
-XX:MaxGCPauseMillis=100
注意: JVM 会尽量保证垃圾回收停顿时间不超过这个值,但不能完全保证。所以针对一些延迟敏感的场景,可以适当调小停顿时间。
4. 设置标记线程数和回收线程数
G1 在进行标记对象为垃圾和回收垃圾时,都是多线程操作的。 因此我们可以根据需要去调整线程数。
# 并行回收线程数(默认值是 CPU 核心数)
-XX:ParallelGCThreads=8
# 并发标记线程数
-XX:ConcGCThreads=4
说到最后,这些调优参数在哪使用呢? 其实是在我们运行服务时设置的,例如:
# -Xms4G:设置JVM堆内存的初始大小为4GB。这意味着JVM启动时会分配4GB的堆内存
# -Xmx4G:设置JVM堆内存的最大大小为4GB。JVM堆的大小不会超过4GB
# -XX:+UseG1GC:启用G1垃圾回收器
# -XX:MaxGCPauseMillis=200:设置G1垃圾回收器的最大目标停顿时间为200 毫秒
# -XX:G1HeapRegionSize=4M:设置G1垃圾回收器的Region大小为4MB
# -XX:InitiatingHeapOccupancyPercent=45:设置堆的占用比例为45%。当堆内存的占用达到该比例时,G1垃圾回收器会开始触发并发标记过程,准备进行垃圾回收
# -Xlog:gc*,gc+heap=debug:file=gc.log:启用GC日志记录,gc*表示记录所有GC日志,gc+heap=debug表示记录GC过程中堆内存的详细调试信息,并将日志输出到gc.log文件中。
java -Xms4G -Xmx4G \
-XX:+UseG1GC \
-XX:MaxGCPauseMillis=200 \
-XX:G1HeapRegionSize=4M \
-XX:InitiatingHeapOccupancyPercent=45 \
-Xlog:gc*,gc+heap=debug:file=gc.log \
-jar my-app.jar
- 上一篇: JVM 性能调优,实现高吞吐量和低延迟
- 下一篇: 定时任务优化总结(从半个小时优化到秒级)
猜你喜欢
- 2025-06-08 这些不可不知的JVM知识,我都用思维导图整理好了
- 2025-06-08 Tomcat调优实战手册,从线程池到内存管理的性能突围战
- 2025-06-08 Java GC调优实战:从高频Minor GC到系统吞吐翻倍的破局之道
- 2025-06-08 Java 经典垃圾回收器详解(java垃圾回收器基本原理)
- 2025-06-08 面试Java被问JVM:你来详细聊一下G1垃圾收集器
- 2025-06-08 JVM调优实战:G1垃圾回收器如何让百万级系统告别卡顿
- 2025-06-08 GC优化实战:CMS vs G1(g1比cms高效的原因)
- 2025-06-08 JVM-G1垃圾收集器原理深入解析(jvm垃圾回收器详解)
- 2025-06-08 Java与Scala的Spark内存管理,当高效撞上安全,谁在主宰你的内存
- 2025-06-08 升级JDK17的理由,核心是降低GC时间
- 最近发表
-
- 一课译词:一刀两断(一刀两断成语解释)
- 核心短语break up用法解析(breakd短语)
- HTML+CSS 实现商品图片列表放大视觉效果 复制完整代码即可马上调用
- 前端实现右键自定义菜单(前端实现右键自定义菜单怎么设置)
- Python中docx与docxcompose批量合并多个Word文档并添加分页符
- Java 将Excel转为XML(java将xls转换成xlsx)
- jq+ajax+bootstrap改了一个动态分页的表格
- css兼容性问题及一些常见问题汇总大全,赶快收藏!
- Java 的业务逻辑验证框架 之-fluent-validator
- 小程序cover-view踩坑系列2(微信小程序overflow)
- 标签列表
-
- location.href (44)
- document.ready (36)
- git checkout -b (34)
- 跃点数 (35)
- 阿里云镜像地址 (33)
- qt qmessagebox (36)
- mybatis plus page (35)
- vue @scroll (38)
- 堆栈区别 (33)
- 什么是容器 (33)
- sha1 md5 (33)
- navicat导出数据 (34)
- 阿里云acp考试 (33)
- 阿里云 nacos (34)
- redhat官网下载镜像 (36)
- srs服务器 (33)
- pico开发者 (33)
- https的端口号 (34)
- vscode更改主题 (35)
- 阿里云资源池 (34)
- os.path.join (33)
- redis aof rdb 区别 (33)
- 302跳转 (33)
- http method (35)
- js array splice (33)