Skip to content
0

Java11 - 新特性

NOTE

从版本地位来看,Java 11 是和 Java 8 一个定位,属于长期支持版本,也就是说它将会与 Java 8 一样,成为企业常用、稳定的 JDK 版本。

本内容涉及实际编写代码的是新增字符串处理方法、Optional 加强、全新 HTTP 客户端。

2022-02-08 @Young Kbt

Java11 概述

北京时间 2018 年 9 月 26 日,Oracle 官方宣布 Java 11 正式发布。这是 Java 大版本周期变化后的第一个长期支持版本,非常值得关注。从官网即可下载,最新发布的 Java11 将带来 ZGC、Http Client 等重要特性,一共包含 17 个 JEP(JDK Enhancement Proposals,JDK 增强提案)。

image-20220210225604172

Features官网文档地址
JEP 181: Nest-Based Access Controlhttp://openjdk.java.net/jeps/181
JEP 309: Dynamic Class-File Constantshttp://openjdk.java.net/jeps/309
JEP 315: Improve Aarch64 Intrinsicshttp://openjdk.java.net/jeps/315
JEP 318: Epsilon: A No-Op Garbage Collectorhttp://openjdk.java.net/jeps/318
JEP 320: Remove the Java EE and CORBA Moduleshttp://openjdk.java.net/jeps/320
JEP 321: HTTP Client (Standard)http://openjdk.java.net/jeps/321
JEP 323: Local-Variable Syntax for Lambda Parametershttp://openjdk.java.net/jeps/323
JEP 324: Key Agreement with Curve25519 and Curve448http://openjdk.java.net/jeps/324
JEP 327: Unicode 10http://openjdk.java.net/jeps/327
JEP 328: Flight Recorderhttp://openjdk.java.net/jeps/328
JEP 329: ChaCha20 and Poly1305 Cryptographic Algorithmshttp://openjdk.java.net/jeps/329
JEP 330: Launch Single-File Source-Code Programshttp://openjdk.java.net/jeps/330
JEP 331: Low-Overhead Heap Profilinghttp://openjdk.java.net/jeps/331
JEP 332: Transport Layer Security (TLS) 1.3http://openjdk.java.net/jeps/332
JEP 333: ZGC: A Scalable Low-Latency Garbage Collector (Experimental)http://openjdk.java.net/jeps/333
JEP 335: Deprecate the Nashorn JavaScript Enginehttp://openjdk.java.net/jeps/335
JEP 336: Deprecate the Pack200 Tools and APIhttp://openjdk.java.net/jeps/336

JDK 11 将是一个 企业不可忽视 的版本。从时间节点来看,JDK 11 的发布正好处在 JDK 8 免费更新到期的前夕,同时 JDK 9、10 也陆续成为 历史版本,下面是 Oracle JDK 支持路线图:

image-20220210225739393

JDK 更新很重要吗?非常重要,在过去的很多年中,Oracle 和 OpenJDK 社区提供了接近免费的午餐,导致人们忽略了其背后的海量工作和价值,这其中包括但不仅仅限于:最新的安全更新,如,安全协议等基础设施的升级和维护,安全漏洞的及时修补,这是 Java 成为企业核心设施的基础之一。大量的新特性、Bug 修复,例如,容器环境支持,GC 等基础领域的增强。很多生产开发中的 Hack,其实升级 JDK 就能解决了。不断改进的 JVM,提供接近零成本的性能优化...

JDK 11 是一个长期支持版本(LTS, Long-Term-Support)

对于企业来说,选择 11 将意味着长期的、可靠的、可预测的技术路线图。其中免费的 OpenJDK11 确定将得到 OpenJDK 社区的长期支持,LTS 版本将是可以放心选择的版本。

从 JVM GC 的角度,JDK11 引入了两种新的 GC,其中包括也许是划时代意义的 ZGC,虽然其目前还是实验特性,但是从能力上来看,这是 JDK 的一个巨大突破,为特定生产环境的苛刻需求提供了一个可能的选择。例如,对部分企业核心存储等产品,如果能够保证不超过 10ms 的 GC 暂停,可靠性会上一个大的台阶,这是过去我们进行 GC 调优几乎做不到的,是能与不能的问题。

image-20220210225919452

对于 G1 GC,相比于 JDK 8,升级到 JDK 11 即可免费享受到:并行的 Full GC,快速的 CardTable 扫描,自适应的堆占用比例调整(IHOP),在并发标记阶段的类型卸载等等。这些都是针对 G1 的不断增强,其中串行 Full GC 等甚至是曾经被广泛诟病的短板,你会发现 GC 配置和调优在 JDK11 中越来越方便。

云计算时代的监控、诊断和 Profiling 能力,这个是相比 ZGC 更具生产实践意义的特性。

Java 的应用场景跨度很大,从单机长时间运行的 Java 应用,发展成为分布式、大的单体应用或小的 function、瞬时或长时间运行等,应用场景非常复杂。

我们用什么工具诊断 Java 应用?

JDK 11 为我们提供了更加强大的基础能力,主要是两部分:

  • JEP 328:Flight Recorder(JFR):是 Oracle 刚刚开源的强大特性

    JFR 是一套集成进入 JDK、JVM 内部的事件机制框架,通过良好架构和设计的框架,硬件层面的极致优化,生产环境的广泛验证,它可以做到极致的可靠和低开销。在 SPECjbb2015 等基准测试中,JFR 的性能开销最大不超过 1%,所以,工程师可以基本没有心理负担地在大规模分布式的生产系统使用,这意味着,我们既可以随时主动开启 JFR 进行特定诊断,也可以让系统长期运行 JFR,用以在复杂环境中进行「After-the-fact」分析。

    在保证低开销的基础上,JFR 提供的能力可以应用在对锁竞争、阻塞、延迟,JVM GC、SafePoint 等领域,进行非常细粒度分析。甚至深入 JIT Compiler 内部,全面把握热点方法、内联、逆优化等等。JFR 提供了标准的 Java、C++ 等扩展 API,可以与各种层面的应用进行定制、集成,为复杂的企业应用栈或者复杂的分布式应用,提供 All-in-One 解决方案。

    而这一切都是内建在 JDK 和 JVM 内部的,并不需要额外的依赖,开箱即用。

  • JEP 331: Low-Overhead Heap Profiling

    它来源于 Google 等业界前沿厂商的一线实践,通过获取对象分配细节,为 JDK 补足了对象分配诊断方面的一些短板,工程师可以通过 JVMTI 使用这个能力增强自身的工具。

从 Java 类库发展的角度来看,JDK 11 最大的进步也是两个方面:

  • 第一,HTTP/2 Client API,新的 HTTP API 提供了对 HTTP/2 等业界前沿标准的支持,精简而又友好的 API 接口,与主流开源 API(如,Apache HttpClient, Jetty, OkHttp 等)对等甚至更高的性能。与此同时它是 JDK 在 Reactive-Stream 方面的第一个生产实践,广泛使用了 Java Flow API 等,终于让 Java 标准 HTTP 类库在扩展能力等方面,满足了现代互联网的需求。

  • 第二,就是安全类库、标准等方面的大范围升级,其中特别是 JEP 332: Transport Layer Security (TLS) 1.3,除了在安全领域的重要价值,它还是中国安全专家范学雷所领导的 JDK 项目,完全不同于以往的修修补补,是个非常大规模的工程。

除此之外,JDK 还在逐渐进行瘦身工作,或者偿还 JVM、Java 规范等历史欠账,例如:

  • 335: Deprecate the Nashorn JavaScript Engine

    它进一步明确了 Graal 很有可能将成为 JVM 向前演进的核心选择,Java-on-Java 正在一步步的成为现实。

Dynamic Class-File Constants

这是类文件新添的一种结构。具体看官方的介绍:http://openjdk.java.net/jeps/309

Java 的类型文件格式将被拓展,支持一种新的常量池格式:CONSTANT_Dynamic,加载 CONSTANT_Dynamic 会将创建委托给 bootstrap 方法。

其目标是降低开发新形式的可实现类文件约束带来的成本和干扰。

新增字符串处理方法

判断字符串是否为空白 isBlank()

java
public void test() {
    String str = "\t \r\n ";
    // 判断字符串的内容是否都是空白
    System.out.println(str.isBlank()); // 输出:true
}

去除首尾空白 strip()

trim() 的区别在于,strip() 去除字符串首尾的空白,包括英文和其他所有语言中的空白字符,而 trim() 去除字符串首尾的空白,只能去除码值小于等于 32 的空白字符,如中文空格无法去除。

java
public void test() {
    // 去除字符串首尾的空白,包括英文和其他所有语言中的空白字符
    String str1 = " youngkbt.cn ".strip();
    System.out.println(str1); // 输出:youngkbt.cn

    // 去除字符串首尾的空白,只能去除码值小于等于 32 的空白字符,如中文空格无法去除
    String str2 = " youngkbt.cn ".trim();
    System.out.println(str2); // 输出:youngkbt.cn
}

去除尾部空白 stripTrailing()

相比较 strip(),只是去除了尾部的空白。

java
public void test() {
    // 去除字符串尾部的空白
    String str = " youngkbt.cn ".stripTrailing();
    System.out.println(str1); // 输出: youngkbt.cn
}

去除首部空白 stripLeading()

相比较 strip(),只是去除了首部的空白。

java
public void test() {
    // 去除字符串首部的空白
    String str = " youngkbt.cn ".stripLeading();
    System.out.println(str1); // 输出:youngkbt.cn
}

复制字符串 repeat()

java
public void test() {
    // 复制字符串 3 次
    String str = "youngkbt.cn".repeat(3);
    System.out.println(str1); // 输出:youngkbt.cnyoungkbt.cnyoungkbt.cn
}

行数统计 lines().count()

注意是行数的统计,而不是字数的统计。

java
public void test() {
    long count = "ABC".lines().count();
    System.out.println(count); // 输出:1

    long count = "A\nB\nC".lines().count();
    System.out.println(count); // 输出:3
}

lines() 有一个很有用的用途,就是读取文件的内容,如:

java
public void test() {
	FileInputStream fis = new FileInputStream("文件路径");
    byte[] buffer = new byte[fis.available()];
    fis.read(buffer);
    fis.close();

    String str = new String(buffer);
    str.lines().forEach(System.out::println);
}

Optional 加强

Optional 也增加了几个非常酷的方法,现在可以很方便的将一个 Optional 转换成一个 Stream,或者当一个空 Optional 时给它一个替代的。

新增方法描述新增的版本
isEmpty()判断 value 是否为空JDK 11
ifPresentOrElse(参数 1, 参数 2)value 非空,执行参数 1 功能;如果 value 为空,执行参数 2 功能JDK 9
or()value 非空,返回对应的 Optional;value 为空,返回形参封装的 OptionalJDK 9
stream()value 非空,返回仅包含此 value 的 Stream;否则,返回一个空的 StreamJDK 9
orElseThrow()value 非空,返回 value;否则抛异常 NoSuchElementExceptionJDK 10

image-20220211181224956

代码示例:

java
public void test() {
	Optional<Object> op = Optional.empty();
    // 判断内部的 value 是否存在
    System.out.println(op.isPresent()); // 输出:false
    // 判断内部的 value 是否为空
    System.out.println(op.isEmpty()); // 输出:true

    op = Optional.of( "abc" ) ;
    // orELseThrow():value 非空,返回 value;否则抛异常 NoSuchELementException
    var obj = op.orElseThrow();
    System.out.println(obj);

    Optional<String> op1 = Optional.of( "hello" );
	// or:value 非空,返回对应的 optional;value 为空,返回形参封装的 optional
    Optional<object> op2 = op.or(() -> op1);
	system.out.println(op2); // sOptional[abc]

}

局部变量类型推断升级

在 var 上添加注解的语法格式,在 Java10 中是不能实现的。在 Java11 中加入了这样的语法。

在声明隐式类型的 lambda 表达式的形参时允许使用 var,使用 var 的好处是在使用 lambda 表达式时给参数加上注解,如下:

java
Consumer<String> consumer = (@Deprecated var x, @Nullable var y) -> x.process(y);

因为不使用 var 的话,是会报错 非法的表达式开始,如下:

java
Consumer<String> consumer = (@Deprecated x, @Nullable y) -> x.process(y);

image-20220211150228703

全新 HTTP 客户端

HTTP,用于传输网页的协议,早在 1997 年就被采用在目前的 1.1 版本中。直到 2015 年,HTTP2 才成为标准

image-20220210184253143

HTTP/1.1 和 HTTP/2 的主要区别是如何在客户端和服务器之间构建 和传输数据。HTTP/1.1 依赖于请求/响应周期HTTP/2 允许服务器 push 数据:它可以发送比客户端请求更多的数据。这使得它可以优先处理并发送对于首先加载网页至关重要的数据。

这是 Java 9 开始引入的一个处理 HTTP 请求的的 HTTP Client API,该 API 支持同步和异步,而在 Java 11 中已经成为正式可用状态,你可以在 java.net 包中找到这个 API。

它将 替代仅适用于 blocking 模式的 HttpURLConnection(HttpURLConnection 是在 HTTP 1.0 的时代创建的,并使用了协议无关的方法),并提供 对 WebSocket 和 HTTP/2 的支持

来看一下 HTTP Client 的同步和异步用法:

  • 同步 HTTP

    java
    public void testHttp() throws Exception {
        // 1. 创建客户端
        HttpClient httpClient = HttpClient.newHttpClient();
        // 2. 创建访问地址的对象
        HttpRequest request = HttpRequest.newBuilder(URI.create("http://www.youngkbt.cn")).GET().build();
        // 3. 创建能处理地址返回结果的对象
        HttpResponse.BodyHandler<String> responseBodyHandler = HttpResponse.BodyHandlers.ofString();
        // 4. 发送请求,获取响应
        HttpResponse<String> response = httpClient.send(request, responseBodyHandler);
        // 5. 输出响应内容
        System.out.println(response.body());
    }

    上面的 .GET() 可以省略,默认请求方式为 GET。

  • 异步 HTTP

    java
    public void testHttpAsync() throws Exception {
         // 1. 创建客户端
        HttpClient httpClient = HttpClient.newHttpClient();
        // 2. 创建访问地址的对象
        HttpRequest request = HttpRequest.newBuilder(URI.create("http://www.youngkbt.cn")).GET().build();
        // 3. 创建能处理地址返回结果的对象
        HttpResponse.BodyHandler<String> responseBodyHandler = HttpResponse.BodyHandlers.ofString();
        // 4. 发送请求,获取响应
        CompletableFuture<HttpResponse<String>> response = httpClient.sendAsync(request, responseBodyHandler);
        // 5. 异步获取并输出响应内容
        System.out.println(response.get().body());
    }

移除的一些内容

移除项

  • 移除了 com.sun.awt.AWTUtilities
  • 移除了 sun.misc.Unsafe.defineClass,使用 java.lang.invoke.MethodHandles.Lookup.defineClass 来替代
  • 移除了 Thread.destroy() 以及 Thread.stop(Throwable) 方法
  • 移除了 sun.nio.ch.disableSystemWideOverlappingFileLockChecksun.locale.formatasdefault 属性
  • 移除了 jdk.snmp 模块
  • 移除了 javafx,OpenJDK 在 Java10 版本就移除了,但是 Oracle JDK10 还尚未移除 javafx,而 Oracle JDK11 版本移除了 javafx
  • 移除了 Java Mission Control,从 JDK 中移除之后,需要自己单独下载
  • 移除了这些 Root Certificates:Baltimore Cybertrust Code Signing CA,SECOM,AOL and Swisscom

废弃项

  • -XX+AggressiveOpts 选项

  • -XX:+UnlockCommercialFeatures 选项

  • -XX:+LogCommercialFeatures 选项

更简化的编译运行程序

JEP 330: 增强 Java 启动器支持运行单个 Java 源代码文件的程序。

在 Java 11 之前,我们要想运行一个 Java 文件,首先利用 javac 将 Java 文件编译处 Class 文件,再 java 来运行 Class 文件,而在 Java 11 中,我们可以直接使用 java 对一个 Java 文件运行,不需要编译成 Class 文件,也不会在目录下生成 Class 文件。

注意点:

  • 执行源文件中的第一个类,第一个类必须包含主方法
  • 并且不可以使用别源文件中的自定义类,本文件中的自定义类是可以使用的

假设有一个 Java 文件,在命令行使用 java TestJava 就会输出 Hello,Java 11,内容如下:

java
public class TestJava {
    public static void main(String[] args) {
        System.out.println("Hello,Java 11");
    }
}

如果该文件有两个类,默认是使用第一个类,如果第一个类没有 main 主方法,则报错,如下的命令 java TestJava 将输出 Java 11

java
class TestJava1 {
    public static void main(String[] args) {
        System.out.println("Java 11");
    }
}
public class TestJava {
    public static void main(String[] args) {
        System.out.println("Hello,Java 11");
    }
}

如果该文件有一个类引用自定义类,则确保自定义类在该文件里,无法跨文件使用,如下:

java
class Teacher {
    private String name;
    private int age;
}
public class TestJava {
    public static void main(String[] args) {
        Teacher teacher = new Teacher();
    }
}

Unicode 10

Unicode 10 增加了 8518 个字符,总计达到了 136690 个字符。并且增加了 4 个脚本.同时还有 56 个新的 emoji 表情符号。

因此 Java11 新增了四个 Java 文件。

移除 JavaEE 和 CORBA 模块

在 Java11 中移除了不太使用的 JavaEE 模块和 CORBA 技术。

CORBA 来自于二十世纪九十年代,Oracle 说,现在用 CORBA 开发现代 Java 应用程序已经没有意义了,维护 CORBA 的成本已经超过了保留它带来的好处

但是删除 CORBA 将使得那些依赖于 JDK 提供部分 CORBA API 的 CORBA 实现无法运行。目前还没有第三方 CORBA 版本,也不确定是否会有第三方愿意接手 CORBA API 的维护工作。

在 Java11 中将 Java9 标记废弃的 Java EE 及 CORBA 模块移除掉,具体如下:

java
java.xml.ws
java.xml.bind
java.xml.ws
java.xml.ws.annotation
jdk.xml.bind
jdk.xml.ws

java.corba
java.se.ee
java.activation
java.transactio

只剩下 java.xmljava.xml.cryptojdk.xml.dom 这几个模块。但是 Java 11 新增一个 java.transaction.xa 模块。

废弃 Nashorn JavaScript 引擎

废除 Nashorn javascript 引擎,在后续版本准备移除掉,有需要的可以考虑使用 GraalVM。

废弃 Pack20 工具和 API

Java5 中带了一个压缩工具:Pack200,这个工具能对普通的 jar 文件进行高效压缩。其实现原理是根据 Java 类特有的结构,合并常数池,去掉无用信息等来实现对 Java 类的高效压缩。由于是专门对 Java 类进行压缩的,所以对普通文件的压缩和普通压缩软件没有什么两样,但是对于 Jar 文件却能轻易达到 10% - 40% 的压缩率。这在 Java 应用部署中很有用,尤其对于移动 Java 计算,能够大大减小代码下载量。

Java5 中还提供了这一技术的 API 接口,你可以将其嵌入到你的程序中使用。使用的方法很简单,下面的短短几行代码即可以实现 jar 的压缩和解压:

java
// 压缩
Packer packer = Pack200.newPacker();
OutputStream output = new BufferedOutputStream(new FileOutputStream(outfile));
packer.pack(new JarFile(jarFile), output);
output.close();

// 解压
Unpacker unpacker = Pack200.newUnpacker();
output = new JarOutputStream(new FileOutputStream(jarFile));
unpacker.unpack(pack200File, output);
output.close();

Pack200 的压缩和解压缩速度是比较快的,而且压缩率也是很惊人的,在我是使用的包 4.46MB 压缩后成了 1.44MB(0.322%),而且随着包的越大压缩率会根据明显,据说如果 jar 包都是 Class 类可以压缩到 1/9 的大小。其实 Java WebStart 还有很多功能,例如可以按不同的 jar 包进行 lazy 下载和单独更新,设置可以根据 jar 中的类变动进行 Class 粒度的下载。

但是在 Java11 中废除了 Pack200 以及 Unpack200 工具以及 java.util.jar 中的 Pack200 API。因为 Pack200 主要是用来压缩 jar 包的工具,由于网络下载速度的提升以及 Java9 引入模块化系统之后不再依赖 Pack200,因此这个版本将其移除掉。

Epsilon 垃圾收集器

A NoOp Garbage Collector。

JDK 对这个特性的描述是:开发一个处理内存分配但不实现任何实际内存回收机制的 GC,一旦可用堆内存用完,JVM 就会退出。

如果有 System.gc() 调用,实际上什么也不会发生(这种场景下和 -XX:+DisableExplicitGC:禁用 GC 效果一样),因为没有内存回收,这个实现可能会警告用户尝试强制 GC 是徒劳。

用法参数

两个参数一起使用。

  • -XX:+UnlockExperimentalVMOptions
  • ``-XX:+UseEpsilonGC`
java
class Garbage {
    int n = (int)(Math.random() * 100);
    @Override
    public void finalize() {
        System.out.println(this + " : " + n + " is dying");
    }
}
public class EpsilonTest {

    public static void main(String[] args) {
        boolean flag = true;
        List<Garbage> list = new ArrayList<>();
        long count = 0;
        while (flag) {
            list.add(new Garbage());
            if (list.size() == 1000000 && count == 0) {
                list.clear();
                count++;
            }
        }
        System.out.println("程序结束");
    }
}

如果使用选项 -XX:+UseEpsilonGC,程序很快就因为堆空间不足而退出,因为该 GC 并不会进行垃圾回收。

使用这个选项的原因

提供完全被动的 GC 实现,具有有限的分配限制和尽可能低的延迟开销,但代价是内存占用和内存吞吐量。

众所周知,Java 实现可广泛选择高度可配置的 GC 实现。各种可用的收集器最终满足不同的需求,即使它们的可配置性使它们的功能相交。有时更容易维护单独的实现,而不是在现有 GC 实现上堆积另一个配置选项。

主要用途

  • 性能测试(它可以帮助过滤掉 GC 引起的性能假象)
  • 内存压力测试(例如,知道测试用例应该分配不超过 1GB 的内存,我们可以使用-Xmx1g–XX:+UseEpsilonGC,如果程序有问题,则程序会崩溃)
  • 非常短的 JOB 任务(对象这种任务,接受 GC 清理堆那都是浪费空间)
  • VM 接口测试
  • Last-drop 延迟 & 吞吐改进

ZGC 垃圾收集器

GC 是 Java 主要优势之一。然而,当 GC 停顿太长,就会开始影响应用的响应时间.消除或者减少 GC 停顿时长,Java 将对更广泛的应用场景是一个更有吸引力的平台。此外,现代系统中可用内存不断增长,用户和程序员希望 JVM 能够以高效的方式充分利用这些内存,并且无需长时间的 GC 暂停时间。

ZGC:A Scalable Low-Latency Garbage Collector(Experimental),这应该是 JDK11 最为瞩目的特性,没有之一。但是后面带了 Experimental,说明这还不建议用到生产环境。

特点:

  • GC 暂停时间不会超过 10ms
  • 既能处理几百兆的小堆,也能处理几个 T 的大堆(OMG)
  • 和 G1 相比,应用吞吐能力不会下降超过 15%
  • 为未来的 GC 功能和利用 colord 指针以及 Load barriers 优化奠定基础
  • 初始只支持 64 位系统

ZGC 的设计目标是:支持 TB 级内存容量,暂停时间低(<10ms),对整个程序吞吐量的影响小于 15%。 将来还可以扩展实现机制,以支持不少令人兴奋的功能,例如多层堆(即热对象置于 DRAM 和冷对象置于 NVMe 闪存),或压缩堆。

ZGC 是一个并发,基于 region,压缩型的垃圾收集器,只有 root 扫描阶段会 STW,因此 GC 停顿时间不会随着堆的增长和存活对象的增长而变长。

用法(两个都要使用):

  • -XX:+UnlockExperimentalVMOptions,因为 ZGC 还处于实验阶段,所以需要通过 JVM 参数来解锁这个特性
  • –XX:+UseZGC

支持 G1 上的并行完全垃圾收集

对于 G1 GC,相比于 JDK 8,升级到 JDK 11 即可免费享受到:并行的 Full GC,快速的 CardTable 扫描,自适应的堆占用比例调整(IHOP),在并发标记阶段的类型卸载等等。这些都是针对 G1 的不断增强,其中串行 Full GC 等甚至是曾经被广泛诟病的短板,你会发现 GC 配置和调优在 JDK11 中越来越方便。

免费的低耗能飞行记录仪和堆分析仪

低耗能飞行记录仪和堆分析仪通过 JVMTI 的 SampledObjectAlloc 回调提供一个低开销的,为了排错 Java 应用问题,以及 JVM 问题的数据收集框架。

希望达到的目标如下:

  • 提供用于生产和消费数据作为事件的 API
  • 提供缓存机制和二进制数据格式
  • 允许事件配置和事件过滤
  • 提供 OS,JVM 和 JDK 库的事件

两种加密算法

Java 11 实现了 RFC 7539 的 ChaCha20 and ChaCha20-Poly1305 加密算法 XECPublicKeyXECPrivateKey,代替 RC4。

RFC7748 定义的秘钥协商方案更高效,更安全。JDK 增加两个新的接口

java
// XECPublicKey 和 XECPrivateKey
KeyPairGenerator kpg = KeyPairGenerator.getInstance("XDH");
NamedParameterSpec paramSpec = new NamedParameterSpec("X25519");
kpg.initialize(paramSpec);
KeyPair kp = kgp.generateKeyPair();

KeyFactory kf = KeyFactory.getInstance("XDH");
BigInteger u = new BigInteger("xxx");
XECPublicKeySpec pubSpec = new XECPublicKeySpec(paramSpec, u);
PublicKey pubKey = kf.generatePublic(pubSpec);

KeyAgreement ka = KeyAgreement.getInstance("XDH");
ka.init(kp.getPrivate());
ka.doPhase(pubKey, true);
byte[] secret = ka.generateSecret();

新的默认根权限证书集

Java 11 实现 TLS 协议 1.3 版本,TLS 允许客户端和服务器端通过互联网以一种防止窃听,篡改以及消息伪造的方式进行通信。

Java Flight Recorder

Flight Recorder 源自飞机的黑盒子。

Flight Recorder 以前是商业版的特性,在 Java11 当中开源出来,它可以导出事件到文件中,之后可以用 Java Mission Control 来分析。可以在应用启动时配置 java -XX:StartFlightRecording,或者在应用启动之后,使用 jcmd 来录制,比如:

  • jcmd <pid> JFR.start,开启 Flight Recorder ,监听 Java 程序的 pid
  • jcmd <pid> JFR.dump filename=recording.jfr,将监听到的数据写入 JFR 文件,并继续监听新的数据
  • jcmd <pid> JFR.stop,关闭 Flight Recorder

Flight Recorder 是 Oracle 刚刚开源的强大特性。我们知道在生产系统进行不同角度的 Profiling,有各种工具、框架,但是能力范围、可靠性、开销等,大都差强人意,要么能力不全面,要么开销太大,甚至不可靠可能导致 Java 应用进程宕机。

而 JFR 是一套集成进入 JDK、JVM 内部的事件机制框架,通过良好架构和设计的框架,硬件层面的极致优化,生产环境的广泛验证,它可以做到极致的可靠和低开销。在 SPECjbb2015 等基准测试中,JFR 的性能开销最大不超过 1%,所以,工程师可以基本没有心理负担地在大规模分布式的生产系统使用,这意味着,我们既可以随时主动开启 JFR 进行特定诊断,也可以让系统长期运行 JFR,用以在复杂环境中进行「After-the-fact」分析。还需要苦恼重现随机问题吗?JFR 让问题简化了很多。

在保证低开销的基础上,JFR 提供的能力也令人眼前一亮,例如:我们无需 BCI 就可以进行 Object Allocation Profiling,终于不用担心 BTrace 之类把进程搞挂了。对锁竞争、阻塞、延迟,JVM GC、SafePoint 等领域,进行非常细粒度分析。甚至深入 JIT Compiler 内部,全面把握热点方法、内联、逆优化等等。JFR 提供了标准的 Java、C++ 等扩展 API,可以与各种层面的应用进行定制、集成,为复杂的企业应用栈或者复杂的分布式应用,提供 All-in-One 解决方案。而这一切都是内建在 JDK 和 JVM 内部的,并不需要额外的依赖,开箱即用。

最近更新