JDK20来啦

发布一下 0 0

发布概览

JDK20来啦[V5][给力],在每6个月的发行节奏下,这个版本是第11个按时发布的特性发行版。注意不是LTS(长期支持版本版本哦,不过大家可以继续往下看↓↓↓,文章后面会跟大家一起分享它有哪些新特性。下图是自JDK8后的一个发布节奏直方图。横轴代表发布周期,纵轴为各版本的特性数量。

JDK20来啦

java8及后期发布节奏图

开源的力量

众所周知,Java真的是开源界的先驱,即使Oracle收购了它,也阻挡不了开源的进程。不论从Oracle自17开始重新宣布免费商用还是Oracle出台了混合许可(商业+开源),Oralce也有意让开源各社区力量来完善和增强Java,想了解OracleJDK和OpenJDK的区别可以参考我的一篇文章《OralceJDK于OpenJDK的区别与联系》。下图可以看出JDK16及JDK17开始的许可授权声明变化及JDK11后增加了GPL许可。GPL具体是啥,可以参考这篇文章《什么是GNU、GPL?为什么会如此重要?》

JDK20来啦

JDK16许可授权

JDK20来啦

JDK17许可授权


JDK20来啦

Oracle推出开源协议

在开源力量的推动下,下面来分析下JDK11到20各组织力量的参与程度。

先引用下Sharat Chander(资深专家和Java产品经理)的几段话。

JDK20来啦

Sharat Chander阐述Java20的变化背景及数据

第一段:

The rate of change over time in the JDK releases has remained largely constant for years, but under the six-month cadence the pace at which production-ready features and improvements are delivered has sharply increased

翻译后:

过去JDK的发行版本带来的变化长期稳定保持一个水平不变(理解不太活跃),但是在每6个月发布一次这样的节奏带动下不管是生产就绪版特性还是已发布的改进版特性的变化都得到了明显的增长。

第二段:

Instead of making tens of thousands of fixes and delivering close to one hundred JEPs (JDK Enhancement Proposals) every few years, as we did with yesteryear Major Releases, enhancements are delivered in leaner Feature Releases on a more manageable, predictable, six-month schedule. The changes range from significant new features to small enhancements to routine maintenance, bug fixes, and documentation improvements. Each change is represented in a single commit for a single issue in the JDK Bug System.

翻译后:

不像往常主要版本中所做的那样,每隔几年进行数以万计的修复并交付近100个 JEP (JDK 增强提案) ,增强提案是通过更简洁的功能发布,以更易于管理、可预测、每6个月周期交付的。这些变化包括重要的新特性、小的增强、日常维护、 bug 修复和文档改进。每个更改都在 JDK Bug System 中针对单个问题的单个提交中表示。

不懂JEP及相关概念的可以阅读我的这篇文章《聊聊JAVA中JCP,JEP,JSR,JLS的定义与区别》

第三段:

of the 21,604 JIRA issues marked as fixed in Java 11 through Java 20 at the time of their GA, 15,420 were completed by people working for Oracle while 6,184 were contributed by individual developers and developers working for other organizations. Going through the issues and collating the organization data from assignees results in the following chart of organizations sponsoring the development of contributions in Java:

翻译后:

从Java11到Java20 在它们GA期间有21604个JIRA问题被标记为已解决,其中15420个是由Oracle内部人员完成的,而6184个是个人开发者和其它组织的开发者参与贡献完成的。下图可以清晰的看到各组织参与贡献的比例


译文中GA的意思是General Availability(正式发布版或稳定版本)JIRA是一个问题缺陷跟踪工具,可以类比中国这边用的禅道这样的bug工具。

JDK20来啦

各组织关于issues修复占比


大家可以看到除了Oracle占了大头外(毕竟人家目前代表Java官方),其它红帽,SAP,亚马逊等顶尖公司都参与其中,包括中国的AliBaba(阿里巴巴)和Tencent(腾讯)。不得不说这个开源力量真的强大[中国赞]。

一番鼓吹之下,下面就来说说Java20的新特性↓↓↓

Java20 新特性

伴随着上千个关于性能,稳定性和安全更新,Java20发布了几十个新特性和增强,其中七个是非常重要和有意义的对于之前提出的JEP来说。其中有四个预览特性和三个孵化中的特性。

有一些重要的更新但是不需要参考JEP(毕竟不是每个功能都要参考JEP的,我理解JEP更多是一些创新和大的特性),这些非JEP变化如下:

  • (D)TLS Key Exchange Named Groups
  • Add GarbageCollectorMXBean for Remark and Cleanup Pause Time in G1
  • Provide ChaCha20 Intrinsics on x86_64 and aarch64 Platforms
  • Unicode 15.0 Support
  • Improved Control of G1 Concurrent Refinement Threads
  • Support for CLDR Version 42
  • New JFR Event: jdk.InitialSecurityProperty
  • New JFR Event: jdk.SecurityProviderService
  • Improved Preview API Page
  • New jmod --compress Command Line Option
  • Grapheme Support in BreakIterator
  • Update Timezone Data to 2022c
  • Auto-Generated IDs in JavaDoc Headings

相比非JEP的变化,其实大部分人还是比较关注的是JEP提出的特性。

首先给大家先科普下JEP的预览特性和孵化特性。

预览特性:

  • 首先它是已经完全实现了Java语言层面和虚拟机层面的规范的。
  • 在确保未来的Release版本中永久可用之前,先让它们在 JDK Feature Releases 中可用,以允许开发人员根据实际使用情况进行反馈。这也为工具供应商提供了在特性最终成为 JavaSE 标准之前致力于继续支持特性的机会。
  • 可以产生多轮预览,比如:JDK19中为第一轮,JDK20中为第二轮

孵化特性

  • 允许将非最终 API 和非最终工具交到开发人员和用户手中,以收集最终将提高 Java 平台质量的反馈,通俗的讲就是比预览特性还低一个层级。

还有个机制是这样的,先产生一系列JEP,然后根据JEP特性的孵化和开发程度,决定将哪些JEP特性在下个JDK版本中发布出来,并且这些JEP是分散在不同的项目中的。比如:Java20的7个JEP特性分别由Project Amber,Project Panama,Project Loom项目进行长期技术支持和维护。为了方便大家阅读,我整理一个表格如下:

项目名称

JEP

预览孵化版本

Project Amber(琥珀项目)

JEP 432 – Record模式

第二轮预览

JEP 433 – Switch模式匹配

第四轮预览

Project Panama(巴拿马项目)

JEP 434 - 外部函数和内存API

第二轮预览

JEP 438 - Vector API

第五轮孵化

Project Loom(织布机项目)

JEP 436 - 虚拟线程

第二轮预览

JEP 429 – 作用域值

孵化阶段

JEP 437 - 结构化并发

第二轮孵化

功能阐述及部分代码展示

  • JEP 432 – Record模式

使用Record模式增强 Java 编程语言,以解构记录值可以嵌套记录模式和类型模式,以支持强大的、声明性的和可组合的数据导航和处理形式

record Point(int x, int y) {}static void printSum(Object o) {    if (o instanceof Point p) {        int x = p.x();        int y = p.y();        System.out.println(x+y);    }}
  • JEP 433 – Switch模式匹配

可以简洁、安全地表达复杂的面向数据的查询

static String formatterPatternSwitch(Object obj) {    return switch (obj) {        case Integer i -> String.format("int %d", i);        case Long l    -> String.format("long %d", l);        case Double d  -> String.format("double %f", d);        case String s  -> String.format("String %s", s);        default        -> obj.toString();    };}
  • JEP 434 - 外部函数和内存API
// 1. Find foreign function on the C library pathLinker linker          = Linker.nativeLinker();SymbolLookup stdlib    = linker.defaultLookup();MethodHandle radixsort = linker.downcallHandle(stdlib.find("radixsort"), ...);// 2. Allocate on-heap memory to store four stringsString[] javaStrings = { "mouse", "cat", "dog", "car" };// 3. Use try-with-resources to manage the lifetime of off-heap memorytry (Arena offHeap = Arena.openConfined()) {    // 4. Allocate a region of off-heap memory to store four pointers    MemorySegment pointers = offHeap.allocateArray(ValueLayout.ADDRESS, javaStrings.length);    // 5. Copy the strings from on-heap to off-heap    for (int i = 0; i < javaStrings.length; i++) {        MemorySegment cString = offHeap.allocateUtf8String(javaStrings[i]);        pointers.setAtIndex(ValueLayout.ADDRESS, i, cString);    }    // 6. Sort the off-heap data by calling the foreign function    radixsort.invoke(pointers, javaStrings.length, MemorySegment.NULL, '\0');    // 7. Copy the (reordered) strings from off-heap to on-heap    for (int i = 0; i < javaStrings.length; i++) {        MemorySegment cString = pointers.getAtIndex(ValueLayout.ADDRESS, i);        javaStrings[i] = cString.getUtf8String(0);    }} // 8. All off-heap memory is deallocated hereassert Arrays.equals(javaStrings, new String[] {"car", "cat", "dog", "mouse"});  // true
  • JEP 438 - Vector API

引入一个 API 来表示在运行时可靠编译的向量计算,以支持 CPU 架构上的最佳向量指令,从而实现优于等效标量计算的性能

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()) {        // FloatVector va, vb, vc;        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;    }}
  • JEP 436 - 虚拟线程

轻量级线程,可减少编写、维护和观察高吞吐量并发应用程序的工作量

void handle(Request request, Response response) {    var url1 = ...    var url2 = ...     try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {        var future1 = executor.submit(() -> fetchURL(url1));        var future2 = executor.submit(() -> fetchURL(url2));        response.send(future1.get() + future2.get());    } catch (ExecutionException | InterruptedException e) {        response.fail(e);    }} String fetchURL(URL url) throws IOException {    try (var in = url.openStream()) {        return new String(in.readAllBytes(), StandardCharsets.UTF_8);    }}
  • JEP 429 – 作用域值

它支持在线程内和线程间共享不可变数据。这些变量优于线程局部变量,尤其是在使用大量虚拟线程时。作用域值允许在大型程序中的组件之间安全有效地共享数据,而无需求助于方法参数

class Server {    final static ScopedValue<Principal> PRINCIPAL =  ScopedValue.newInstance(); // (1)    void serve(Request request, Response response) {        var level     = (request.isAdmin() ? ADMIN : GUEST);        var principal = new Principal(level);        ScopedValue.where(PRINCIPAL, principal)                            // (2)                   .run(() -> Application.handle(request, response));    }}class DBAccess {    DBConnection open() {        var principal = Server.PRINCIPAL.get();                            // (3)        if (!principal.canOpen()) throw new  InvalidPrincipalException();        return newConnection(...);    }}
  • JEP 437 - 结构化并发

通过为结构化并发引入 API 来简化多线程编程。结构化并发将在不同线程中运行的多个任务视为单个工作单元,从而简化了错误处理和取消,提高了可靠性,并增强了可观察性

Response handle() throws ExecutionException, InterruptedException {    try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {        Future<String>  user  = scope.fork(() -> findUser());        Future<Integer> order = scope.fork(() -> fetchOrder());        scope.join();           // Join both forks        scope.throwIfFailed();  // ... and propagate errors        // Here, both forks have succeeded, so compose their results        return new Response(user.resultNow(), order.resultNow());    }}

版权声明:内容来源于互联网和用户投稿 如有侵权请联系删除

本文地址:http://0561fc.cn/208469.html