译者 | 晶颜
审校 | 重楼
Java的内部系统和语法在不断发展,这些变化主要是通过Java社区进程(JCP)和Java增强提案(JEPs)来实现的。JCP和JEP共同定义了描述、设计和引入JVM(Java虚拟机)新特性的路径。它们保持了Java语言和平台的动态性和社区的参与性。随着JDK 24发布日期的临近,现在是时候看看即将到来的JEP是如何完成这一进程的。
JEP进程的各个阶段
你可以在OpenJDK主页上查看JEP索引,获取所有JEP的目录,包括过去和现在提交给Java的JEP。概括来说,JEP是根据其发展阶段进行组织的:
- 正在运行的JEP(In-flight JEPs)是目前正在研究的提案,将包含在Java的未来版本中。这包括从预览和可用于实验的提案到最近被接受用于开发的提案的所有内容。这个集合中的所有提案都已经经过了审查,并且很可能在未来的Java版本中出现。
- 提交的JEP(Submitted JEPs)已经完成了创建过程,现在已经正式提交,但尚未被接受。一旦它们被接受,将进入In-flight阶段。
- JEP草案(Draft JEPs)是正在制定的提案,以便进入准备正式提交的状态。当这种情况发生时,它们将上升到Submitted JEPs状态。
- 交付的功能、基础设施和信息性JEP(informational JEPs)都是过去成功的JEP,它们已经成为JVM的一部分。有些甚至已经交付,然后由进一步的JEP进行改进。
- 撤回的JEP(Withdrawn JEPs)是指没有成功而被撤回的提案。
你可能还会注意到索引开头的进程JEP(Process JEP)。这些是帮助你理解和定义进程本身的程序性JEP。
有时候,较大的JEP会被分解成多个部分或阶段。例如,JEP 462:结构化并发(第二次预览版)在交付的功能集中有一个单独的条目。
目前最著名的In-flight JEP
目前有许多有趣的JEP正在开发中。下述所强调的主要是旨在调优和重构JVM以及扩展和增强语言的提案。
JEP 485:流收集器
流收集器(Stream Gatherers)使函数操作更具可定制性。流收集器API公开了一个称为收集器的低级操作符接口,开发人员可以使用收集器对流进行以前很难或不可能的操作,比如处理同构集合类型。
JEP 485提案是先前两轮预览——在JDK 23中交付的JEP 473以及在JDK 22中交付的JEP 461的更新版。该功能旨在增强 Stream API,使其能够支持自定义中间操作,让流式管道能够以一种不易通过现有内置中间操作实现的方式转换数据。
流收集器虽非每天都需要的功能,但当你需要它的时候,它还是很棒的。它把一个令人沮丧的边缘情况变成了一个简单的解决方案。
JEP 484:类文件API
类文件(Class-File)API针对的是库和框架开发人员,他们需要用额外的功能修饰Java程序的编译输出。这是Java中一个长期存在的方法。Java生态系统中有许多用于此类开发的工具,但是JDK的快速变化使得采用更加标准化的方法变得非常重要。
类文件API是用于解析、操作和输出框架或库的“.class”结构的标准机制。然后,其他开发人员工具(以及JDK本身)便可以在提供的输出上进行构建。
JEP 478:密钥派生函数API(预览)
JEP 478改进并扩展了Java处理密钥和哈希等加密元素的原生能力。它旨在使这些操作更加强大,包括前瞻性能力,以帮助抵御未来的量子计算攻击。
涉及密码学的开发人员将使用密钥派生函数(Key Derivation Function)API来处理诸如使用Argon2等高级算法的散列密码之类的事情。JEP 478升级了Java的内置加密支持,并为未来几年提供了更好的定位。
JEP 478目前是一个预览提案,这意味着它在成为官方功能之前可能还有一段路要走。
JEP 472:准备限制对JNI的使用
作为巴拿马项目(Project Panama)用外部函数内存API取代JNI的一部分,JEP 472表明JVM正在弃用Java本机接口。这个提案提醒了应用程序开发人员,JNI将在默认情况下受到限制。这个JEP关注的是使JNI和FFM API更加一致和安全。使用JNI或FFM的开发人员将受到此更改的影响,因为它要求显式启用这些特性,如果未启用则会发出警告。
JEP 468:派生记录创建(预览)
JEP 468提案通过派生创建记录来增强Java语言。由于记录是不可变的对象,开发人员经常会根据旧记录创建新记录,以建立新数据模型。派生创建可从现有记录派生出新记录,只需指定不同的组件即可,从而简化代码编写。
该提案的作者提供了一个例子,将现有的Point实例(nextLoc)在新的finalLoc实例中进行扩展:
Point finalLoc = nextLoc with {
x *= 2;
y *= 2;
z *= 2;
};
本例中的Point类引用一个三维整数记录。这消除了向Point类添加链接方法的需要。下面是使用链接法的例子:
Point finalLoc = nextLoc
with { x *= 2; }
with { y *= 2; }
with { z *= 2; };
总的来说,JEP是对记录功能的一个很好的补充。
JEP 198:轻量级JSON API
JEP 198中提出的功能备受开发人员青睐。处理JSON是现代编程中无法绕过的一个事实,它无处不在,而且有很好的存在理由。在JavaScript中使用JSON非常容易,而在Java中则需要第三方库。有时,这些API并不容易使用。
不幸的是,JEP 198起源于2014年,但自2017年以来一直没有更新。这是一个有价值的JEP例子,它处于运行状态,但却并非得到有效改进。希望未来能有更积极的发展。
JEP 479:移除Windows 32位x86端口
JDK 21已通过JEP 479完成了弃用32位Windows的工作。一旦该提案成为Java的一部分,Java平台将不再支持32位窗口。JEP描述了删除这些代码路径将如何简化JVM。
JEP 218:原始类型上的泛型
Java 泛型的早期妥协之一是泛型的类型变量只能用引用类型实例化,而不能使用原始类型。这既不方便(当想使用 List<int> 时只能用 List<Integer>),又很昂贵(装箱有性能开销)。
作为Valhalla项目的一部分,JEP 218是在泛型中使用原始类型的能力。这是对基本Java语法的重大改进,意味着大量的内部规划和重构。统一泛型和原语意味着我们摆脱了原语包装和(自动)装箱。这为彻底统一原语和对象以及引入值类型扫清了道路,且将是很长一段时间以来我们编写Java方式的最大变化。
JEP 483:提前类加载和链接
JEP 483是JVM团队致力于改进Java底层行为的一个很好的例子。最终的结果是一个更好的平台:一个启动和重新加载更快的平台。
总体思路是,JVM增加了快速加载类的方法,同时保留了其他领域的动态,从而加快了启动和预热时间。应用程序开发人员不需要做任何特别的事情来利用这个特性;在即将发布的HotSpot JVM版本中,我们将能免费获得它。
JEP 475: G1延迟屏障扩展
与JEP 483一样,JEP 475也是一种重构,应用程序开发人员不会直接使用它。相反地,它为实现垃圾收集例程的平台开发人员提高了HotSpot JVM的性能和可访问性。
该JEP建议将G1垃圾收集器的屏障扩展从C2 JIT编译器的早期阶段推迟到后期阶段,以此来简化G1垃圾收集器屏障的实现。这些屏障记录了有关应用程序内存访问的信息。目标是在使用G1收集器时减少C2的执行时间,这对于使Java成为更强大的云平台至关重要。
JEP 450:压缩对象头(实验)
作为另一个内部性能改进提案,JEP 450旨在减少Java对象在内存中的大小。实际测试表明,对象占用的堆空间大部分是对象头数据。这意味着,“将每个对象的标头从96位减少到64位可以把总体堆使用量提高10%以上,因为标头是每个对象的固定成本。较小的平均对象大小可以改善内存使用、GC压力和数据局部性。”
这是另一个受欢迎的内部重构,我们可以期待它无声地改进我们程序的运行方式。
JEP 111:正则表达式的附加Unicode结构
JEP 111扩展了正则表达式可以处理的字符类型,涵盖了更多的Unicode技术标准。具体来说,它添加了以下可以在字符串中处理的字符类型:
- Unicode名称属性:\N \{…\}
- 扩展Grapheme Clusters:\X
- Unicode换行序列,如TR#18 Line Boundaries:\R
- Perl风格的命名捕获组和捕获组结构:\g \{…\}
- 更完整的Unicode属性,如\p \{IsXXXX\}
- 水平/垂直空白符:\h \H \v \V
结语
本文只探讨了一些调优和重构JVM以及扩展和增强Java语言的提案,其他还有很多正在运行以及处于草案阶段的JEP提案。有兴趣的话,可以自行查看索引,以更好地了解Jave系统。
原文标题:12 Java Enhancement Proposals changing Java,作者:Matthew Tyson