跳转至

JDK 17:JVM 与运行时更新#

版本信息

  • JDK:17(LTS,2021-09 GA)
  • 本页覆盖的关键 JVM JEP377(ZGC 转正)、 379(Shenandoah 转正)、 391(macOS/AArch64)、 382(macOS Metal 渲染)、 411(Security Manager 弃用)

本页讲 「工具与运行时」 桶。语言特性见 概览

运行时主线#

JDK 17 的 JVM 层头条是:两台低延迟 GC 从实验转正为产品级——ZGC(JEP 377)与 Shenandoah(JEP 379),都在 JDK 15 完成,17 LTS 承接。这意味着低延迟 GC 进入"生产可用"阶段,不再需要解锁实验开关

ZGC 转正为产品#

为什么需要#

ZGC(Z Garbage Collector)把绝大部分回收工作与应用线程并发进行,停顿通常 <1ms 且不随堆大小增长(TB 级堆仍保持低停顿)。在 JDK 11 它还只是实验特性(且需特定构建),到 JDK 17 已是正式 GC。

怎么用#

一个标志即可,无需解锁(本机实测 JDK 17 直接可用):

java -XX:+UseZGC -Xmx16g -jar app.jar

下面是 examples/zgc/真实可运行的演示(snippets 嵌入,零漂移):

package com.javamodern.zgc;

import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 演示 ZGC:可扩展低延迟垃圾收集器(JEP 377,JDK 15 转正,17 LTS 可用)。
 *
 * <p>ZGC 是并发 GC,回收大部分工作与应用线程并发进行,MXBean 名为
 * {@code "ZGC Cycles"}(并发周期)与 {@code "ZGC Pauses"}(短暂 STW 停顿)。
 * 测试 JVM 必须以 {@code -XX:+UseZGC} 启动(见 {@code pom.xml} 的 surefire {@code argLine})。
 */
public class ZgcDemo {

    /** 当前所有 GC MXBean 的名字。 */
    public static List<String> gcNames() {
        return ManagementFactory.getGarbageCollectorMXBeans().stream()
                .map(GarbageCollectorMXBean::getName)
                .collect(Collectors.toList());
    }

    /** 是否运行在 ZGC 下(任一 bean 名含 "ZGC")。 */
    public static boolean isZgc() { // (1)
        return gcNames().stream().anyMatch(n -> n.contains("ZGC"));
    }

    public static void main(String[] args) {
        System.out.println("GC beans = " + gcNames());
        System.out.println("isZGC = " + isZgc());
    }
}
  1. :material-lightbulb: 通过 GC MXBean 名判定当前 GC:ZGC 的 bean 是 ZGC Cycles(并发周期)与 ZGC Pauses(短暂 STW 停顿)——两个 bean 的并存体现了它"并发为主、偶发短停顿"的结构。

运行 ZgcDemo.main 的实测输出(JDK 17 + ZGC):

GC beans = [ZGC Cycles, ZGC Pauses]
isZGC = true

底层原理#

graph LR
    App["应用线程运行"] -.并发.- C["并发标记/转移<br/>colored pointers + load barriers"]
    App --> P["极短 STW 停顿<br/>仅初始标记/再标记等几个点"]
    C --> D["堆可达性更新"]
    P --> D
    style App fill:#c8e6c9
    style P fill:#ffe0b2
    style C fill:#bbdefb

关键技术:染色指针(colored pointers) 在 64 位指针里编码对象状态,读屏障(load barrier) 在应用线程访问对象时并发完成转移——这让大部分回收无需 Stop-The-World。

Shenandoah 转正(发行版差异)#

Shenandoah(Red Hat 主导)也在 JDK 15 转正(JEP 379),思路与 ZGC 类似(并发整理,低停顿),技术细节不同(用 Brooks 指针 / 转发指针而非染色指针)。

发行版差异(本机实测)

本机所有构建(Oracle JDK 17、OpenJDK 11/21)都不含 Shenandoah-XX:+UseShenandoahGCUnrecognized VM option。Shenandoah 主要出现在 Red Hat / Fedora / Amazon Corretto 等构建中。选 GC 前先确认你的 JDK 发行版是否包含目标 GC。

其他运行时更新#

特性 JEP 说明
macOS/AArch64 移植 391 Apple Silicon(M1/M2)原生支持
macOS Metal 渲染 382 Swing/Java2D 在 macOS 上改用 Metal,替代已废弃的 OpenGL
Security Manager 弃用 411 标记 Security Manager 为移除候选——它已不适应现代安全模型,未来版本将移除
增强型 PRNG 356 (标准库)新增 java.util.random.RandomGenerator 统一接口与可跳变/流式 PRNG

与 JDK 8 对比#

java -jar app.jar            # 默认 Parallel;或手动 -XX:+UseG1GC
# 没有停顿 <1ms 的并发 GC 可选
java -XX:+UseZGC -Xmx16g -jar app.jar   # 产品级低延迟,一个标志
java -jar app.jar                        # 仍是默认 G1

常见坑 / 最佳实践#

  • ZGC 不等于更快:它降的是停顿,不是吞吐;吞吐型批处理用 G1/Parallel 可能更高。按负载选。
  • GC 选型看发行版:要 Shenandoah 得选 Red Hat 系构建;要 ZGC 大多数 OpenJDK 构建都有。
  • Oracle JDK 17 的免费窗口:Oracle JDK 17 的免费商用更新窗口有限且会过期;长期使用建议改用 OpenJDK 衍生发行版(Temurin/Corretto/Zulu 等),升级规划时把"换发行版"纳入考虑。
  • 大堆 + 低延迟:ZGC 的停顿几乎与堆大小无关,几十 GB~TB 堆仍能保持亚毫秒停顿——这是它相对 G1 的核心优势。

小结#

JDK 17 的 JVM 更新主线是「低延迟 GC 转正」:ZGC、Shenandoah 从实验走向产品级,停顿可控性跃升;平台层面补齐了 Apple Silicon 支持。对企业升级,这意味着大堆、低延迟负载有了开箱即用的方案。

参考#