Java 16 新功能介绍
点赞再看,动力无限。Hello world : ) 微信搜「程序猿阿朗 」。
本文 Github.com/niumoo/JavaNotes 和 程序猿阿朗博客 已经收录,有很多知识点和系列文章。
Java 16 在 2021 年 3 月 16 日正式发布,不是长久支持版本,这次更新没有带来很多语法上的改动,但是也带来了不少新的实用功能。
OpenJDK Java 16 下载:https://jdk.java.net/archive/
OpenJDK Java 16 文档:https://openjdk.java.net/projects/jdk/16/
此文章属于Java 新特性教程 系列,会介绍 Java 每个版本的新功能,可以点击浏览。
1. JEP 347: 启用 C++ 14 语言特性
这项更新和 Java 开发者关系不太密切,JEP 347 允许 在 JDK 的 C++ 源码中使用 C++ 14 的语言特性,并且给出了哪些特性可以在 HotSpot 代码中使用的具体说明。
扩展阅读:启用 C++ 14 语言特性
2. JEP 357:从 Mercurial 迁移到 Git
在此之前,OpenJDK 源代码是使用版本管理工具 Mercurial 进行管理的,你也可以在 http://hg.openjdk.java.net/ 查看 OpenJDK 的源代码历史版本。
但是现在迁移到了 GIt ,主要原因如下:
- Mercurial 生成的版本控制元数据过大。
- Mercurial 相关的开发工具比较少,而 Git 几乎在所有的主流 IDE 中已经无缝集成。
- Mercurial 相关的服务比较少,无论是自建托管,还是服务托管。
为了优雅的迁移到 Git,OpenJDK 做了如下操作。
- 将所有的单存储库 OpenJDK 项目从 Mercurial 迁移到 Git。
- 保留所有的版本控制历史,也包括 Tag。
- 根据 Git 的最佳实践重新格式化提交的消息。
- 创建了一个工具用来在 Mercurial 和 Git 哈希之间进行转换。
扩展阅读: 从 Mercurial 迁移到 Git
3. JEP 369:迁移到 GitHub
和 JEP 357 从 Mercurial 迁移到 Git 的改变一致,在把版本管理迁移到 Git 之后,选择了在 GitHub 上托管 OpenJDK 社区的 Git 仓库。不过只对 JDK 11 以及更高版本 JDK 进行了迁移。
4. JEP 376:ZGC 并发线程堆栈处理
这次改动让 ZGC 线程堆栈处理从安全点(Safepoints)移动到并发阶段。
如果你忘记了什么是 Safepoints,可以复习一下。
我们都知道,在之前,需要 GC 的时候,为了进行垃圾回收,需要所有的线程都暂停下来,这个暂停的时间我们成为 Stop The World。
而为了实现 STW 这个操作, JVM 需要为每个线程选择一个点停止运行,这个点就叫做安全点(Safepoints)。
扩展阅读:JEP 376:ZGC 并发线程堆栈处理
5. JEP 380:Unix 域套接字通道
添加 UnixDomainSocketAddress.java 类用于支持 Unix 域套接字通道。
添加 Unix-domain socket 到 SocketChannel 和 ServerSocketChannel API 中。
添加枚举信息 java.net.StandardProtocolFamily.UNIX。
6. JEP 386:移植 Alpine Linux
Apine Linux 是一个独立的、非商业的 Linux 发行版,它十分的小,一个容器需要不超过 8MB 的空间,最小安装到磁盘只需要大约 130MB 存储空间,并且十分的简单,同时兼顾了安全性。
此提案将 JDK 移植到了 Apline Linux,由于 Apline Linux 是基于 musl lib 的轻量级 Linux 发行版,因此其他 x64 和 AArch64 架构上使用 musl lib 的 Linux 发行版也适用。
7. JEP 387:更好的 Metaspace
自从引入了 Metaspace 以来,根据反馈,Metaspace 经常占用过多的堆外内存,从而导致内存浪费,现在可以更及时地将未使用的 HotSpot class-metaspace 内存返还给操作系统,从而减少 Metaspace 的占用空间,并优化了 Metaspace 代码以降低后续的维护成本。
8. JEP 388:移植 Windows/AArch64
将 JDK 移植到 Windows/AArch64 架构上,Windows/AArch64 已经是终端用户市场的热门需求。
9. JEP 389:外部连接器 API(孵化)
这项提案让 Java 代码可以调用由其他语言(比如 C ,C++)编写的编译后的机器代码,替换了之前的 JNI 形式。
不过这还是一个孵化中的功能,运行时需要添加 --add-modules jdk.incubator.foreign 参数来编译和运行 Java 代码。
下面是一个调用 C 语言函数方法,然后输出运行结果的例子。
- 编写一个 C 函数打印一个 "hello www.wdbyte.com"。
#include <stdio.h>
void printHello(){
printf("hello www.wdbyte.com\n");
}
- 将上面的代码编译,然后输出到共享库 hello.so
$ gcc -c -fPIC hello.c
$ gcc -shared -o hello.so hello.o
$ ll
total 128
-rw-r--r-- 1 darcy staff 76B 10 28 19:46 hello.c
-rw-r--r-- 1 darcy staff 776B 10 28 19:46 hello.o
-rwxr-xr-x 1 darcy staff 48K 10 28 19:47 hello.so
- 编写一个 Java 代码,调用 hello.so 的 printHello 方法。
import jdk.incubator.foreign.CLinker;
import jdk.incubator.foreign.FunctionDescriptor;
import jdk.incubator.foreign.LibraryLookup;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodType;
import java.nio.file.Path;
import java.util.Optional;
public class JEP389 {
public static void main(String[] args) throws Throwable {
Path path = Path.of("/Users/darcy/git/java-core/java-16/src/com/wdbyte/hello.so");
LibraryLookup libraryLookup = LibraryLookup.ofPath(path);
Optional<LibraryLookup.Symbol> optionalSymbol = libraryLookup.lookup("printHello");
if (optionalSymbol.isPresent()) {
LibraryLookup.Symbol symbol = optionalSymbol.get();
FunctionDescriptor functionDescriptor = FunctionDescriptor.ofVoid();
MethodType methodType = MethodType.methodType(Void.TYPE);
MethodHandle methodHandle = CLinker.getInstance().downcallHandle(
symbol.address(),
methodType,
functionDescriptor);
methodHandle.invokeExact();
}
}
}
- Java 代码编译。
$ javac --add-modules jdk.incubator.foreign JEP389.java
警告: 使用 incubating 模块: jdk.incubator.foreign
1 个警告
- Java 代码执行。
$ java --add-modules jdk.incubator.foreign -Dforeign.restricted=permit JEP389.java
WARNING: Using incubator modules: jdk.incubator.foreign
警告: 使用 incubating 模块: jdk.incubator.foreign
1 个警告
hello www.wdbyte.com
扩展阅读: JEP 389:外部链接器 API(孵化器)
10. JEP 390:基于值的类的警告
添加了一个注解,用于标识当前是是基于值的类,比如 Java 8 引入的预防空指针的 Optional 类,现在已经添加了注解标识。
@jdk.internal.ValueBased
public final class Optional<T> {
// ...
}
扩展阅读:基于值的类的警告
11. JEP 392:打包工具
在 Java 14 中,JEP 343 引入了打包工具,命令是 jpackage,在 Java 14 新功能文章里也做了介绍:
使用
jpackage命令可以把 JAR 包打包成不同操作系统支持的软件格式。jpackage --name myapp --input lib --main-jar main.jar --main-class myapp.Main
常见平台格式如下:
- Linux:
debandrpm- macOS:
pkganddmg- Windows:
msiandexe要注意的是,
jpackage不支持交叉编译,也就是说在 windows 平台上是不能打包成 macOS 或者 Linux 系统的软件格式的。
在 Java 15 中,继续孵化,现在在 Java 16 中,终于成为了正式功能。
下面是一个例子,把一个简单的 Java Swing 程序打包成当前操作系统支持的软件格式,然后安装到当前电脑。
编写 Java 代码
import javax.swing.*;
import java.awt.*;
public class JEP392 {
public static void main(String[] args) {
JFrame frame = new JFrame("Hello World Java Swing");
frame.setMinimumSize(new Dimension(800, 600));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel lblText = new JLabel("Hello World!", SwingConstants.CENTER);
frame.getContentPane().add(lblText);
frame.pack();
frame.setVisible(true);
}
}
编译后,创建一个 JAR 文件。
$ javac JEP392.java
$ java JEP392.java
$ jar cvf JEP392.jar JEP392.class
将生成的 JEP392.jar 打包到符合当前平台的软件包中。
$ ~/develop/jdk-16.0.1.jdk/Contents/Home/bin/jpackage -i . -n JEP392 --main-jar hello.jar --main-class JEP392
$ ll
-rw-r--r--@ 1 darcy staff 50M 10 28 20:34 JEP392-1.0.dmg
-rw-r--r-- 1 darcy staff 864B 10 28 20:22 JEP392.class
-rw-r--r-- 1 darcy staff 1.0K 10 28 20:30 JEP392.jar
-rw-r--r-- 1 darcy staff 588B 10 28 20:22 JEP392.java
ll 后显示的 JEP392-1.0.dmg(我用的 MacOS ,所以格式是 dmg)就是打包后的结果。
双击这个文件后可以像 mac 软件一样安装。其他平台类似。

安装后可以在启动台启动。

不同的系统安装位置不同:
- Linux:
/opt - MacOS :
/Applications - Windows:
C:\Program Files\
扩展阅读:JEP 392:打包工具
12. JEP 393:外部内存访问(第三次孵化)
此提案旨在引入新的 API 以允许 Java 程序安全有效的访问 Java 堆之外的内存。相关提案早在 Java 14 的时候就已经提出了,在 Java 15 中重新孵化,现在在 Java 16 中再次孵化。
此提案的目标如下:
- 通用:单个 API 应该能够对各种外部内存(如本机内存、持久内存、堆内存等)进行操作。
- 安全:无论操作何种内存,API 都不应该破坏 JVM 的安全性。
- 控制:可以自由的选择如何释放内存(显式、隐式等)。
- 可用:如果需要访问外部内存,API 应该是
sun.misc.Unsafa.
扩展阅读:外部内存访问
13. JEP 394:instanceof 模式匹配
改进 instanceof 在 Java 14 中已经提出,在 Java 15 中继续预览,而现在,在 Java 16 中成为正式功能。
在之前,使用 instanceof 需要如下操作:
if (obj instanceof String) {
String s = (String) obj; // grr...
...
}
多余的类型强制转换,而现在:
if (obj instanceof String s) {
// Let pattern matching do the work!
...
}
14. JEP 395:Records
Record 成为 Java 16 的正式功能,下面是介绍 Java 14 时关于 Record 的介绍。
record 是一种全新的类型,它本质上是一个 final 类,同时所有的属性都是 final 修饰,它会自动编译出 public get hashcode 、equals、toString 等方法,减少了代码编写量。
示例:编写一个 Dog record 类,定义 name 和 age 属性。
package com.wdbyte;
public record Dog(String name, Integer age) {
}
Record 的使用。
package com.wdbyte;
public class Java14Record {
public static void main(String[] args) {
Dog dog1 = new Dog("牧羊犬", 1);
Dog dog2 = new Dog("田园犬", 2);
Dog dog3 = new Dog("哈士奇", 3);
System.out.println(dog1);
System.out.println(dog2);
System.out.println(dog3);
}
}
输出结果:
Dog[name=牧羊犬, age=1]
Dog[name=田园犬, age=2]
Dog[name=哈士奇, age=3]
这个功能在 Java 15 中进行二次预览,在 Java 16 中正式发布。
15. JEP 396:默认强封装JDK内部
Java 9 JEP 261引入了 --illegal-access 控制内部 API 访问和 JDK 打包的选项。
此 JEP 将 --illegal-access 选项的默认模式从允许更改为拒绝。通过此更改,JDK的内部包和 API(关键内部 API除外)将不再默认打开。
该 JEP 的动机是阻止第三方库、框架和工具使用 JDK 的内部 API 和包,增加了安全性。
16. JEP 397:Sealed Classes(密封类)预览
Sealed Classes 再次预览,在 Java 15 新特性介绍文章里已经介绍过相关功能,并且给出了详细的使用演示,这里不再重复介绍。
下面是一段引用:
我们都知道,在 Java 中如果想让一个类不能被继承和修改,这时我们应该使用 final 关键字对类进行修饰。不过这种要么可以继承,要么不能继承的机制不够灵活,有些时候我们可能想让某个类可以被某些类型继承,但是又不能随意继承,是做不到的。Java 15 尝试解决这个问题,引入了 sealed 类,被 sealed 修饰的类可以指定子类。这样这个类就只能被指定的类继承。
而且 sealed 修饰的类的机制具有传递性,它的子类必须使用指定的关键字进行修饰,且只能是 final 、sealed 、non-sealed 三者之一。
扩展阅读:Java 15 新特性介绍
参考
<完>
Hello world : ) 我是阿朗,一线技术工具人,认认真真写文章。
点赞的个个都是人才,不仅长得帅气好看,说话还好听。
文章持续更新,可以关注公众号「程序猿阿朗 」或访问「程序猿阿朗博客](https://www.wdbyte.com) 」。
回复【资料】有我准备的各系列知识点和必看书籍。
本文 Github.com/niumoo/JavaNotes 已经收录,有很多知识点和系列文章,欢迎Star。

Java 16 新功能介绍的更多相关文章
- Java 17 新功能介绍(LTS)
点赞再看,动力无限.Hello world : ) 微信搜「程序猿阿朗 」. 本文 Github.com/niumoo/JavaNotes 和 未读代码博客 已经收录,有很多知识点和系列文章. Jav ...
- Java 14 新功能介绍
不做标题党,认认真真写个文章. 文章已经收录在 Github.com/niumoo/JavaNotes 和未读代码博客,点关注,不迷路. Java 14 早在 2019 年 9 月就已经发布,虽然不是 ...
- 超详细 Java 15 新功能介绍
点赞再看,动力无限.微信搜「程序猿阿朗 」,认认真真写文章. 本文 Github.com/niumoo/JavaNotes 和 未读代码博客 已经收录,有很多知识点和系列文章. Java 15 在 2 ...
- Java 19 新功能介绍
点赞再看,动力无限. 微信搜「程序猿阿朗 」. 本文 Github.com/niumoo/JavaNotes 和 未读代码博客 已经收录,有很多知识点和系列文章. Java 19 在2022 年 9 ...
- Java 18 新功能介绍
文章持续更新,可以关注公众号程序猿阿朗或访问未读代码博客. 本文 Github.com/niumoo/JavaNotes 已经收录,欢迎Star. Java 18 在2022 年 3 月 22 日正式 ...
- CentOS以及Oracle数据库发展历史及各版本新功能介绍, 便于构造环境时有个对应关系
CentOS版本历史 版本 CentOS版本号有两个部分,一个主要版本和一个次要版本,主要和次要版本号分别对应于RHEL的主要版本与更新包,CentOS采取从RHEL的源代码包来构建.例如CentOS ...
- Java 11 新特性介绍
Java 11 已于 2018 年 9 月 25 日正式发布,之前在Java 10 新特性介绍中介绍过,为了加快的版本迭代.跟进社区反馈,Java 的版本发布周期调整为每六个月一次——即每半年发布一个 ...
- Java 12 新特性介绍,快来补一补
Java 12 早在 2019 年 3 月 19 日发布,它不是一个长久支持(LTS)版本.在这之前我们已经介绍过其他版本的新特性,如果需要可以点击下面的链接进行阅读. Java 11 新特性介绍 J ...
- 原创开源项目HierarchyViewer for iOS 2.1 Beta新功能介绍
回顾 HierarchyViewer for iOS是我们发布的一个开源项目,采用GPL v3.0协议. HierarchyViewer for iOS可以帮助iOS应用的开发和测试人员,在没有源代码 ...
随机推荐
- .net Core 基于EF Core 实现数据库上下文
在做项目时,需要将某一些功能的实体建立在另一个数据库中,连接不同的数据库用以存储记录.通过查找资料,实现EF Core上下文. 下面是实现上下文后的解决方案的目录: 1.UpAndDownDbCont ...
- study day2
study day2 windows 常用快捷键 CTRL C:复制 CTRL V:粘贴 CTRL A:全选 CTRL X:剪切 CTRL S:保存 CTRL Z:撤销 alt f4:关闭窗口 shi ...
- jquery .play()报错is not a function
报错原因:play()方法属于DOM对象方法,$('#audio')为jquery对象解决办法:将jquery对象转换为DOM对象首先打印jquery对象$('#audio') 两种转换方式将一个jQ ...
- 给你一个app,怎么测试
安装卸载 安装卸载路径是否能自己选择,在不同操作系统下(Android.ios)安装是否正常,能正常运行,安装的文件及文件夹是否写入了指定的目录里,安装来自不同来源的(应用宝.360助手)下是否正常. ...
- 1.4redis小结--队列在抢购活动的实现思路
思路:采用 客户队列,抢购结果队列,库存队列 1.1用户排队 <?php //连接本地的 Redis 服务 $redis = new Redis(); $redis->connect('1 ...
- 在反序列化数据的时候报错raise JSONDecodeError("Expecting value", s, err.value) from None json.decode
今天在爬取某网站数据内容适合,通过正则匹配拿到了需要的内容字符串,但是在反序列化的时候竟然报错,大概意思知道他不是json的期望值,那么我就会像是不是数据内有一些内容是由于编码的问题导致的呢?因为之前 ...
- 深入浅出WPF-09.Command(命令)
命令 1)命令系统的基本元素 命令(Command),WPF的命令实际上就是实现了ICommand接口的类,平时使用最多的是RoutedCommand类 命令源(Command Source),即命令 ...
- 解决报错:The import javax.servlet.annotation cannot be resolved
maven项目,引入javax.servlet.annotation.WebServlet的jar包,使用@WebServlet注解来实现对传统web.xml中servlet和url的映射 报错:Th ...
- 【LeetCode】300.最长递增子序列——暴力递归(O(n^3)),动态规划(O(n^2)),动态规划+二分法(O(nlogn))
算法新手,刷力扣遇到这题,搞了半天终于搞懂了,来这记录一下,欢迎大家交流指点. 题目描述: 给你一个整数数组 nums ,找到其中最长严格递增子序列的长度. 子序列是由数组派生而来的序列,删除(或不删 ...
- 用Flask 实现文件服务器(包含docker版本)
最近有了公司局域网内共享axure原型的需求,所以用Flask开发了一款文件上传/查看工具,记录一下其中的问题和解决方案 这个工具参照了一位大神的uploads工具 https://zhuanlan. ...