JDK 8 - 14 新特性集合

JDK 8 - 14 新特性集合

Administrator 762 2020-04-05

写作备忘录,方便自己针对性学习

本篇引用内容占 95% 以上,且为简要记载,感谢文章最后提供帮助的各位博主

JDK 8[^1]

  • Lambda Expression 与函数式接口
    • Lambda 允许把函数作为一个方法的参数(函数作为参数传递到方法中)
  • 方法引用
    • 方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器
    • 与lambda联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码
  • Optional
    • Optional 类已经成为 JDK 8 类库的一部分,用来解决空指针异常
  • 默认方法
    • 默认方法就是一个在接口里面有了一个实现的方法
  • Stream API
    • 新添加的 Stream API(java.util.stream) 把真正的函数式编程风格引入到 Java
  • Date Time API
    • 加强对日期与时间的处理
  • Nashorn JavaScript 引擎
    • JDK 8 提供了一个新的Nashorn javascript引擎,它允许我们在 JVM 上运行特定的 javascript 应用
  • 重复注解
    • JDK 8 引入了重复注解的概念,打破了这个限制注解只能使用一次的限制,允许在同一个地方多次使用同一个注解
  • Base64
    • Base64 编码的支持已经被加入到 JDK 8 官方库中,这样不需要使用第三方库就可以进行 Base64 编码
  • 并行数组
    • Java8版本新增了很多新的方法,用于支持并行数组处理
    • 最重要的方法是 parallelSort() ,可以显著加快多核机器上的数组排序
  • 并发性
    • 基于新增的lambda表达式和steam特性,为JDK 8中为 java.util.concurrent.ConcurrentHashMap 类添加了新的方法来支持聚焦操作
    • 另外,也为 java.util.concurrentForkJoinPool 类添加了新的方法来支持通用线程池操作
  • 新工具
    • 新的编译工具,如:Nashorn 引擎 jjs 、类依赖分析器 jdeps

JDK 9[^2]

  • Java 平台模块系统
    • 重新组织了 JDK 的模块,优化了 runtime 的占用空间大小
  • Jshell
    • jshellJava 增加了类似 NodeJSPython 中的读取-求值-打印循环( Read-Evaluation-Print Loop
  • 集合、StreamOptional
    • 在集合上,JDK 9 增加 了 List.of()Set.of()Map.of()Map.ofEntries() 等工厂方法来创建不可变集合
    • Stream 中增加了新的方法 ofNullable()dropWhile()takeWhile()iterate()
    • Collectors 中增加了新的方法 filtering()flatMapping()
    • Optional 类中新增了 ifPresentOrElse()or()stream() 等方法
  • 进程 API
    • JDK 9 增加了 ProcessHandle 接口,可以对原生进程进行管理,尤其适合于管理长时间运行的进程
  • 平台日志 API 和 服务
    • JDK 9 允许为JDK 和应用配置同样的日志实现
    • 新增的 System.LoggerFinder 用来管理 JDK 使 用的日志记录器实现
  • Reactive Streams
    • Java 平台上有流行的反应式 库 RxJavaReactor
    • 反应式流规范的出发点是提供一个带非阻塞负压( non-blocking backpressure ) 的异步流处理规范
    • 反应式流规范的核心接口已经添加到了 Java9 中的 java.util.concurrent.Flow 类中
    • Flow 中包含了 Flow.PublisherFlow.SubscriberFlow.SubscriptionFlow.Processor 等 4 个核心接口
    • JDK 9 还提供了 SubmissionPublisher 作为 Flow.Publisher 的一个实现。RxJava 2Reactor 都可以很方便的 与 Flow 类的核心接口进行互操作
  • 变量句柄
    • 变量句柄是一个变量或一组变量的引用,包括静态域,非静态域,数组元素和堆外数据结构中的组成部分等
    • 变量句柄由 Javajava.lang.invoke.VarHandle 来表示。可以使用类 java.lang.invoke.MethodHandles.Lookup 中的静态工厂方法来创建 VarHandle 对 象
    • 通过变量句柄,可以在变量上进行各种操作,这些操作称为访问模式(详见[^2])
  • 改进方法句柄(Method Handle)
    • java.lang.invoke.MethodHandles 增加了更多的静态方法来创建不同类型的方法句柄
  • 并发
    • 在并发方面,类 CompletableFuture 中增加了几个新的方法
  • Nashorn
    • Nashorn 是 JDK 8 中引入的新的 JavaScript 引擎
    • JDK 9 中的 Nashorn 已经实现了一些 ECMAScript 6 规范中的新特性,包括模板字符串、二进制和八进制字面量、迭代器 和 for..of 循环和箭头函数等
    • Nashorn 还提供了 API 把 ECMAScript 源代码解析成抽象语法树( Abstract Syntax Tree,AST ) ,可以用来对 ECMAScript 源代码进行分析
  • I/O 流新特性
    • java.io.InputStream 中增加了新的方法来读取和复制 InputStream 中包含的数据
  • 改进应用安全性能
    • JDK 9 新增了 4 个 SHA- 3 哈希算法,SHA3-224、SHA3-256、SHA3-384 和 S HA3-512
    • 另外也增加了通过 java.security.SecureRandom 生成使用 DRBG 算法的强随机数
  • 用户界面
    • java.awt.Desktop 增加了新的与桌面进行互动的能力
  • 统一 JVM 日志
    • JDK 9 中 ,JVM 有了统一的日志记录系统,可以使用新的命令行选项 -Xlog 来控制 JVM 上 所有组件的日志记录
    • 该日志记录系统可以设置输出的日志消息的标签、级别、修饰符和输出目标等。JDK 9 移除了在 JDK 8 中 被废弃的垃圾回收器配置组合,同时 把 G1 设为默认的垃圾回收器实现
    • 另外,CMS 垃圾回收器已经被声明为废弃。JDK 9 也增加了很多可以通过 jcmd 调用的诊断命令
  • 其他
    • 在 Java 语言本身,JDK 9 允许在接口中使用私有方法
    • try-with-resources 语句中可以使用 effectively-final 变量
    • java.lang.StackWalker 可 以对线程的堆栈进行遍历,并且支持过滤和延迟访问
    • JDK 9 把对 Unicode 的支持升级到了 8.0
    • ResourceBundle 加载属性文件的默认编码从 ISO-8859-1 改成了 UTF-8,不再需要使用 native2ascii 命 令来对属性文件进行额外处理
    • 注解 @Deprecated 也得到了增强,增加了 sinceforRemoval 两 个属性,可以分别指定一个程序元素被废弃的版本,以及是否会在今后的版本中被删除

JDK 10[^3]

  • 局部变量类型推断

    var list = new ArrayList<String>(); // ArrayList<String>
    var stream = list.stream(); // Stream<String>
    
  • 整合 JDK 代码仓库

    • 为了简化开发流程,JDK 10 中会将多个代码库合并到一个代码仓库中
  • 统一的垃圾回收接口

    • JDK 10 中,hotspot/gc 代码实现方面,引入一个干净的 GC 接口,改进不同 GC 源代码的隔离性,多个 GC 之间共享的实现细节代码应该存在于辅助类中
    • 这种方式提供了足够的灵活性来实现全新 GC 接口,同时允许以混合搭配方式重复使用现有代码,并且能够保持代码更加干净、整洁,便于排查收集器问题
  • 并行全垃圾回收器 G1

    • JDK 10 中将为 G1 引入多线程并行 GC,同时会使用与年轻代回收和混合回收相同的并行工作线程数量,从而减少了 Full GC 的发生,以带来更好的性能提升、更大的吞吐量
    • JDK 10 中将采用并行化 mark-sweep-compact 算法,并使用与年轻代回收和混合回收相同数量的线程
    • 具体并行 GC 线程数量可以通过:-XX:ParallelGCThreads 参数来调节,但这也会影响用于年轻代和混合收集的工作线程数
  • 应用程序类数据共享

    • Java 安装程序会把 rt.jar 中的核心类提前转化成内部表示,转储到一个共享存档(shared archive)中
    • 多个 Java 进程(或者说 JVM 实例)可以共享这部分数据
    • 为改善启动和占用空间,JDK 10 在现有的 CDS 功能基础上再次拓展,以允许应用类放置在共享存档中。
  • 线程-局部管控

    • 为了能够对单独的某个线程进行操作,JDK 10 中线程管控引入 JVM 安全点的概念,将允许在不运行全局 JVM 安全点的情况下实现线程回调,由线程本身或者 JVM 线程来执行,同时保持线程处于阻塞状态,这种方式使得停止单个线程变成可能,而不是只能启用或停止所有线程。通过这种方式显著地提高了现有 JVM 功能的性能开销,并且改变了到达 JVM 全局安全点的现有时间语义
    • 增加的参数为:-XX:ThreadLocalHandshakes (默认为开启),将允许用户在支持的平台上选择安全点
  • 移除 Native-Header 自动生成工具

  • 额外的 Unicode 语言标签扩展

    • 增强 java.util.Locale 类及其相关的 API,以更方便的获得所需要的语言地域环境信息
    编码注释
    cu货币类型
    fw一周的第一天
    rg区域覆盖
    tz时区
  • 备用存储装置上的堆分配

  • 基于 Java 的 实验性 JIT 编译器

  • 根证书认证

  • 基于时间的版本发布模式

JDK 11[^4]

  • 基于嵌套的访问控制

    • 与 Java 语言中现有的嵌套类型概念一致, 嵌套访问控制是一种控制上下文访问的策略,允许逻辑上属于同一代码实体,但被编译之后分为多个分散的 class 文件的类,无需编译器额外的创建可扩展的桥接访问方法,即可访问彼此的私有成员,并且这种改进是在 Java 字节码级别的
    • JDK 11 中引入了两个新的属性
      • 一个叫做 NestMembers 的属性,用于标识其它已知的静态 nest 成员
      • 另外一个是每个 nest 成员都包含的 NestHost属性,用于标识出它的 nest 宿主类
  • 标准 HTTP Client 升级

    • 新版 Java 中,Http Client 的包名由 jdk.incubator.http 改为 java.net.http,该 API 通过 CompleteableFutures 提供非阻塞请求和响应语义,可以联合使用以触发相应的动作,并且 RX Flow 的概念也在 JDK 11 中得到了实现
    • JDK 11 中的新 Http Client API,提供了对 HTTP/2 等业界前沿标准的支持,同时也向下兼容 HTTP/1.1
  • Epsilon:低开销垃圾回收器

    • Epsilon 垃圾回收器的目标是开发一个控制内存分配,但是不执行任何实际的垃圾回收工作
    • 它提供一个完全消极的 GC 实现,分配有限的内存资源,最大限度的降低内存占用和内存吞吐延迟时间
  • 简化启动单个源代码文件的方法

    • JDK 11 版本中最令人兴奋的功能之一是增强 Java 启动器,使之能够运行单一文件的 Java 源代码。此功能允许使用 Java 解释器直接执行 Java 源代码,源代码在内存中编译,然后由解释器执行
    $ java Helloworld.java
    
    等同于
    
    $ javac HelloWorld.java
    $ java -cp . hello.World
    
  • 用于 Lambda 参数的局部变量语法

    • 为了 Lambda 类型表达式中正式参数定义的语法与局部变量定义语法的不一致,且为了保持与其他局部变量用法上的一致性,希望能够使用关键字 var 隐式定义 Lambda 表达式的形参
    ========================================
    [In JDK 10]
    var x = new Foo();
    for (var x : xs) { ... }
    try (var x = ...) { ... } catch ...
    ========================================
    [In JDK 11]
    (var x, var y) -> x.process(y);
    
    @Nonnull var x = new Foo();
    (@Nonnull var x, @Nullable var y) -> x.process(y)
    ========================================
    
  • 低开销的 Heap Profiling

    • JDK 11 中提供一种低开销的 Java 堆分配采样方法,能够得到堆分配的 Java 对象信息,并且能够通过 JVMTI 访问堆信息
  • 支持 TLS 1.3 协议

    • JDK 11 中包含了传输层安全性(TLS)1.3 规范(RFC 8446)的实现,替换了之前版本中包含的 TLS,包括 TLS 1.2,同时还改进了其他 TLS 功能
    • 同时 JDK 11 版本中实现的 TLS 1.3,重新定义了以下新标准算法名称:
      1. TLS 协议版本名称:TLSv1.3
      2. SSLContext算法名称:TLSv1.3
      3. TLS 1.3 的 TLS 密码套件名称:TLS_AES_128_GCM_SHA256TLS_AES_256_GCM_SHA384
      4. 用于 X509KeyManagerkeyTypeRSASSA-PSS
      5. 用于 X509TrustManagerauthTypeRSASSA-PSS
  • ZGC:可伸缩低延迟垃圾收集器

  • 飞行记录器

    • Java 语言中的飞行记录器类似飞机上的黑盒子,是一种低开销的事件信息收集框架,主要用于对应用程序和 JVM 进行故障检查、分析
      • 启用飞行记录器参数如下:
    -XX:StartFlightRecording
    
  • 动态类文件常量

JDK 12[^5]

  • Shenandoah:一个低停顿垃圾收集器(实验阶段)

    • JDK 12 中引入一个新的垃圾收集器:Shenandoah,它是作为一中低停顿时间的垃圾收集器而引入到 JDK 12 中的,其工作原理是通过与 Java 应用程序中的执行线程同时运行,用以执行其垃圾收集、内存回收任务,通过这种运行方式,给虚拟机带来短暂的停顿时间
  • 增加一套微基准套件

  • Switch 表达式扩展(预览功能)

    • 在 JDK 12 中重新拓展了 Switch 让它具备了新的能力,通过扩展现有的 Switch 语句,可将其作为增强版的 Switch 语句或称为 "Switch 表达式"来写出更加简化的代码
    int dayNumber = switch (day) {
        case MONDAY, FRIDAY, SUNDAY -> 6;
        case TUESDAY                -> 7;
        case THURSDAY, SATURDAY     -> 8;
        case WEDNESDAY              -> 9;
        default                      -> throw new IllegalStateException("Huh? " + day);
    }
    
  • 引入 JVM 常量 API

    • JDK 12 中引入 JVM 常量 API,用来更容易地对关键类文件 (key class-file) 和运行时构件(artefact)的名义描述 (nominal description) 进行建模,特别是对那些从常量池加载的常量,这是一项非常技术性的变化,能够以更简单、标准的方式处理可加载常量
  • 改进 AArch64 实现

    • JDK 12 中将只保留一套 AArch64 实现,删除所有与 arm64 实现相关的代码,只保留 32 位 ARM 端口和 64 位 aarch64 的端口
  • 使用默认类数据共享(CDS)存档

    • 类数据共享机制 (Class Data Sharing ,简称 CDS) ,允许将一组类预处理为共享归档文件,以便在运行时能够进行内存映射以减少 Java 程序的启动时间,当多个 JVM 共享相同的归档文件时,还可以减少动态内存的占用量,同时减少多个虚拟机在同一个物理或虚拟的机器上运行时的资源占用
  • 改善 G1 垃圾收集器,使其能够中止混合集合

  • 增强 G1 垃圾收集器,使其能自动返回未用堆内存给操作系统

JDK 13[^6]

  • 动态应用程序类-数据共享

    • 在 JDK 13 中,可以不用提供归档类列表,而是通过更简洁的方式来创建包含应用程序类的归档。具体可以使用参数 -XX:ArchiveClassesAtExit 来控制应用程序在退出时生成存档,也可以使用 -XX:SharedArchiveFile 来使用动态存档功能
  • 增强 ZGC 释放未使用内存

  • Socket API 重构

    • JDK 13 中的新底层实现,引入 NioSocketImpl 的实现用以替换 SocketImplPlainSocketImpl 实现,此实现与 NIO(新 I/O)实现共享相同的内部基础结构,并且与现有的缓冲区高速缓存机制集成在一起,因此不需要使用线程堆栈
    • 除了这些更改之外,还有其他一些更便利的更改,如使用 java.lang.ref.Cleaner 机制来关闭套接字(如果 SocketImpl 实现在尚未关闭的套接字上被进行了垃圾收集),以及在轮询时套接字处于非阻塞模式时处理超时操作等方面
  • Switch 表达式扩展(预览功能)

    • 在 JDK 13 中,value break 语句不再被编译,而是用 yield 来进行值返回,上述写法被改为如下写法
    private static String getText(int number) {
        return switch (number) {
            case 1, 2:
                yield "one or two";
            case 3:
                yield "three";
            case 4, 5, 6:
                yield "four or five or six";
            default:
                yield "unknown";
        };
    }
    
  • 文本块(预览功能)

    String html = """
                    <html>
                        <body>
                            <p>Hello, World</p>
                        </body>
                    </html>
                    """;
    
     String json = """
                    {
                        "name":"mkyong",
                        "age":38
                    }
                    """;
    
    • 由于预览功能不是规范的一部分,因此有必要为编译和运行时明确启用它们。需要使用下面两个命令行参数来启用预览功能
    $ javac --enable-preview --release 13 Example.java
    $ java --enable-preview Example
    

JDK 14[^7]

  • 对于 instance 的模式匹配

    • 增强了对 instance 的支持,避免了调用 instance 后转型出现的错误,新语法如下

      if (obj instanceof String s) {
          // can use s here
      } else {
          // can't use s here
      }
      
      if (obj instanceof String s && s.length() > 5) {.. s.contains(..) ..}
      
      @Override public boolean equals(Object o) { 
          return (o instanceof CaseInsensitiveString cis) &&cis.s.equalsIgnoreCase(s); 
      }
      
  • 打包工具

    • 创建一个用于打包独立Java应用程序的工具
  • 针对 G1NUMA 感知内存分配

    • 通过实现可识别 NUMA 的内存分配,提高大型计算机上的 G1 性能
  • JFR 事件流

    • 该包装 jdk.jfr.consumer,在模块 jdk.jfr,与功能扩展到订阅事件异步。用户可以直接从磁盘存储库读取记录数据或从磁盘存储流中读取数据,而无需转储记录文件
    • 与流进行交互的方式是注册一个处理程序,例如lambda函数,以响应事件的到来而被调用
    • RecordingStream 类实现了接口 jdk.jfr.consumer.EventStream,该接口提供了一种统一的方式来过滤和使用事件,无论源是实时流还是磁盘上的文件
    public interface EventStream extends AutoCloseable {
      public static EventStream openRepository();
      public static EventStream openRepository(Path directory);
      public static EventStream openFile(Path file);
    
      void setStartTime(Instant startTime);
      void setEndTime(Instant endTime);
      void setOrdered(boolean ordered);
      void setReuse(boolean reuse);
    
      void onEvent(Consumer<RecordedEvent> handler);
      void onEvent(String eventName, Consumer<RecordedEvent handler);
      void onFlush(Runnable handler);
      void onClose(Runnable handler);
      void onError(Runnable handler);
      void remove(Object handler);
    
      void start();
      void startAsync();
    
      void awaitTermination();
      void awaitTermination(Duration duration);
      void close();
    }
    
  • 非易失性映射字节缓冲区

  • 有用的 NullPointerExceptions

    • 触发 NullPointerExceptions 时会提供更多的有效信息
  • 记录(预览)

  • switch 表达式(标准)

    int numLetters = switch (day) {
        case MONDAY, FRIDAY, SUNDAY -> 6;
        case TUESDAY                -> 7;
        case THURSDAY, SATURDAY     -> 8;
        case WEDNESDAY              -> 9;
    };
    
  • 弃用Solaris和SPARC端口

  • 删除并发标记扫描(CMS)垃圾收集器

  • Mac OS上的ZGC

  • Windows上的ZGC

  • 弃用ParallelScavenge + SerialOld GC组合

  • 删除Pack200工具和API

  • 文本块(第二预览)

    • HTML example

      Using "one-dimensional" string literals

      Using a "two-dimensional" block of text

      String html = """
                    <html>
                        <body>
                            <p>Hello, world</p>
                        </body>
                    </html>
                    """;
      
    • SQL example

      Using a "two-dimensional" block of text

      String query = """
                     SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`
                     WHERE `CITY` = 'INDIANAPOLIS'
                     ORDER BY `EMP_ID`, `LAST_NAME`;
                     """;
      
  • 外部存储器访问API(孵化器)

参考资料:

[^1]: 【译】Java 8 的新特性—终极版
[^2]: JDK 9 新特性概述
[^3]: JDK 10 新特性介绍
[^4]: JDK 11 新特性介绍
[^5]: JDK 12 新特性介绍
[^6]: JDK 13 新特性介绍
[^7]: JDK 14