JEPs Part I

JEP 11

https://openjdk.java.net/jeps/11

JEP 11(Java Enhancement Proposal 11)提出了“孵化模块”的概念,这是一种将非最终版本的API和非最终工具提供给开发者的方法,以便在将来的版本中进行最终化或删除。孵化模块的目的是在标准化之前,让感兴趣的社区成员有机会使用和反馈这些新的特性,从而减少在Java SE平台和JDK中犯下代价高昂的错误的可能性。

孵化模块的特点包括:

  1. 它们包含正在开发中、尚未足够成熟、有待进一步经验和反馈的API或工具。
  2. 孵化模块的名称以jdk.incubator.前缀开头,无论是导出孵化API还是包含孵化工具。
  3. 孵化API的包名也以jdk.incubator.前缀开头,仅由孵化模块导出。
  4. 孵化工具可能在命令行调用时使用jdk.incubator前缀,但不是必须的。
  5. 如果孵化API在将来被标准化或提升到某种稳定状态,其包名和模块将被重命名并从非孵化模块中导出。

孵化模块的过程和演变遵循以下指南:

  1. 定义孵化特征的JEP应明确指出孵化计划,并且孵化结果将是导出API/包含工具的孵化模块。
  2. 后来被推广到Java SE平台或其他JDK稳定状态的孵化特征,应有一个新的JEP来提出和记录这一变化。
  3. 如果孵化特征后来被删除,则不需要新的JEP。孵化模块和其包含的特征可能会被静默移除。

孵化模块与其他模块的关系如下:

  1. 孵化模块只能导出孵化API,即jdk.incubator命名空间下的包。
  2. 孵化模块不得导出受支持的JDK API或关键的内部API。
  3. 标准模块和非孵化JDK模块不得指定对孵化模块的传递依赖,也不得暴露孵化模块导出的类型。

孵化模块在JDK运行时映像中是可用的,但在默认情况下,它们不会被应用程序类路径上的应用程序解析。应用程序需要通过--add-modules命令行选项来请求解析孵化模块。孵化模块的文档将与JDK的其他API一起构建,并且在孵化API的JavaDoc中将明确警告该特性的孵化状态,并提醒该特性最终会被移除。


 


JEP 181

https://openjdk.java.net/jeps/181

JEP 181(Java Enhancement Proposal 181)是关于引入“nests”的提案,这是一种访问控制上下文,与Java编程语言中现有的嵌套类型概念相一致。这个提案的目的是允许逻辑上属于同一代码实体的类之间相互访问彼此的私有成员,而无需编译器插入桥接方法来放宽访问权限。

在当前的JVM访问规则下,私有成员之间的访问是不被允许的,因此编译器必须通过添加桥接方法来实现这一目标。这些桥接方法破坏了封装性,增加了部署的应用程序的大小,并可能使用户和工具感到困惑。为了简化编译器的任务、强化现有访问检查以及消除核心反射和MethodHandle API中的意外行为,JEP 181提出了将一组类文件定义为“nest”,其中nestmates共享一个公共的访问控制机制。

具体来说,JEP 181建议修改类文件格式以定义两个新的属性:NestMembers 和 NestHost。这样,就可以直接实现预期的结果,以一种更简单、更安全、更透明的方式。例如,在编译时,可以直接生成对私有成员的调用指令,而不是通过桥接方法间接调用。此外,此提案还涉及了核心反射API的改变,以便能够检查和查询新引入的类文件属性。

该提案的影响范围广泛,涉及到所有明确或隐含涉及访问控制的规格和API,包括Java虚拟机规范、核心反射API、MethodHandle查找规则等。同时,它也影响了其他工具,如类文件操作工具、字节码生成和处理工具等。

尽管JEP 181带来了一些复杂性,但它旨在提高效率、安全性和透明度,并为未来的增强功能奠定基础。


JEP 309


https://openjdk.java.net/jeps/309

JEP 309(Java Enhancement Proposal 309)的目标是为Java类文件格式扩展一个新的常量池形式,称为CONSTANT_Dynamic。这个新形式的目的是减少创建可实例化类文件常量的成本和干扰,从而为语言设计者和编译器实现者提供更广泛的表达能力和性能选项。

具体来说,CONSTANT_Dynamic常量会委托给引导方法进行解析,就像链接invokedynamic调用站点时那样。这种设计允许将复杂的常量数据存储在常量池中,并且可以由引导方法根据提供的静态参数动态创建。这类似于invokedynamic指令的处理方式,但不同的是,引导方法返回的不是CallSite对象,而是立即转换为所需类型的值。

为了支持CONSTANT_Dynamic,需要对类文件格式进行调整,并增加新的常量标签17。这个新常量包含两个组件:一个是引导方法的索引,另一个是表示预期类型的CONSTANT_NameAndType

JEP 309还计划调整JVM与引导方法之间的链接时间握手协议,使得invokedynamic使用的引导API同样适用于动态常量。此外,还将放松对引导方法参数列表处理的某些限制,以适应更复杂的常量。

成功实施JEP 309后,应能确保CONSTANT_Dynamic可用于任何当前允许通用常量池常量的环境,例如作为ldc指令的操作数,或者作为引导方法的静态参数。此外,还应考虑后续工作,例如支持大量聚合常量、进一步调整引导方法握手协议等。

这项工作的动机在于,随着invokedynamic的使用越来越广泛,存储复杂数据的需求也在增加。通过引入CONSTANT_Dynamic,可以使开发invokedynamic协议的开发者更加轻松地处理复杂的逻辑,从而提升程序性能和简化编译器逻辑。


JEP 334

https://openjdk.java.net/jeps/334

JEP 334(Java Enhancement Proposal 334)提出了一种新的API,用于模型化关键类文件和运行时构件的名义描述,特别是那些可以从常量池加载的常量。

在Java类文件中,常量池存储着类字节码指令的操作数。这些条目大致可以分为两类:一类是运行时构件,如类和方法;另一类是简单值,如字符串和整数。所有这些条目都被称为可加载常量,因为它们可以作为ldc指令("load constant")的操作数,也可能出现在invokedynamic指令的引导方法的静态参数列表中。执行ldcinvokedynamic指令会导致可加载常量被解析为一个标准Java类型的“活动”值,如ClassStringint

然而,使用标准Java类型来模拟可加载常量是不够的。例如,对于描述类的可加载常量来说,产生一个“活动”的Class对象依赖于类加载的正确性和一致性,而这可能会受到许多环境依赖性和失败模式的影响。因此,如果程序能够以纯粹名义性的、符号的形式操纵类和方法,以及其他不太知名的构件(如方法句柄和动态计算的常量),那么处理可加载常量的程序将会变得更加简单。

为了解决这个问题,JEP 334定义了一系列基于值的符号引用类型(JVMS 5.1),位于新的包java.lang.invoke.constant中,能够描述每种类型的可加载常量。这些符号引用以纯粹的名义形式描述可加载常量,独立于类加载或访问性上下文。对于一些类,它们本身就可以作为自己的符号引用(例如String)。对于可链接的常量,我们定义了一系列符号引用类型(ClassDescMethodTypeDescMethodHandleDescDynamicConstantDesc),它们包含了描述这些常量的名义信息。

JEP 334最初是作为JEP 303(针对ldcinvokedynamic指令的内置函数)的一个子特性提出的,但现在JEP 303依赖于JEP 334。


JEP 352

https://openjdk.java.net/jeps/352

JEP 352: Non-Volatile Mapped Byte Buffers

JEP 352 的目标是为 FileChannel API 添加新的JDK特定文件映射模式,以便创建引用非易失性内存的 MappedByteBuffer 实例。这个JEP的主要目的是确保客户端能够高效且一致地从Java程序访问和更新NVM。关键要素之一是确保缓冲区区域的个别写入(或小群组连续写入)可以被提交,而开销最小化,即确保任何可能仍在缓存中的更改被写回内存。

此外,JEP还提出了一个次要目标,即使用受限的JDK内部API来实现这种提交行为,允许除了 MappedByteBuffer 之外的其他类也可能需要提交NVM时使用。最后,相关目标还包括允许映射在NVM上的缓冲区被现有的监控和管理API跟踪。

JEP 352 提出的JDK特定API变更包括:

  1. 通过新模块公开一个新的枚举值,用于 FileChannel::map 方法创建映射在NVM设备文件上的只读或读写 MappedByteBuffer
  2. 发布一个 BufferPoolMXBean 来跟踪持久化的 MappedByteBuffer 统计信息。

JEP 352 还提出了内部JDK API变更,包括向 jdk.internal.misc.Unsafe 类添加新的 writebackMemory 方法,以确保指定地址范围内的任何修改都被写回到内存。

测试将需要在配备NVM设备的x64或AArch64主机上进行,并且运行适当的最新Linux内核版本。


JEP 412

https://openjdk.java.net/jeps/412

JEP 412: Foreign Function & Memory API (Incubator)

JEP 412 旨在引入一个API,通过该API,Java程序可以与Java运行时之外的外部代码和数据交互。通过高效调用外部函数(即JVM外的代码)以及安全地访问外部内存(即不由JVM管理的内存),该API使Java程序能够调用本地库和处理本地数据,而不必依赖脆弱和不安全的JNI。

历史背景:
该API是先前两个孵化API——外部内存访问API和外部链接器API——的演变。外部内存访问API首次由JEP 370提出,并计划作为孵化API在Java 14中推出;之后在Java 15和Java 16中分别通过JEP 383和JEP 393进行了重新孵化。外部链接器API首次由JEP 389提出,并计划作为孵化API在Java 16中推出。

目标:

  1. 易用性:用更优的纯Java开发模式替换Java本地接口(JNI)。
  2. 性能:提供与现有API(如JNI和sun.misc.Unsafe)相当甚至更好的性能。
  3. 通用性:提供处理不同种类的外部内存(如本地内存、持久内存和管理堆内存)的方法,并随着时间的推移适应其他平台(如32位x86)和其他语言编写的外部函数(如C++、Fortran)。
  4. 安全性:禁用默认的不安全操作,仅允许在应用开发者或最终用户明确选择后启用。

非目标:

  1. 不重新实现JNI或改变JNI的任何方面;
  2. 不重新实现遗留Java API,如sun.misc.Unsafe;
  3. 不提供从原生代码头文件机械生成Java代码的工具;
  4. 不改变Java应用程序与本地库交互的打包和部署方式(如通过多平台JAR文件)。

动机:
Java平台始终为希望超越JVM并与其他平台互动的库和应用开发者提供了丰富的基础。Java API方便可靠地暴露了非Java资源,无论是访问远程数据(JDBC)、调用Web服务(HTTP客户端)、为远程客户端提供服务(NIO通道)还是与本地进程通信(Unix域套接字)。不幸的是,Java开发者在访问位于JVM所在同一机器上但运行在JVM之外的重要的非Java资源时仍然面临重大障碍。


JEP 419

https://openjdk.java.net/jeps/419

JEP 419: Foreign Function & Memory API (Second Incubator)

JEP 419 旨在引入一个API,通过该API,Java程序可以与Java运行时之外的外部代码和数据交互。通过高效调用外部函数(即JVM外的代码)以及安全地访问外部内存(即不由JVM管理的内存),该API使Java程序能够调用本地库和处理本地数据,而不必依赖脆弱和不安全的JNI。

历史背景:
外函数和内存API是由JEP 412提出的,并计划在2021年中期的Java 17中作为一个孵化API。它结合了之前的两个孵化API:外部内存访问API和外部链接器API。本JEP提议根据反馈进行改进,并在Java 18中重新孵化API。

目标:

  1. 易用性:用更优的纯Java开发模式替换Java本地接口(JNI)。
  2. 性能:提供与现有API(如JNI和sun.misc.Unsafe)相当甚至更好的性能。
  3. 通用性:提供处理不同种类的外部内存(如本地内存、持久内存和管理堆内存)的方法,并随着时间的推移适应其他平台(如32位x86)和其他语言编写的外部函数(如C++、Fortran)。
  4. 安全性:禁用默认的不安全操作,仅允许在应用开发者或最终用户明确选择后启用。

非目标:

  1. 不重新实现JNI或改变JNI的任何方面;
  2. 不重新实现遗留Java API,如sun.misc.Unsafe;
  3. 不提供从原生代码头文件机械生成Java代码的工具;
  4. 不改变Java应用程序与本地库交互的打包和部署方式(如通过多平台JAR文件)。

动机:
Java平台始终为希望超越JVM并与其他平台互动的库和应用开发者提供了丰富的基础。Java API方便可靠地暴露了非Java资源,无论是访问远程数据(JDBC)、调用Web服务(HTTP客户端)、为远程客户端提供服务(NIO通道)还是与本地进程通信(Unix域套接字)。不幸的是,Java开发者在访问位于JVM所在同一机器上但运行在JVM之外的重要的非Java资源时仍然面临重大障碍。


JEP 424


https://openjdk.java.net/jeps/424

JEP 424: Foreign Function & Memory API (Preview)

JEP 424 旨在介绍一种API,通过该API,Java程序可以与Java运行时之外的外部代码和数据交互。通过高效调用外部函数(即JVM外的代码)以及安全地访问外部内存(即不由JVM管理的内存),该API使Java程序能够调用本地库和处理本地数据,而不必依赖脆弱和不安全的JNI。这是一个预览API。

历史背景:
外函数和内存(FFM)API结合了早期的孵化API:外部内存访问API(JEPs 370、383和393)和外部链接器API(JEP 389)。FFM API在JDK 17中通过JEP 412孵化,并在JDK 18中通过JEP 419重新孵化。此JEP基于在孵化期间收到的反馈对FFM API进行了细化。在JDK 19中,外函数和内存API不再是孵化状态;相反,它是一个预览API。

目标:

  1. 易用性:用更优的纯Java开发模式替换Java本地接口(JNI)。
  2. 性能:提供与现有API(如JNI和sun.misc.Unsafe)相当甚至更好的性能。
  3. 通用性:提供处理不同种类的外部内存(如本地内存、持久内存和管理堆内存)的方法,并随着时间的推移适应其他平台(如32位x86)和其他语言编写的外部函数(如C++、Fortran)。
  4. 安全性:允许程序对外部内存执行不安全操作,但默认会警告用户此类操作。

非目标:

  1. 不重新实现JNI或改变JNI的任何方面;
  2. 不重新实现遗留Java API,如sun.misc.Unsafe;
  3. 不提供从原生代码头文件机械生成Java代码的工具;
  4. 不改变Java应用程序与本地库交互的打包和部署方式(如通过多平台JAR文件)。

动机:
Java平台始终为希望超越JVM并与其他平台互动的库和应用开发者提供了丰富的基础。Java API方便可靠地暴露了非Java资源,无论是访问远程数据(JDBC)、调用Web服务(HTTP客户端)、为远程客户端提供服务(NIO通道)还是与本地进程通信(Unix域套接字)。不幸的是,Java开发者在访问位于JVM所在同一机器上但运行在JVM之外的重要的非Java资源时仍然面临重大障碍。

描述:
FFM API定义了类和接口,以便库和应用中的客户端代码可以:

  1. 分配外部内存(MemorySegment、MemoryAddress和SegmentAllocator);
  2. 操纵和访问结构化外部内存(MemoryLayout、VarHandle);
  3. 控制外部内存的分配和释放(MemorySession);
  4. 调用外部函数(Linker、FunctionDescriptor和SymbolLookup)。

FFM API位于java.lang.foreign包中。


JEP 425

https://openjdk.java.net/jeps/425

JEP 425(Java Enhancement Proposal 425)提出了名为“虚拟线程”的特性,旨在通过引入轻量级的线程来显著降低编写、维护和高吞吐量并发应用程序的难度。虚拟线程是一种不同于传统平台线程的新型线程实现,它们能够在单个操作系统线程上运行多个虚拟线程,从而极大地提高了硬件利用率。

虚拟线程的主要目标是:

  1. 使采用每请求一线程风格的服务器应用程序能够以接近最优的硬件利用率进行扩展。
  2. 使使用java.lang.Thread API的现有代码能够以最小的变更采用虚拟线程。
  3. 使现有的JDK工具能够容易地对虚拟线程进行故障排除、调试和性能分析。

虚拟线程的设计原则是,当任务拆分为并发子任务时,它们都应该返回到同一个地方,即任务的代码块。这使得多线程代码的维护、可靠性和可观测性与单线程代码相当。

虚拟线程的引入不会改变Java的基本并发模型,也不会提供新的数据并行性构造。它们保留了Java平台的线程-每请求风格,同时利用硬件达到最优效果。虚拟线程不需要学习新概念,但可能需要摒弃应对当前线程成本高的习惯。

虚拟线程的主要特点包括:

  1. 它们是轻量级的线程实现,由JDK提供,而不是操作系统。
  2. 它们可以在单个操作系统线程上运行多个虚拟线程,有效地共享资源。
  3. 它们支持线程局部变量和线程中断,与平台线程类似。
  4. 它们可以无缝地与现有的Java代码集成,无需显式地将控制权交回调度器。

虚拟线程的引入不会影响现有的线程池和ExecutorService的使用,但建议不要对虚拟线程进行池化,因为每个虚拟线程都旨在在其生命周期内只运行一个任务。

虚拟线程的引入还包括了对JDK工具集的更新,以确保它们能够正确地处理大量的虚拟线程。例如,JDK Flight Recorder (JFR) 现在支持虚拟线程的事件记录,而jcmd 命令现在可以输出新的JSON格式的线程转储,以更清晰地展示虚拟线程的状态。

总之,虚拟线程为Java平台带来了一种新的并发模型,它既保持了与现有Java平台的兼容性,又充分利用了现代硬件的能力,有望成为未来高吞吐量并发应用程序的首选解决方案。


JEP 426
 

https://openjdk.java.net/jeps/426

JEP 426: Vector API (Fourth Incubator)

JEP 426 旨在引入一个API,通过该API,Java程序可以在支持的CPU架构上可靠地将向量计算编译为最优的向量指令,从而实现比等效标量计算更优越的性能。

历史背景:
向量API最初由JEP 338提出,并在JDK 16中作为孵化API集成。随后,通过JEP 414(集成到JDK 17)和JEP 417(JDK 18)进行了多轮孵化。

主要变化包括:

  1. 增强API以使用JEP 424中定义的MemorySegments加载和存储向量。
  2. 添加两个新的跨通道向量操作,压缩(compress)及其逆操作展开(expand),以及相应的向量掩码压缩操作。
  3. 扩展支持的位运算整数值操作,包括计数单比特、前导零位数、尾随零位数、反转位序、反转字节序和压缩与展开位。

目标:

  1. 清晰简洁的API:能够明确且简洁地表达各种向量计算,包括循环内组合的向量操作序列,可能包含控制流。
  2. 平台无关性:API应不受CPU架构限制,支持多种架构上的向量指令实现。
  3. 在x64和AArch64架构上可靠地编译向量操作并达到高性能。
  4. 优雅降级:在某些情况下,向量计算无法完全用向量指令序列表示时,实现应能优雅降级并保持功能。

非目标:

  1. 不增强现有的HotSpot自动向量化算法。
  2. 不支持除x64和AArch64之外的CPU架构上的向量指令。
  3. 不支持C1编译器。
  4. 不保证严格浮点计算的支撑,如Java平台对标量操作所要求的。

动机:
向量计算涉及一系列向量上的操作,其中向量通常包含固定数量的标量值。向量操作可以显著提高性能,因为它们可以在单个CPU周期内执行更多的工作。

描述:
向量由抽象类Vector<E>表示,类型变量E是向量覆盖的标量原始整型或浮点元素类型的装箱类型。向量还具有定义其大小的形状。向量的长度即向量的大小除以元素大小。

操作分为两类:

  1. 逐道(lane-wise)操作,例如加法,适用于每个向量通道。
  2. 跨通道(cross-lane)操作,例如置换或归约操作。

为了减少API的表面复杂性,我们为每种操作类别定义了集合方法。这些方法接受操作常数作为输入,这些常数是VectorOperator.Operator类的实例,定义于VectorOperators类中的静态最终字段。

向量比较操作产生掩码,可用于其他操作以选择性地操作某些通道,从而模拟流程控制。


JEP 428


https://openjdk.java.net/jeps/428

JEP 428(Java Enhancement Proposal 428)提出了名为“结构化并发”的特性,旨在简化多线程编程。结构化并发通过将不同线程中运行的多个任务视为一个工作单位,从而简化错误处理和取消操作,提高可靠性,并增强可观测性。

结构化并发的主要目标是提高多线程代码的可维护性、可靠性和可观测性。它提倡一种并发编程风格,可以消除因取消和关闭而产生的常见风险,例如线程泄露和取消延迟。

结构化并发不打算取代java.util.concurrent包中的任何并发构造,如ExecutorServiceFuture,也不打算定义Java的结构化并发API的最终版本。相反,它提供了一个孵化API,供第三方库或在未来的JDK版本中定义其他结构化并发构造。

结构化并发特别适用于虚拟线程,后者是由JDK实现的轻量级线程。许多虚拟线程共享相同的操作系统线程,允许多达数百万个虚拟线程。这使得服务器应用程序可以使用结构化并发一次处理数千或数百万个传入请求。

结构化并发API的核心类是StructuredTaskScope,它允许开发人员将任务组织成一个并发子任务的家族,并将它们作为一个单位进行协调。子任务在其自己的线程中执行,通过单独分叉它们然后作为一个单位加入它们,并可能作为一个单位取消它们。

使用StructuredTaskScope的一般工作流程如下:

  1. 创建一个范围。创建范围的线程是其所有者。
  2. 在范围内分叉并发子任务。
  3. 范围内的任何分叉,或其所有者,可以随时调用范围的shutdown()方法来请求取消所有剩余的子任务。
  4. 范围的所有者作为一个单元加入范围。所有者可以调用范围的join()方法,这将阻塞直到所有的分叉都已经完成(成功或不成功)或通过shutdown()被取消。
  5. 处理分叉中的任何错误并处理结果。
  6. 关闭范围,通常通过try-with-resources隐式完成。这将关闭范围并等待任何落后的分叉完成。

结构化并发通过强制在运行时强制执行结构化使用,从而在并发操作中引入结构和顺序。例如,尝试从不在范围的树层次结构中的线程调用fork(Callable)将导致异常。

结构化并发还扩展了由JEP 425新增的JSON线程转储格式,以显示StructuredTaskScope将线程分组为层次结构。这使得观察工具能够清楚地展示出由结构化并发所施加的树状结构,从而帮助开发人员更好地理解和调试并发程序。


JEP 429


https://openjdk.java.net/jeps/429

JEP 429(Java Enhancement Proposal 429)介绍了名为“作用域值”的特性,这是一种允许在大型程序的不同组件间安全高效地共享不可变数据的机制。作用域值主要用于替代传统的线程局部变量,尤其是在大量使用虚拟线程的场景中。

作用域值的设计目标包括易用性、可理解性、健壮性和性能。它们旨在简化数据流推理,让共享数据的生命周期在代码结构中清晰可见,并确保只有合法的调用者才能获取共享数据。由于作用域值是不可变的,因此它们可以被大量线程共享,并允许运行时优化。

作用域值具有以下特点:

  1. 它们是不可变的,一旦写入后就无法更改,确保了数据的安全共享。
  2. 它们的生命周期是有限的,仅在一定范围内有效,避免了长期内存泄漏的风险。
  3. 它们可以被继承,子线程可以自动继承父线程的作用域值,从而实现了跨线程的数据共享。

作用域值的使用方式类似于线程局部变量,但提供了更多的控制和灵活性。它们可以通过ScopedValue.where(...)run(...)方法绑定到特定线程,并在该线程的执行期间内可用。

作用域值特别适合于Web框架等场景,在这些场景中,不同的组件需要共享数据,但又不能简单地通过方法参数传递。例如,服务器组件可以在处理请求的线程中创建一个作用域值,并将其绑定到一个Principal对象,然后在数据访问组件中使用这个作用域值来验证数据库访问权限。

此外,作用域值还支持重新绑定和继承,使得它们在处理嵌套调用和子线程时更加灵活。重新绑定允许在一个线程中对同一个作用域值绑定不同的值,而继承则使得子线程可以自动获得父线程中绑定的值。

总的来说,作用域值提供了一种比线程局部变量更简洁、安全和高效的共享数据方式,尤其适合于现代Java应用中大量使用虚拟线程的环境。


JEP 430


https://openjdk.java.net/jeps/430

JEP 430(Java Enhancement Proposal 430)提议在Java编程语言中引入一种名为“字符串模板”的新特性。字符串模板结合了文本字面量和嵌入的表达式,并通过模板处理器生成专门的结果。这是一个预览版语言特性和API。

字符串模板的主要目标是简化Java程序的编写,使程序员能够方便地在字符串中包含运行时计算出的值。它增强了混合文本和表达式的代码的可读性,无论是单行源代码还是跨多行的文本块。此外,字符串模板还提高了安全性,特别是在构造来自用户提供值的SQL语句和其他系统传递的字符串时。

字符串模板的设计理念是通过模板处理器来保证安全性,这些处理器负责验证和转换模板及其嵌入表达式的值。这使得字符串模板不仅限于构建字符串,还可以根据特定领域的规则将结构化文本转换为任何类型的对象。

JEP 430引入了两个预定义的模板处理器:STRFMTSTR是一个简单的字符串插值处理器,它将模板中的每个嵌入表达式替换为其值。而FMT则类似于STR,但还能解释出现在嵌入表达式左侧的格式说明符,这些格式说明符与java.util.Formatter中的定义相同。

除了预定义的模板处理器外,开发者也可以自定义模板处理器,以处理特定的模板需求。例如,可以创建一个用于数据库查询的模板处理器,该处理器首先从字符串模板中创建SQL查询字符串,然后使用该查询字符串创建一个JDBC PreparedStatement,并将它的参数设置为嵌入表达式的值。

总的来说,字符串模板提供了一种灵活且安全的字符串组合机制,它借鉴了其他编程语言中的字符串插值概念,但更加注重安全性和易用性。


JEP 434

https://openjdk.java.net/jeps/434

JEP 434: Foreign Function & Memory API (Second Preview)

JEP 434 旨在介绍一种API,通过该API,Java程序可以与Java运行时之外的外部代码和数据交互。通过高效调用外部函数(即JVM外的代码)以及安全地访问外部内存(即不由JVM管理的内存),该API使Java程序能够调用本地库和处理本地数据,而不必依赖脆弱和不安全的JNI。这是一个预览API。

历史背景:
外函数和内存(FFM)API结合了之前的孵化API:外部内存访问API(JEPs 370、383和393)和外部链接器API(JEP 389)。FFM API在JDK 17中通过JEP 412孵化,并在JDK 18中通过JEP 419重新孵化,然后在JDK 19中通过JEP 424首次预览。

主要变化包括:

  1. 统一了MemorySegmentMemoryAddress抽象(现在将内存地址建模为零长度的内存段);
  2. 增强了封闭的MemoryLayout层次结构,以促进在switch表达式和语句中使用模式匹配(JEP 433);
  3. MemorySession拆分为ArenaSegmentScope,以便在不同维护边界之间共享段。

目标:

  1. 易用性:用更优的纯Java开发模式替换Java本地接口(JNI)。
  2. 性能:提供与现有API(如JNI和sun.misc.Unsafe)相当甚至更好的性能。
  3. 通用性:提供处理不同种类的外部内存(如本地内存、持久内存和管理堆内存)的方法,并随着时间的推移适应其他平台(如32位x86)和其他语言编写的外部函数(如C++、Fortran)。
  4. 安全性:允许程序在外部内存上执行不安全操作,但默认会警告用户此类操作。

非目标:

  1. 不重新实现JNI或改变JNI的任何方面;
  2. 不重新实现遗留Java API,如sun.misc.Unsafe;
  3. 不提供从原生代码头文件机械生成Java代码的工具;
  4. 不改变Java应用程序与本地库交互的打包和部署方式(如通过多平台JAR文件)。


JEP 442

https://openjdk.java.net/jeps/442


JEP 442: Foreign Function & Memory API (Third Preview)

JEP 442 旨在介绍一种API,通过该API,Java程序可以与Java运行时之外的外部代码和数据交互。通过高效调用外部函数(即JVM外的代码)以及安全地访问外部内存(即不由JVM管理的内存),该API使Java程序能够调用本地库和处理本地数据,而不必依赖脆弱和不安全的JNI。这是一个预览API。

历史背景:
外函数和内存(FFM)API在JDK 19中通过JEP 424首次预览,然后在JDK 20中通过JEP 434再次预览。本JEP提议第三次预览,以纳入基于反馈的改进。在本版中,我们做了以下改动:

  1. 将原生段的生命周期管理集中在Arena接口中;
  2. 使用一个新元素增强布局路径,以解引用地址布局;
  3. 为不会回调到Java的短生命期函数提供了链接器选项(例如,clock_gettime);
  4. 提供了一个基于libffi的后备本地链接器实现,以方便移植;
  5. 移除了VaList类。

目标:

  1. 易用性:用更优的纯Java开发模式替换Java本地接口(JNI)。
  2. 性能:提供与现有API(如JNI和sun.misc.Unsafe)相当甚至更好的性能。
  3. 通用性:提供处理不同种类的外部内存(如本地内存、持久内存和管理堆内存)的方法,并随着时间的推移适应其他平台(如32位x86)和其他语言编写的外部函数(如C++、Fortran)。
  4. 安全性:允许程序在外部内存上执行不安全操作,但默认会警告用户此类操作。

JEP 448

https://openjdk.java.net/jeps/448

JEP 448: Vector API (Sixth Incubator)

JEP 448 旨在引入一个API来表示向量计算,这些计算能够在支持的CPU架构上在运行时可靠地编译为最优的向量指令,从而实现比等效标量计算更优越的性能。该提案提出在JDK 21中重新孵化API,与JDK 20相比,API进行了一些小的增强。

历史背景:
向量API最初由JEP 338提出,并在JDK 16中作为孵化API集成。随后,通过JEP 414(集成到JDK 17)、JEP 417(JDK 18)、JEP 426(JDK 19)和JEP 438(JDK 20)进行了多轮孵化。

主要变化包括:

  1. 在向量掩码中添加异或(xor)操作。
  2. 提高向量洗牌性能,特别是在重新排列向量元素以及向量之间转换时。

目标:

  1. 清晰简洁的API:能够明确且简洁地表达各种向量计算,包括循环内组合的向量操作序列,可能包含控制流。
  2. 平台无关性:API应不受CPU架构限制,支持多种架构上的向量指令实现。
  3. 在x64和AArch64架构上可靠地编译向量操作并达到高性能。
  4. 优雅降级:在某些情况下,向量计算无法完全用向量指令序列表示时,实现应能优雅降级并保持功能。
  5. 与Project Valhalla对齐:长期目标是利用Project Valhalla对Java对象模型的增强。

非目标:

  1. 不增强现有的HotSpot自动向量化算法。
  2. 不支持除x64和AArch64之外的CPU架构上的向量指令。
  3. 不支持C1编译器。
  4. 不保证严格浮点计算的支撑,如Java平台对标量操作所要求的。

动机:
向量计算涉及一系列向量上的操作,其中向量通常包含固定数量的标量值。向量操作可以显著提高性能,因为它们可以在单个CPU周期内执行更多的工作。

描述:
向量由抽象类Vector<E>表示,类型变量E是向量覆盖的标量原始整型或浮点元素类型的装箱类型。向量还具有定义其大小的形状。向量的长度即向量的大小除以元素大小。

操作分为两类:

  1. 逐道(lane-wise)操作,例如加法,适用于每个向量通道。
  2. 跨通道(cross-lane)操作,例如置换或归约操作。

为了减少API的表面复杂性,我们为每种操作类别定义了集合方法。这些方法接受操作常数作为输入,这些常数是VectorOperator.Operator类的实例,定义于VectorOperators类中的静态最终字段。

向量比较操作产生掩码,可用于其他操作以选择性地操作某些通道,从而模拟流程控制。

示例:
使用向量API进行向量计算,与标量计算相比,可以实现更高效的代码生成,例如在支持AVX的x64处理器上生成类似汇编代码的机器码。

未来工作:

  1. 预期将向量类声明为值类,以符合Project Valhalla的提议。
  2. 考虑添加对IEEE浮点二进制16位值(float16值)的支持。
  3. 预计将增强实现以提高包含向量化代码的循环优化,并逐步改进性能。

JEP 454

https://openjdk.java.net/jeps/454

JEP 454: Foreign Function & Memory API

JEP 454 旨在介绍一种API,通过该API,Java程序可以与Java运行时之外的外部代码和数据交互。通过高效调用外部函数(即JVM外的代码)以及安全地访问外部内存(即不由JVM管理的内存),该API使Java程序能够调用本地库和处理本地数据,而不必依赖脆弱和不安全的JNI。

历史背景:
外函数和内存(FFM)API最初由JEP 424提出,并在JDK 19中作为预览特性引入。随后,通过JEP 434(JDK 20)和JEP 442(JDK 21)进行了进一步的细化。本JEP提议对FFM API进行最终的完善,以纳入基于持续经验和反馈的小幅改进。

主要变化包括:

  1. 提供了一个新的链接器选项,允许客户端将堆段传递给下调用方法句柄;
  2. 引入了Enable-Native-Access JAR文件清单属性,允许可执行JAR文件中的代码调用受限制的方法,而无需使用--enable-native-access命令行选项;
  3. 允许客户端编程方式构建C语言函数描述符,避免平台特定的常量;
  4. 改进了对原生内存中变长数组的支持;
  5. 为原生字符串添加了任意字符集的支持。

See

https://cr.openjdk.org/~vlivanov/talks/2017_Vectorization_in_HotSpot_JVM.pdf

  • 25
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

P("Struggler") ?

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值