Java基础、中级、高级、架构面试资料

JDK 27,从 JEP 338 到 JEP 537 一个性能提升 16 倍的 API

JAVA herman 18浏览
公告:“业余草”微信公众号提供免费CSDN下载服务(只下Java资源),关注业余草微信公众号,添加作者微信:xttblog2,发送下载链接帮助你免费下载!
本博客日IP超过2000,PV 3000 左右,急需赞助商。
极客时间所有课程通过我的二维码购买后返现24元微信红包,请加博主新的微信号:xttblog2,之前的微信号好友位已满,备注:返现
受密码保护的文章请关注“业余草”公众号,回复关键字“0”获得密码
所有面试题(java、前端、数据库、springboot等)一网打尽,请关注文末小程序
视频教程免费领
【腾讯云】1核2G5M轻量应用服务器50元首年,高性价比,助您轻松上云

JDK 27 的 JEP 新特性马上就要冻结了,目前来看,不出意外的话,差不多还是 10 个 JEP。

我今天看了一眼,其中有一个 JEP,非常扎眼,谁能想到这个 JEP 537: Vector API (Twelfth Incubator) 竟然成了 JDK 迭代的一个钉子户。从 JDK 16 到 JDK 27,这个 API 经历了 12 次孵化,这创造了 OpenJDK 历史上最长的“孵化马拉松”纪录。

所以,接下来,本文就带领大家来看看这个 Java 史上最“难产”的 API,孵了 12 次还没转正的它到底在等什么?

JEP 537 是什么?

JEP 537: Vector API(第十二次孵化) 是 JDK 27 中一个处于孵化器状态的 API。它的核心目标是,让 Java 开发者能够显式编写向量计算代码,并由 JVM 在运行时可靠地将其编译为底层 CPU 的最优向量指令,从而获得远超传统标量计算的性能。

简单的来说,它让 Java 也能像 C/C++ 那样直接利用 CPU 的 SIMD(Single Instruction Multiple Data,单指令多数据)能力。

什么是 SIMD?

SIMD 我们接触的少,但它是现代 CPU 普遍支持 SIMD 指令集。包括 Intel 的 SSE/AVX、ARM 的 NEON/SVE 等。其一条 AVX-512 指令可以在一个 CPU 周期内同时处理 16 个 int 的加法运算,而传统标量代码需要 16 个周期。这种并行计算能力在机器学习、科学计算、密码学、金融分析等领域至关重要。

文章配图参见 https://mp.weixin.qq.com/s/iikrasY8poCd-EQvF8-E4w

Vector API 的核心设计

Vector API 始终围绕下面这几个关键抽象构建。

  • Vector<E>:向量抽象类,E 为元素类型(ByteShortIntegerLongFloatDouble
  • VectorSpecies<E>:定义向量的”种类”,由元素类型和形状(64、128、256、512、max bits)共同决定
  • VectorMask<E>:掩码,用于模拟控制流,支持条件向量操作
  • VectorShuffle<E>:洗牌操作,用于跨通道元素重排

看下面这个简单的代码示例。

static final VectorSpecies<Float> SPECIES = FloatVector.SPECIES_PREFERRED;

void vectorComputation(float[] a, float[] b, float[] c) {
    int i = 0;
    int upperBound = SPECIES.loopBound(a.length);
    for (; i < upperBound; i += SPECIES.length()) {
        var va = FloatVector.fromArray(SPECIES, a, i);
        var vb = FloatVector.fromArray(SPECIES, b, i);
        var vc = va.mul(va).add(vb.mul(vb)).neg();
        vc.intoArray(c, i);
    }
    // 尾部标量处理
    for (; i < a.length; i++) {
        c[i] = (a[i] * a[i] + b[i] * b[i]) * -1.0f;
    }
}

这段代码会被 HotSpot C2 编译器直接生成 AVX 向量指令,如 vmovdquvmulpsvaddps 等,无需开发者手写汇编。

为什么经历了 12 次孵化?

这可能是 OpenJDK 历史上孵化次数最多的特性,没有之一。从 JDK 16(JEP 338)首次孵化,到 JDK 27(JEP 537)第十二次孵化,整整跨越了 12 个版本、约 6 年时间。

为什么需要孵化这么久呢?其中最核心的原因是,它在等 Project Valhalla。

而且官方文档中也明确指出,The Vector API will incubate until necessary features of Project Valhalla become available as preview features.。Vector API 将持续孵化,直到 Project Valhalla 的必要功能作为预览特性可用。届时,团队将调整 Vector API 以使用这些功能,并将其从孵化状态提升为预览状态。

那 Project Valhalla 又是什么呢?

Project Valhalla 是 OpenJDK 的一个长期项目,旨在为 Java 引入值类型(Value Types/Value Classes)泛型特化(Generic Specialization)。这是 Java 语言模型自诞生以来最深刻的变革之一。

Vector API 对 Valhalla 的依赖

首当其冲的是值类(Value Classes)改造。

当前 Vector API 的类被标记为“value-based classes”(基于值的类),但本质上仍是普通对象,带有对象头、身份标识等开销。Valhalla 的值类将消除这些开销,让向量实例成为真正的“扁平化”值对象,就像 intlong 一样,直接映射到 CPU 向量寄存器。

而值类型改造,对应的是JEP 401: Value Classes and Objects (Preview)。这个特性,今年 5 月 12 日还在更新,这意味着今年也可能没戏。

然后是泛型特化(Primitive Generic Specialization)。

要知道,当前的 Vector<E> 泛型参数 E 必须使用包装类型(Integer 而非 int),这是 Java 泛型擦除的限制。Valhalla 的泛型特化将允许 Vector<int> 这样的写法,消除自动装箱/拆箱开销,并可能让 IntVector 等具体子类变得不再必要。

别说特化泛型了,Java 目前在语言层面连第一阶段的通用泛型都不支持,可以说是还差的远。

最后是数组和字段的优化布局方面。Valhalla 还将优化值类型在数组和对象字段中的内存布局。对于 Vector API 来说,这意味着 Float16 等新型向量元素可以更高效地存储和处理。

为什么不等 Valhalla 完成再发布?

目前,社区采取的是“边孵化边打磨”的策略。

  • 提前获取反馈:让开发者尽早试用,收集实际使用场景中的问题和需求
  • 逐步完善实现:每次孵化都伴随 bug 修复和性能优化(如 JDK 25 中通过 FFM API 链接原生数学库替代自定义 C++ 代码)
  • 保持技术领先:支持最新的硬件特性(如 ARM SVE、AVX-512、Float16 自动向量化)

正如 Azul 的 Java Champion 所指出的,Vector API 是更大的 Valhalla 项目的一部分,因此在 Valhalla 的其他部分交付之前,此功能不会最终确定,以防需要进一步更改

Vector API 要解决什么问题?

从目前来看,主要聚焦在下面 3 个问题。

JIT 自动向量化不可预测

HotSpot JVM 确实有自动向量化(Auto-Vectorization)能力,但它存在明显局限:

  • 可转换的操作有限:只有特定代码模式才能被识别
  • 对代码形状敏感:微小的代码改动可能导致向量化失效
  • 无法利用全部指令集:只能使用部分向量指令

开发者为了“讨好”自动向量化器,需要深入理解其内部算法,这既不现实也不可持续。

复杂算法无法自动优化

涉及复杂数据访问模式、跨通道重排、掩码操作或丰富控制流的算法,自动向量化往往无能为力。例如:

  • Arrays.hashCode() 的向量化实现
  • 字典序数组比较
  • 机器学习中的矩阵运算

这些场景需要显式的向量编程模型。

跨平台可移植性差

手写 JNI 调用平台特定的 SIMD 库(如 Intel SVML、ARM SLEEF)虽然能获得性能,但牺牲了 Java 的“一次编写,到处运行”特性。

Vector API 带来的好处

首先是性能飞跃。

根据 JMH 微基准测试显示,Vector API 实现的数组计算可以生成与手写汇编等效的机器码。在支持 AVX-512 的平台上,理论加速比可达 8x~16x(取决于数据类型和向量宽度)。也就是说,性能最高可以提升 16 倍。

其次是可预测的性能模型。

与自动向量化不同,Vector API 提供显式、可控的编程模型。

  • 开发者明确知道哪些操作会被向量化
  • 便于性能分析和调优
  • 代码重构不会意外破坏向量化

接着是优雅降级(Graceful Degradation)。

如果目标 CPU 不支持某些向量操作,Vector API 会自动回退到功能等效的标量实现,确保程序正确性。在部分场景下,即使回退后的性能也能与手动展开的标量循环竞争。

然后是,平台无关的 API 设计。

API 本身是 CPU 架构无关的。同一份 Java 代码可以在 x64(SSE/AVX)和 AArch64(NEON/SVE)上运行,由 JVM 在运行时选择最优指令序列。社区甚至已经开始在 RISC-V 上的移植工作。

再然后是丰富的操作支持。

  • Lane-wise 操作:加、减、乘、除、位运算等
  • Cross-lane 操作:归约(如求和)、排列、洗牌
  • 掩码操作:支持条件执行,模拟控制流
  • 超越函数:通过 SVML/SLEEF 支持三角函数、指数、对数等

最后是与 Project Panama 的协同。

Vector API 利用 Panama 的 FFM(Foreign Function & Memory)API 链接原生数学库,大幅减少了 HotSpot 内部的 C++ 胶水代码,提升了可维护性。

总的来说,虽然这个 JEP 仍处于孵化器阶段,但 Vector API 已经可以在生产环境中试用(需添加 --add-modules jdk.incubator.vector)。

import jdk.incubator.vector.*;

public class VectorDemo {
    public static void main(String[] args) {
        var species = FloatVector.SPECIES_PREFERRED;
        float[] a = {1.0f, 2.0f, 3.0f, 4.0f};
        float[] b = {5.0f, 6.0f, 7.0f, 8.0f};
        float[] c = new float[4];

        var va = FloatVector.fromArray(species, a, 0);
        var vb = FloatVector.fromArray(species, b, 0);
        var vc = va.add(vb);
        vc.intoArray(c, 0);

        // c = [6.0, 8.0, 10.0, 12.0]
    }
}

就是不知道有没有大佬或老外,开始在大规模数值计算(科学模拟、图像处理)、机器学习推理(向量点积、矩阵乘法)、密码学算法(AES、SHA 的向量化实现)、金融分析(大规模数据聚合)等方面进行使用。

结语

正如老外所说,Vector API 的 12 次孵化,不是“难产”,而是“精工细作”的体现。它像一位耐心的工匠,在等待 Project Valhalla 这把“绝世好剑”铸成后,再将自己打磨至完美。

对于 Java 生态而言,这意味着当 Vector API 最终转正时,它将不仅仅是一个高性能计算 API,更是 Valhalla 项目价值的有力证明,Java 依然能在保持语言优雅的同时,触及硬件性能的极限。

只是这个时间等的太久太久了,一代程序员老去了,云原生也错过了,AI 时代也要拱手让人了。

业余草公众号

最后,欢迎关注我的个人微信公众号:业余草(yyucao)!可加作者微信号:xttblog2。备注:“1”,添加博主微信拉你进微信群。备注错误不会同意好友申请。再次感谢您的关注!后续有精彩内容会第一时间发给您!原创文章投稿请发送至532009913@qq.com邮箱。商务合作也可添加作者微信进行联系!

本文原文出处:业余草: » JDK 27,从 JEP 338 到 JEP 537 一个性能提升 16 倍的 API