JDK 28 的 HotSpot 开始给后量子算法热路径加 intrinsic。Mark Powers 在 inside.java(2026-09-30)写到,开启适用 intrinsic 后,相对纯 Java 实现最高约 218% 的 speed-up,也就是大约 3.18 倍吞吐。覆盖范围是 ML-KEM、ML-DSA,以及哈希型签名 HSS/LMS。本文只谈这条「算法热路径加速」线,不展开 TLS 握手策略。

算法已经在 JDK 里,这次加速的是热路径

JDK 里已经能用几类现代后量子算法:ML-KEM(FIPS 203,算法能力由 JEP 496 引入)、ML-DSA(FIPS 204,JEP 497)、以及 RFC 8554 描述的哈希型 HSS/LMS。这些实现先落在 Java 里,好处是可移植,也有一份可靠的功能基线。业务代码通常仍通过标准 KeyPairGenerator、KEM、Signature 等 API 使用它们,一般不必自己碰底层多项式运算。

对特别吃性能的操作,HotSpot 可以把选定的 Java 方法替换成平台相关的机器码,也就是 intrinsic。这类代码会用上 CPU 上的 SHA-3 加速、SHA-256 加速、向量指令,以及更高效的模运算。原文强调,intrinsic 并不会永久抹掉 Java 实现。Java 方法一直留着,作为可移植回退。@IntrinsicCandidate 用来标出「当前平台若有合适实现,HotSpot 可以替换」的方法。

适合做成 intrinsic 的候选,通常同时满足三件事:算起来贵、调用很频繁,而且平台实现相对 Java 回退要有可见收益。当前平台没有合适 intrinsic 时,行为仍是跑纯 Java。对运维与应用来说,同一份字节码在不同 CPU 上可能走出不同速度,语义与可移植性仍由 Java 基线兜底。

ML-KEM:多项式热路径很适合 intrinsic

ML-KEM 有多处方法标了 @IntrinsicCandidate,落在密钥生成、encapsulation、decapsulation 的热路径上。最有潜力的操作,是对恰好 256 个系数的多项式做高度规整的计算。同一套小算术步骤可以对每个系数反复执行。

正向与逆向数论变换(NTT)里有大量彼此独立的 butterfly 操作。原文脚注把 butterfly 写成变换里的基本两入两出步骤,例如在预计算常数 w 下得到 a′ = a + wb、b′ = a − wb,NTT 里全部在某个素数模下运算。NTT 域多项式乘法则是反复做模乘加。多项式加法结构规整,容易向量化。Barrett 约简是对大量系数做同一种模约简。比特打包与解包则适合 CPU 的字节重排、比特抽取指令。

原文专门提醒:汇编本身并不天然比 Java 更快。这些操作成为好候选,是因为计算结构让现代 CPU 能直接、反复吃同一类模式。intrinsic 盯的是「形状对了」的热循环;整份 ML-KEM 仍以 Java 实现为功能基线,并未被汇编整体替换。

ML-DSA:共享大类运算,实现仍要算法专用

ML-DSA 与 ML-KEM 同属格基方案,共享几类多项式工作:正向与逆向 NTT、NTT 域多项式乘法、多项式加法。两边实现不能互换。ML-KEM 使用模数 3329,ML-DSA 使用 8380417,系数表示与约简算术也不同。工作类型相近,但 HotSpot 通常仍需要按算法分别做 intrinsic。

ML-DSA 还有没有直接 ML-KEM 对应物的操作。例如 implDilithiumDecomposePoly:在处理过程中把多项式系数拆成两个分量,属于 ML-DSA 专用、且非 NTT 的 intrinsic 候选。读源码或跟 JDK 变更时,看到 Dilithium 前缀不必惊讶。ML-DSA 由 Dilithium 派生,但 JEP 497 明确二者不可互通;这里的方法名更多是实现侧痕迹。

签名与验签场景里,多项式分解、NTT 相关步骤往往落在高频路径。若你们已经在压测 ML-DSA,升级后建议按参数集(如 ML-DSA-44 / 65 / 87)分别看吞吐区间,原文也提示不同参数集的算力需求不同。

HSS/LMS:验证路径主要吃 SHA-256

HSS/LMS 是哈希型签名方案。在原文给出的验证负载里,SHA-256 占了大部分执行时间,所以 SHA-256 intrinsic 特别有价值。这类结果也说明一个常见权衡:精选一小段高频原语做加速,就能显著抬高整条算法的吞吐,同时仍把 Java 实现留作可移植回退。

若你们已经在用 HSS/LMS 做固件签名、代码签名类场景,升级到带 SHA-256 加速 intrinsic 的构建后,更值得先看验证路径的吞吐与 CPU 占用。原文的测量口径正是验证负载;密钥生成是否同幅度受益,文中未给出对等数字,本文不作外推。

JDK 28 上测到的吞吐提升

吞吐对比是「开启适用 intrinsic」相对「纯 Java 实现」。原文图里的 intrinsic 条,给出适用算法参数集上的相对吞吐最小到最大范围。例如 ML-KEM-512 比 ML-KEM-1024 算力需求更低,因此吞吐更高。读图时按参数集看区间,比只记一个 headline 数字更稳妥。

文中特别校正读数:218% 的 speed-up,表示开启 intrinsic 后大约是纯 Java 版本的 3.18 倍快;若把「218%」误读成「快了 2.18 倍」,会低估实际吞吐比。文中给出的测试机如下。

Linux aarch64:

  • 2× Ampere Altra Quicksilver(3.0 GHz Neoverse-N1,32 MiB System Cache,1024 KiB L2)
  • 每颗 80 核,合计 160 个处理器线程,1024 GB 内存

Linux x64:

  • 2× Ice Lake-SP(3.0 GHz Xeon Gold 6354,最大睿频 3.6 GHz,60 MiB L3)
  • 每颗 18 核并开启超线程,合计 72 个处理器线程,512 GB 内存

图表本身在原文页面上。本文只转写文字结论与测试机配置,不另行解读未在正文写出的分参数集数值。自家机器若缺少对应加速指令,或 HotSpot 未启用该候选,实测可能明显低于文中上限。发布说明里写「最高约 3.18 倍」时,建议同时附上测试平台与「相对纯 Java」这一对比口径。

落地时怎么理解边界

对应用侧,这条更新更贴近「热路径更快了」。算法 API 仍走既有 Java 实现路径;有平台 intrinsic 时 HotSpot 替换候选方法,没有则回退纯 Java。关注点可以放在:你们是否已经在用 ML-KEM / ML-DSA / HSS-LMS,升级到带这些 intrinsic 的 JDK 28 构建后,密钥协商、签名验证等热路径是否出现可测的吞吐变化。

TLS 默认策略、混合握手怎么配,属于另一篇文章的范围。若团队内部 changelog 容易混写,建议把「算法可用性(JEP 496 / 497)」与「HotSpot 热路径 intrinsic(JDK 28 / inside.java 此文)」拆成两条,避免读成一次大升级。性能验收也建议用你们真实参数集与硬件指令集做对照实验,直接套用文中 headline 往往不够稳。

若要核对算法归属,可分别看 JEP 496(ML-KEM) 与 JEP 497(ML-DSA)。二者均已交付;本次 inside.java 文章讨论的是 JDK 28 上 HotSpot 对相关热路径的 intrinsic 加速。

参考资料

— 感谢阅读 —

一起交流

分享你的思考,让讨论更进一步。