diff --git a/README.md b/README.md index a3661f2f..a74d5241 100755 --- a/README.md +++ b/README.md @@ -122,7 +122,8 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle - [Java 10 新特性概览](./docs/java/new-features/java10.md) - [Java 11 新特性概览](./docs/java/new-features/java11.md) - [Java 12~13 新特性概览](./docs/java/new-features/java12-13.md) -- [Java 14~15 新特性概览](./docs/java/new-features/java14-15.md) +- [Java 14 新特性概览](./docs/java/new-features/java14.md) +- [Java 15 新特性概览](./docs/java/new-features/java15.md) - [Java 16 新特性概览](./docs/java/new-features/java16.md) - [Java 18 新特性概览](./docs/java/new-features/java18.md) - [Java 19 新特性概览](./docs/java/new-features/java19.md) diff --git a/docs/home.md b/docs/home.md index d49be00a..61c9e32d 100644 --- a/docs/home.md +++ b/docs/home.md @@ -126,8 +126,10 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle - [Java 10 新特性概览](./java/new-features/java10.md) - [Java 11 新特性概览](./java/new-features/java11.md) - [Java 12~13 新特性概览](./java/new-features/java12-13.md) -- [Java 14~15 新特性概览](./java/new-features/java14-15.md) +- [Java 14 新特性概览](./java/new-features/java14.md) +- [Java 15 新特性概览](./java/new-features/java15.md) - [Java 16 新特性概览](./java/new-features/java16.md) +- [Java 17 新特性概览](./java/new-features/java17.md) - [Java 18 新特性概览](./java/new-features/java18.md) - [Java 19 新特性概览](./java/new-features/java19.md) diff --git a/docs/java/new-features/java14.md b/docs/java/new-features/java14.md new file mode 100644 index 00000000..b2187b7f --- /dev/null +++ b/docs/java/new-features/java14.md @@ -0,0 +1,120 @@ +--- +title: Java 14 新特性概览 +category: Java +tag: + - Java新特性 +--- + +## 空指针异常精准提示 + +通过 JVM 参数中添加`-XX:+ShowCodeDetailsInExceptionMessages`,可以在空指针异常中获取更为详细的调用信息,更快的定位和解决问题。 + +```java +a.b.c.i = 99; // 假设这段代码会发生空指针 +``` + +Java 14 之前: + +```java +Exception in thread "main" java.lang.NullPointerException + at NullPointerExample.main(NullPointerExample.java:5) +``` + +Java 14 之后: + +```java + // 增加参数后提示的异常中很明确的告知了哪里为空导致 +Exception in thread "main" java.lang.NullPointerException: + Cannot read field 'c' because 'a.b' is null. + at Prog.main(Prog.java:5) +``` + +## switch 的增强(转正) + +Java12 引入的 switch(预览特性)在 Java14 变为正式版本,不需要增加参数来启用,直接在 JDK14 中就能使用。 + +Java12 为 switch 表达式引入了类似 lambda 语法条件匹配成功后的执行块,不需要多写 break ,Java13 提供了 `yield` 来在 block 中返回值。 + +```java +String result = switch (day) { + case "M", "W", "F" -> "MWF"; + case "T", "TH", "S" -> "TTS"; + default -> { + if(day.isEmpty()) + yield "Please insert a valid day."; + else + yield "Looks like a Sunday."; + } + + }; +System.out.println(result); +``` + +## 预览新特性 + +### record 关键字 + +`record` 关键字可以简化 **数据类**(一个 Java 类一旦实例化就不能再修改)的定义方式,使用 `record` 代替 `class` 定义的类,只需要声明属性,就可以在获得属性的访问方法,以及 `toString()`,`hashCode()`, `equals()`方法 + +类似于使用 `class` 定义类,同时使用了 lombok 插件,并打上了`@Getter,@ToString,@EqualsAndHashCode`注解 + +```java +/** + * 这个类具有两个特征 + * 1. 所有成员属性都是final + * 2. 全部方法由构造方法,和两个成员属性访问器组成(共三个) + * 那么这种类就很适合使用record来声明 + */ +final class Rectangle implements Shape { + final double length; + final double width; + + public Rectangle(double length, double width) { + this.length = length; + this.width = width; + } + + double length() { return length; } + double width() { return width; } +} +/** + * 1. 使用record声明的类会自动拥有上面类中的三个方法 + * 2. 在这基础上还附赠了equals(),hashCode()方法以及toString()方法 + * 3. toString方法中包括所有成员属性的字符串表示形式及其名称 + */ +record Rectangle(float length, float width) { } +``` + +### 文本块 + +Java14 中,文本块依然是预览特性,不过,其引入了两个新的转义字符: + +- `\` : 表示行尾,不引入换行符 +- `\s` :表示单个空格 + +```java +String str = "凡心所向,素履所往,生如逆旅,一苇以航。"; + +String str2 = """ + 凡心所向,素履所往, \ + 生如逆旅,一苇以航。"""; +System.out.println(str2);// 凡心所向,素履所往, 生如逆旅,一苇以航。 +String text = """ + java + c++\sphp + """; +System.out.println(text); +//输出: +java +c++ php +``` + +### instanceof 增强 + +依然是**预览特性** ,Java 12 新特性中介绍过。 + +## Java14 其他特性 + +- 从 Java11 引入的 ZGC 作为继 G1 过后的下一代 GC 算法,从支持 Linux 平台到 Java14 开始支持 MacOS 和 Window(个人感觉是终于可以在日常开发工具中先体验下 ZGC 的效果了,虽然其实 G1 也够用) +- 移除了 CMS(Concurrent Mark Sweep) 垃圾收集器(功成而退) +- 新增了 jpackage 工具,标配将应用打成 jar 包外,还支持不同平台的特性包,比如 linux 下的`deb`和`rpm`,window 平台下的`msi`和`exe` diff --git a/docs/java/new-features/java14-15.md b/docs/java/new-features/java15.md similarity index 50% rename from docs/java/new-features/java14-15.md rename to docs/java/new-features/java15.md index bb09867d..5879c08e 100644 --- a/docs/java/new-features/java14-15.md +++ b/docs/java/new-features/java15.md @@ -1,129 +1,11 @@ --- -title: Java 14 ~ 15 新特性概览 +title: Java 15 新特性概览 category: Java tag: - Java新特性 --- -## Java14 - -### 空指针异常精准提示 - -通过 JVM 参数中添加`-XX:+ShowCodeDetailsInExceptionMessages`,可以在空指针异常中获取更为详细的调用信息,更快的定位和解决问题。 - -```java -a.b.c.i = 99; // 假设这段代码会发生空指针 -``` - -Java 14 之前: - -```java -Exception in thread "main" java.lang.NullPointerException - at NullPointerExample.main(NullPointerExample.java:5) -``` - -Java 14 之后: - -```java - // 增加参数后提示的异常中很明确的告知了哪里为空导致 -Exception in thread "main" java.lang.NullPointerException: - Cannot read field 'c' because 'a.b' is null. - at Prog.main(Prog.java:5) -``` - -### switch 的增强(转正) - -Java12 引入的 switch(预览特性)在 Java14 变为正式版本,不需要增加参数来启用,直接在 JDK14 中就能使用。 - -Java12 为 switch 表达式引入了类似 lambda 语法条件匹配成功后的执行块,不需要多写 break ,Java13 提供了 `yield` 来在 block 中返回值。 - -```java -String result = switch (day) { - case "M", "W", "F" -> "MWF"; - case "T", "TH", "S" -> "TTS"; - default -> { - if(day.isEmpty()) - yield "Please insert a valid day."; - else - yield "Looks like a Sunday."; - } - - }; -System.out.println(result); -``` - -### 预览新特性 - -#### record 关键字 - -`record` 关键字可以简化 **数据类**(一个 Java 类一旦实例化就不能再修改)的定义方式,使用 `record` 代替 `class` 定义的类,只需要声明属性,就可以在获得属性的访问方法,以及 `toString()`,`hashCode()`, `equals()`方法 - -类似于使用 `class` 定义类,同时使用了 lombok 插件,并打上了`@Getter,@ToString,@EqualsAndHashCode`注解 - -```java -/** - * 这个类具有两个特征 - * 1. 所有成员属性都是final - * 2. 全部方法由构造方法,和两个成员属性访问器组成(共三个) - * 那么这种类就很适合使用record来声明 - */ -final class Rectangle implements Shape { - final double length; - final double width; - - public Rectangle(double length, double width) { - this.length = length; - this.width = width; - } - - double length() { return length; } - double width() { return width; } -} -/** - * 1. 使用record声明的类会自动拥有上面类中的三个方法 - * 2. 在这基础上还附赠了equals(),hashCode()方法以及toString()方法 - * 3. toString方法中包括所有成员属性的字符串表示形式及其名称 - */ -record Rectangle(float length, float width) { } -``` - -#### 文本块 - -Java14 中,文本块依然是预览特性,不过,其引入了两个新的转义字符: - -- `\` : 表示行尾,不引入换行符 -- `\s` :表示单个空格 - -```java -String str = "凡心所向,素履所往,生如逆旅,一苇以航。"; - -String str2 = """ - 凡心所向,素履所往, \ - 生如逆旅,一苇以航。"""; -System.out.println(str2);// 凡心所向,素履所往, 生如逆旅,一苇以航。 -String text = """ - java - c++\sphp - """; -System.out.println(text); -//输出: -java -c++ php -``` - -#### instanceof 增强 - -依然是**预览特性** ,Java 12 新特性中介绍过。 - -### Java14 其他特性 - -- 从 Java11 引入的 ZGC 作为继 G1 过后的下一代 GC 算法,从支持 Linux 平台到 Java14 开始支持 MacOS 和 Window(个人感觉是终于可以在日常开发工具中先体验下 ZGC 的效果了,虽然其实 G1 也够用) -- 移除了 CMS(Concurrent Mark Sweep) 垃圾收集器(功成而退) -- 新增了 jpackage 工具,标配将应用打成 jar 包外,还支持不同平台的特性包,比如 linux 下的`deb`和`rpm`,window 平台下的`msi`和`exe` - -## Java15 - -### CharSequence +## CharSequence `CharSequence` 接口添加了一个默认方法 `isEmpty()` 来判断字符序列为空,如果是则返回 true。 @@ -135,7 +17,7 @@ public interface CharSequence { } ``` -### TreeMap +## TreeMap `TreeMap` 新引入了下面这些方法: @@ -145,7 +27,7 @@ public interface CharSequence { - `compute()` - `merge()` -### ZGC(转正) +## ZGC(转正) Java11 的时候 ,ZGC 还在试验阶段。 @@ -159,7 +41,7 @@ Java11 的时候 ,ZGC 还在试验阶段。 $ java -XX:+UseZGC className ``` -### EdDSA(数字签名算法) +## EdDSA(数字签名算法) 新加入了一个安全性和性能都更强的基于 Edwards-Curve Digital Signature Algorithm (EdDSA)实现的数字签名算法。 @@ -186,25 +68,26 @@ System.out.println(encodedString); 0Hc0lxxASZNvS52WsvnncJOH/mlFhnA8Tc6D/k5DtAX5BSsNVjtPF4R4+yMWXVjrvB2mxVXmChIbki6goFBgAg== ``` -### 文本块(转正) +## 文本块(转正) 在 Java 15 ,文本块是正式的功能特性了。 -### 隐藏类(Hidden Classes) +## 隐藏类(Hidden Classes) 隐藏类是为框架(frameworks)所设计的,隐藏类不能直接被其他类的字节码使用,只能在运行时生成类并通过反射间接使用它们。 -### 预览新特性 +## 预览新特性 -#### 密封类 +### 密封类 -Java 15 对 Java 14 中引入的预览新特性进行了增强,主要是引入了一个新的概念 **密封类(Sealed Classes)。** +**密封类(Sealed Classes)** 是 Java 15 中的一个预览新特性。 -密封类可以对继承或者实现它们的类进行限制。 +没有密封类之前,在 Java 中如果想让一个类不能被继承和修改,我们可以使用`final` 关键字对类进行修饰。不过,这种方式不太灵活,直接把一个类的继承和修改渠道给堵死了。 -比如抽象类 `Person` 只允许 `Employee` 和 `Manager` 继承。 +密封类可以对继承或者实现它们的类进行限制,这样这个类就只能被指定的类继承。 ```java +// 抽象类 Person 只允许 Employee 和 Manager 继承。 public abstract sealed class Person permits Employee, Manager { @@ -226,13 +109,13 @@ public non-sealed class Manager extends Person { 如果允许扩展的子类和封闭类在同一个源代码文件里,封闭类可以不使用 permits 语句,Java 编译器将检索源文件,在编译期为封闭类添加上许可的子类。 -#### instanceof 模式匹配 +### instanceof 模式匹配 Java 15 并没有对此特性进行调整,继续预览特性,主要用于接受更多的使用反馈。 在未来的 Java 版本中,Java 的目标是继续完善 `instanceof` 模式匹配新特性。 -### Java15 其他新特性 +## Java15 其他新特性 - **Nashorn JavaScript 引擎彻底移除** :Nashorn 从 Java8 开始引入的 JavaScript 引擎,Java9 对 Nashorn 做了些增强,实现了一些 ES6 的新特性。在 Java 11 中就已经被弃用,到了 Java 15 就彻底被删除了。 - **DatagramSocket API 重构** @@ -257,11 +140,4 @@ Java 15 并没有对此特性进行调整,继续预览特性,主要用于接 整体优化的方向是**高效,低时延的垃圾回收表现** -对于日常的应用开发者可能比较关注新的语法特性,但是从一个公司角度来说,在考虑是否升级 Java 平台时更加考虑的是**JVM 运行时的提升** - -## 参考 - -- Oracle Java14 record -- java14-features -- Java 14 Features : -- What is new in Java 15: https://mkyong.com/java/what-is-new-in-java-15/ \ No newline at end of file +对于日常的应用开发者可能比较关注新的语法特性,但是从一个公司角度来说,在考虑是否升级 Java 平台时更加考虑的是**JVM 运行时的提升** \ No newline at end of file diff --git a/docs/java/new-features/java16.md b/docs/java/new-features/java16.md index 17493f38..31b2259d 100644 --- a/docs/java/new-features/java16.md +++ b/docs/java/new-features/java16.md @@ -5,9 +5,7 @@ tag: - Java新特性 --- -## Java 16 - -### 记录类型(转正) +## 记录类型(转正) 变更历史: @@ -29,7 +27,7 @@ public class Outer { > 在 JDK 16 之前,如果写上面这种代码,IDE 会提示你静态字段 age 不能在非静态的内部类中定义,除非它用一个常量表达式初始化。(The field age cannot be declared static in a non-static inner type, unless initialized with a constant expression) -### instanceof 模式匹配(转正) +## instanceof 模式匹配(转正) | JDK 版本 | 更新类型 | JEP | 更新内容 | | ---------- | ----------------- | --------------------------------------- | ---------------------------------------- | @@ -49,13 +47,13 @@ public class Outer { } ``` -### 预览新特性 +## 预览新特性 -#### 密封类 +### 密封类 在 JDK 15 引入的 sealed class(密封类)在 JDK 16 得到了改进:更加严格的引用检查和密封类的继承关系。 -### 其他优化与改进 +## 其他优化与改进 - **优化 JavaDoc 的搜索功能** :对于单词大小写问题的改进,当不知道具体拼写或者大小写的时候很有用。 - **ZGC 并发线程处理** :JEP 376 将 ZGC 线程栈处理从安全点转移到一个并发阶段,甚至在大堆上也允许在毫秒内暂停 GC 安全点。消除 ZGC 垃圾收集器中最后一个延迟源可以极大地提高应用程序的性能和效率。 @@ -70,7 +68,7 @@ public class Outer { - **启用 C++14 语言特性** :它允许在 JDK C++ 源代码中使用 C++14 语言特性,并提供在 HotSpot 代码中可以使用哪些特性的具体指导。在 JDK 15 中,JDK 中 C++ 代码使用的语言特性仅限于 C++98/03 语言标准。它要求更新各种平台编译器的最低可接受版本。 - **AlpineLinux 移植;JEP 388,Windows/AArch64 移植** :这些 JEP 的重点不是移植工作本身,而是将它们集成到 JDK 主线存储库中;JEP 386 将 JDK 移植到 Alpine Linux 和其他使用 musl 作为 x64 上主要 C 库的发行版上。此外,JEP 388 将 JDK 移植到 Windows AArch64(ARM64)。 -### 参考文献 +## 参考文献 - [Java Language Changes](https://docs.oracle.com/en/java/javase/16/language/java-language-changes.html) - [Consolidated JDK 16 Release Notes](https://www.oracle.com/java/technologies/javase/16all-relnotes.html) diff --git a/docs/java/new-features/java17.md b/docs/java/new-features/java17.md new file mode 100644 index 00000000..5d34002e --- /dev/null +++ b/docs/java/new-features/java17.md @@ -0,0 +1,157 @@ +Java 17 在 2021 年 9 月 14 日正式发布,Java 17 是一个长期支持(LTS)版本,这次更新共带来 14 个新特性: + +- [JEP 306:Restore Always-Strict Floating-Point Semantics(恢复始终严格的浮点语义)](https://openjdk.java.net/jeps/306) +- [JEP 356:Enhanced Pseudo-Random Number Generators(增强的伪随机数生成器)](https://openjdk.java.net/jeps/356) +- [JEP 382:New macOS Rendering Pipeline(新的 macOS 渲染管道)](https://openjdk.java.net/jeps/382) +- [JEP 391:macOS/AArch64 Port(支持 macOS AArch64)](https://openjdk.java.net/jeps/391) +- [JEP 398:Deprecate the Applet API for Removal(删除已弃用的 Applet API)](https://openjdk.java.net/jeps/398) +- [JEP 403:Strongly Encapsulate JDK Internals(更强大的封装 JDK 内部元素)](https://openjdk.java.net/jeps/403) +- [JEP 406:Pattern Matching for switch (switch 的类型匹配)](https://openjdk.java.net/jeps/406)(预览) +- [JEP 407:Remove RMI Activation(删除远程方法调用激活机制)](https://openjdk.java.net/jeps/407) +- [JEP 409:Sealed Classes(密封类)](https://openjdk.java.net/jeps/409)(转正) +- [JEP 410:Remove the Experimental AOT and JIT Compiler(删除实验性的 AOT 和 JIT 编译器)](https://openjdk.java.net/jeps/410) +- [JEP 411:Deprecate the Security Manager for Removal(弃用安全管理器以进行删除)](https://openjdk.java.net/jeps/411) +- [JEP 412:Foreign Function & Memory API (外部函数和内存 API)](https://openjdk.java.net/jeps/412)(孵化) +- [JEP 414:Vector(向量) API ](https://openjdk.java.net/jeps/417)(第二次孵化) +- [JEP 415:Context-Specific Deserialization Filters](https://openjdk.java.net/jeps/415) + +这里只对 356、398、413、406、407、409、410、411、412、414 这几个我觉得比较重要的新特性进行详细介绍。 + +相关阅读:[OpenJDK Java 17 文档](https://openjdk.java.net/projects/jdk/17/) 。 + +## JEP 356:增强的伪随机数生成器 + +JDK 17 之前,我们可以借助 `Random`、`ThreadLocalRandom`和`SplittableRandom`来生成随机数。不过,这 3 个类都各有缺陷,且缺少常见的伪随机算法支持。 + +Java 17 为伪随机数生成器 (pseudorandom number generator,RPNG,又称为确定性随机位生成器)增加了新的接口类型和实现,使得开发者更容易在应用程序中互换使用各种 PRNG 算法。 + +> [RPNG](https://ctf-wiki.org/crypto/streamcipher/prng/intro/) 用来生成接近于绝对随机数序列的数字序列。一般来说,PRNG 会依赖于一个初始值,也称为种子,来生成对应的伪随机数序列。只要种子确定了,PRNG 所生成的随机数就是完全确定的,因此其生成的随机数序列并不是真正随机的。 + +使用示例: + +```java +RandomGeneratorFactory l128X256MixRandom = RandomGeneratorFactory.of("L128X256MixRandom"); +// 使用时间戳作为随机数种子 +RandomGenerator randomGenerator = l128X256MixRandom.create(System.currentTimeMillis()); +// 生成随机数 +randomGenerator.nextInt(10)); +``` + +## JEP 398:弃用 Applet API 以进行删除 + +Applet API 用于编写在 Web 浏览器端运行的 Java 小程序,很多年前就已经被淘汰了,已经没有理由使用了。 + +Applet API 在 Java 9 时被标记弃用([JEP 289](https://openjdk.java.net/jeps/289)),但不是为了删除。 + +## JEP 406:switch 的类型匹配(预览) + +正如 `instanceof` 一样, `switch` 也紧跟着增加了类型匹配自动转换功能。 + +`instanceof` 代码示例: + +```java +// Old code +if (o instanceof String) { + String s = (String)o; + ... use s ... +} + +// New code +if (o instanceof String s) { + ... use s ... +} +``` + +`switch` 代码示例: + +```java +// Old code +static String formatter(Object o) { + String formatted = "unknown"; + if (o instanceof Integer i) { + formatted = String.format("int %d", i); + } else if (o instanceof Long l) { + formatted = String.format("long %d", l); + } else if (o instanceof Double d) { + formatted = String.format("double %f", d); + } else if (o instanceof String s) { + formatted = String.format("String %s", s); + } + return formatted; +} + +// New code +static String formatterPatternSwitch(Object o) { + return switch (o) { + 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 -> o.toString(); + }; +} + +``` + +对于 `null` 值的判断也进行了优化。 + +```java +// Old code +static void testFooBar(String s) { + if (s == null) { + System.out.println("oops!"); + return; + } + switch (s) { + case "Foo", "Bar" -> System.out.println("Great"); + default -> System.out.println("Ok"); + } +} + +// New code +static void testFooBar(String s) { + switch (s) { + case null -> System.out.println("Oops"); + case "Foo", "Bar" -> System.out.println("Great"); + default -> System.out.println("Ok"); + } +} +``` + +## JEP 407:删除远程方法调用激活机制 + +删除远程方法调用 (RMI) 激活机制,同时保留 RMI 的其余部分。RMI 激活机制已过时且不再使用。 + +## JEP 409:密封类(转正) + +密封类由 [JEP 360](https://openjdk.java.net/jeps/360) 提出预览,集成到了 Java 15 中。在 JDK 16 中, 密封类得到了改进(更加严格的引用检查和密封类的继承关系),由 [JEP 397](https://openjdk.java.net/jeps/397) 提出了再次预览。 + +在 [Java 15 新特性概览](./java15.md) 中,我有详细介绍到密封类,这里就不再做额外的介绍了。 + +## JEP 410:删除实验性的 AOT 和 JIT 编译器 + +在 Java 9 的 [JEP 295](https://openjdk.java.net/jeps/295) ,引入了实验性的提前 (AOT) 编译器,在启动虚拟机之前将 Java 类编译为本机代码。 + +Java 17,删除实验性的提前 (AOT) 和即时 (JIT) 编译器,因为该编译器自推出以来很少使用,维护它所需的工作量很大。保留实验性的 Java 级 JVM 编译器接口 (JVMCI),以便开发人员可以继续使用外部构建的编译器版本进行 JIT 编译。 + +## JEP 411:弃用安全管理器以进行删除 + +弃用安全管理器以便在将来的版本中删除。 + +安全管理器可追溯到 Java 1.0,多年来,它一直不是保护客户端 Java 代码的主要方法,也很少用于保护服务器端代码。为了推动 Java 向前发展,Java 17 弃用安全管理器,以便与旧版 Applet API ( [JEP 398](https://openjdk.java.net/jeps/398) ) 一起移除。 + +## JEP 412:外部函数和内存 API(孵化) + +Java 程序可以通过该 API 与 Java 运行时之外的代码和数据进行互操作。通过高效地调用外部函数(即 JVM 之外的代码)和安全地访问外部内存(即不受 JVM 管理的内存),该 API 使 Java 程序能够调用本机库并处理本机数据,而不会像 JNI 那样危险和脆弱。 + +外部函数和内存 API 在 Java 17 中进行了第一轮孵化,由 [JEP 412](https://openjdk.java.net/jeps/412) 提出。第二轮孵化由[ JEP 419](https://openjdk.org/jeps/419) 提出并集成到了 Java 18 中,预览由 [JEP 424](https://openjdk.org/jeps/424) 提出并集成到了 Java 19 中。 + +在 [Java 19 新特性概览](./java19.md) 中,我有详细介绍到外部函数和内存 API,这里就不再做额外的介绍了。 + +## JEP 414:向量 API(第二次孵化) + +向量(Vector) API 最初由 [JEP 338](https://openjdk.java.net/jeps/338) 提出,并作为[孵化 API](http://openjdk.java.net/jeps/11)集成到 Java 16 中。第二轮孵化由 [JEP 414](https://openjdk.java.net/jeps/414) 提出并集成到 Java 17 中,第三轮孵化由 [JEP 417](https://openjdk.java.net/jeps/417) 提出并集成到 Java 18 中,第四轮由 [JEP 426](https://openjdk.java.net/jeps/426) 提出并集成到了 Java 19 中。 + +该孵化器 API 提供了一个 API 的初始迭代以表达一些向量计算,这些计算在运行时可靠地编译为支持的 CPU 架构上的最佳向量硬件指令,从而获得优于同等标量计算的性能,充分利用单指令多数据(SIMD)技术(大多数现代 CPU 上都可以使用的一种指令)。尽管 HotSpot 支持自动向量化,但是可转换的标量操作集有限且易受代码更改的影响。该 API 将使开发人员能够轻松地用 Java 编写可移植的高性能向量算法。 + +在 [Java 18 新特性概览](./java18.md) 中,我有详细介绍到向量 API,这里就不再做额外的介绍了。 \ No newline at end of file diff --git a/docs/java/new-features/java18.md b/docs/java/new-features/java18.md index aec384f3..b9c85157 100644 --- a/docs/java/new-features/java18.md +++ b/docs/java/new-features/java18.md @@ -19,7 +19,7 @@ Java 18 在 2022 年 3 月 22 日正式发布,非长期支持版本。Java 18 Java 17 中包含 14 个特性,Java 16 中包含 17 个特性,Java 15 中包含 14 个特性,Java 14 中包含 16 个特性。相比于前面发布的版本来说,Java 18 的新特性少了很多。 -这里只对 400、408、413、416、418 这 5 个我觉得比较重要的新特性进行详细介绍。在 [Java 19 新特性概览](./java19.md)这篇文章中,我详细介绍了 Vector(向量) API 和 Foreign Function & Memory API(外部函数和内存 API),感兴趣的可以看看,这里就不重复讲了。 +这里只对 400、408、413、416、417、418、419 这几个我觉得比较重要的新特性进行详细介绍。 相关阅读: @@ -80,6 +80,58 @@ OpenJDK 官方给出了新老实现的反射性能基准测试结果。 ![新老实现的反射性能基准测试结果](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/java/new-features/JEP416Benchmark.png) +## JEP 417: 向量 API(第三次孵化) + +向量(Vector) API 最初由 [JEP 338](https://openjdk.java.net/jeps/338) 提出,并作为[孵化 API](http://openjdk.java.net/jeps/11)集成到 Java 16 中。第二轮孵化由 [JEP 414](https://openjdk.java.net/jeps/414) 提出并集成到 Java 17 中,第三轮孵化由 [JEP 417](https://openjdk.java.net/jeps/417) 提出并集成到 Java 18 中,第四轮由 [JEP 426](https://openjdk.java.net/jeps/426) 提出并集成到了 Java 19 中。 + +向量计算由对向量的一系列操作组成。向量 API 用来表达向量计算,该计算可以在运行时可靠地编译为支持的 CPU 架构上的最佳向量指令,从而实现优于等效标量计算的性能。 + +向量 API 的目标是为用户提供简洁易用且与平台无关的表达范围广泛的向量计算。 + +这是对数组元素的简单标量计算: + +```java +void scalarComputation(float[] a, float[] b, float[] c) { + for (int i = 0; i < a.length; i++) { + c[i] = (a[i] * a[i] + b[i] * b[i]) * -1.0f; + } +} +``` + +这是使用 Vector API 进行的等效向量计算: + +```java +static final VectorSpecies 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; + } +} + +``` + +在 JDK 18 中,向量 API 的性能得到了进一步的优化。 + ## JEP 418:互联网地址解析 SPI -Java 18 定义了一个全新的 SPI(service-provider interface),用于主要名称和地址的解析,以便 `java.net.InetAddress` 可以使用平台之外的第三方解析器。 \ No newline at end of file +Java 18 定义了一个全新的 SPI(service-provider interface),用于主要名称和地址的解析,以便 `java.net.InetAddress` 可以使用平台之外的第三方解析器。 + +## JEP 419:Foreign Function & Memory API(第二次孵化) + +Java 程序可以通过该 API 与 Java 运行时之外的代码和数据进行互操作。通过高效地调用外部函数(即 JVM 之外的代码)和安全地访问外部内存(即不受 JVM 管理的内存),该 API 使 Java 程序能够调用本机库并处理本机数据,而不会像 JNI 那样危险和脆弱。 + +外部函数和内存 API 在 Java 17 中进行了第一轮孵化,由 [JEP 412](https://openjdk.java.net/jeps/412) 提出。第二轮孵化由[ JEP 419](https://openjdk.org/jeps/419) 提出并集成到了 Java 18 中,预览由 [JEP 424](https://openjdk.org/jeps/424) 提出并集成到了 Java 19 中。 + +在 [Java 19 新特性概览](./java19.md) 中,我有详细介绍到外部函数和内存 API,这里就不再做额外的介绍了。 \ No newline at end of file diff --git a/docs/java/new-features/java19.md b/docs/java/new-features/java19.md index 4cf98e12..c8d4f4cc 100644 --- a/docs/java/new-features/java19.md +++ b/docs/java/new-features/java19.md @@ -25,7 +25,7 @@ JDK 19 只有 7 个新特性: Java 程序可以通过该 API 与 Java 运行时之外的代码和数据进行互操作。通过高效地调用外部函数(即 JVM 之外的代码)和安全地访问外部内存(即不受 JVM 管理的内存),该 API 使 Java 程序能够调用本机库并处理本机数据,而不会像 JNI 那样危险和脆弱。 -外部函数和内存 API 之前在 JDK 17 中孵化,在 JDK 18 中重新孵化。 +外部函数和内存 API 在 Java 17 中进行了第一轮孵化,由 [JEP 412](https://openjdk.java.net/jeps/412) 提出。第二轮孵化由[ JEP 419](https://openjdk.org/jeps/419) 提出并集成到了 Java 18 中,预览由 [JEP 424](https://openjdk.org/jeps/424) 提出并集成到了 Java 19 中。 在没有外部函数和内存 API 之前: @@ -84,45 +84,9 @@ Java 虚拟线程的详细解读可以看这篇文章:[Java19 正式 GA!看 ## JEP 426: 向量 API(第四次孵化) -向量(Vector) API 最初由[JEP 338](https://openjdk.java.net/jeps/338)提出,并作为[孵化 API](http://openjdk.java.net/jeps/11)集成到 JDK 16 中。第二轮孵化由[JEP 414](https://openjdk.java.net/jeps/414)提出并集成到 JDK 17 中。第三轮孵化由[JEP 417](https://openjdk.java.net/jeps/417)提出并集成到 JDK 18 中。 +向量(Vector) API 最初由 [JEP 338](https://openjdk.java.net/jeps/338) 提出,并作为[孵化 API](http://openjdk.java.net/jeps/11)集成到 Java 16 中。第二轮孵化由 [JEP 414](https://openjdk.java.net/jeps/414) 提出并集成到 Java 17 中,第三轮孵化由 [JEP 417](https://openjdk.java.net/jeps/417) 提出并集成到 Java 18 中,第四轮由 [JEP 426](https://openjdk.java.net/jeps/426) 提出并集成到了 Java 19 中。 -向量计算由对向量的一系列操作组成。向量 API 用来表达向量计算,该计算可以在运行时可靠地编译为支持的 CPU 架构上的最佳向量指令,从而实现优于等效标量计算的性能。 - -向量 API 的目标是为用户提供简洁易用且与平台无关的表达范围广泛的向量计算。 - -这是对数组元素的简单标量计算: - -```java -void scalarComputation(float[] a, float[] b, float[] c) { - for (int i = 0; i < a.length; i++) { - c[i] = (a[i] * a[i] + b[i] * b[i]) * -1.0f; - } -} -``` - -这是使用 Vector API 进行的等效向量计算: - -```java -static final VectorSpecies 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; - } -} - -``` +在 [Java 18 新特性概览](./java18.md) 中,我有详细介绍到向量 API,这里就不再做额外的介绍了。 ## JEP 428: 结构化并发(孵化)