最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
JVM 并发标记清除:性能调优技巧
时间:2026-07-08 10:07:57 编辑:袖梨 来源:一聚教程网
JVM没有独立的“并发标记清除”收集器,而是CMS、G1等收集器内部采用的算法逻辑;应优先选对收集器(如G1为默认,ZGC/Shenandoah适配超低延迟),再通过参数优化标记与清除效率。
JVM 没有“并发标记清除”这一独立可启用的收集器或参数,它只是某些垃圾收集器(如已废弃的 CMS、或 G1 的部分回收阶段)内部采用的算法逻辑。真正能调优的,是选择合适收集器并配置其行为参数,从而间接优化标记与清除过程的并发性、延迟和碎片控制。
选对收集器,比调参更重要
CMS 在 JDK 9+ 已被移除,G1 是当前主流默认收集器(JDK 9 起),ZGC/Shenandoah 更适合超低延迟场景。不要试图“启用并发标记清除”,而应明确目标:
- 若追求停顿可控(
- 若需平衡吞吐与延迟(堆 4–64GB),G1 是更稳妥的选择;
- 避免继续使用 CMS——它无压缩阶段,长期运行必然积累碎片,最终触发 Full GC,反而放大 STW 时间。
控制标记启动时机,防早不防晚
标记阶段是否及时启动,直接影响清除压力和内存碎片风险:
- G1 中用 -XX:InitiatingHeapOccupancyPercent=35~45(默认45),设太低会频繁 Mixed GC,设太高易触发 Full GC;
- CMS(仅限 JDK 8 及以前)用 -XX:CMSInitiatingOccupancyFraction=65~75,需结合老年代实际增长速率实测调整;
- 配合 -XX:+PrintGCDetails -Xloggc:gc.log 观察老年代占用曲线,让标记在稳定增长期前触发,而非等临界点才动作。
分配策略减少无效标记负担
很多“标记慢”,本质是老年代塞了不该进的对象。从源头控制:
- 用 -XX:MaxTenuringThreshold=6(而非默认15),避免短寿对象在 Survivor 区反复拷贝后误升老年代;
- 大对象(如 >2MB 的 byte[])直接进老年代:加 -XX:PretenureSizeThreshold=2097152(单位字节),避开新生代复制开销和老年代碎片化双重损耗;
- 调小新生代比例(如 -XX:NewRatio=3)可缓解老年代过快填满,但需同步观察 Young GC 频率,避免 YGC 过于频繁。
降低标记与清除的实际开销
即使算法逻辑固定,运行时效率仍可优化:
- 开启压缩指针:-XX:+UseCompressedOops(默认开启,确认未被禁用),减小对象引用体积,加快根扫描与对象遍历;
- 为并发标记分配足够线程:-XX:ConcGCThreads=4(建议设为 CPU 核数的 1/4,上限一般 ≤8),太少导致标记拖尾,太多抢应用线程资源;
- G1 下可启用自适应 IHOP:-XX:+G1UseAdaptiveIHOP(默认开启),让 JVM 根据历史 GC 数据动态调整标记启动阈值,比静态配置更稳。
不复杂但容易忽略:标记-清除不是开关,而是结果;调优的关键,在于让标记更准、更轻、更及时,让清除动作尽量少发生、少留碎片。
相关文章
- 《Disney Lorcana: Wilds Unknown》预购开启 首批《Toy Story》及皮克斯卡牌购买指南 07-29
- 车来了赶车闹钟如何设置 07-29
- 崩坏星穹铁道余晖残卷巨剑守护打法攻略 07-29
- 崩坏星穹铁道砂金角色部分背景介绍 07-29
- 崩坏3雷电芽衣什么时候上线 07-29
- 玩具熊的五夜后宫4代噩梦气球男孩Nightmare Balloon Boy介绍 07-29