Last Updated:

Java 11 中的新功能

银狐
Java 11 徽标

 

Java 11于 2018 年 9 月 25 日正式发布,这是一个长期支持 (LTS) 版本,请在此处下载 Java 11或此openJDK 存档

Java 11 特性。

Java 11 开发人员功能。

新的HTTP Client APIs java.net.http.*var在lambda 参数中,Java 恐惧记录器(JFR),启动单文件程序java ClassName.java,支持ChaCha20 密码算法。

最新 JDK 发布 Java 16
最新 Java 16 中的新功能

1. JEP 181:基于嵌套的访问控制

它直接支持嵌套成员内的私有访问,不再通过自动生成的桥接方法access$000。此外,新的嵌套 API 用于验证并允许嵌套成员内的私有反射访问。

在 Java 11 之前。

.java

public class Alphabet {
    private String name = "I'm Alphabet!";

    public class A {
        public void printName() {
            System.out.println(name);       // access Alphabet's private member!
        }
    }
}

如果我们编译上面的类,它会生成两个类,Alphabet并且Alphabet$A,即使是嵌套类也是具有唯一名称的典型类。JVM 访问规则不允许在不同的类中进行私有访问。但是,Java 允许嵌套成员内的私有访问,因此 Java 编译器创建了一个桥接方法access$000来应用于 JVM 访问规则。


// After javac Alphabet.java, Java compiler created something similar to this.
public class Alphabet {
  private String name = "I'm Alphabet!";
  String access$000(){
    return name;
  }
}

public class Alphabet$A {
  final Alphabet obj;
  public void printName(){
    System.out.println(obj.access$000());
  }
}

在 Java 11 中,Java 编译器不会access$000为嵌套成员内的私有访问生成任何桥接方法。这个新的 JVM 访问规则,基于 Nest 的访问控制,允许在 Nest 成员中进行私有访问。

进一步阅读

 

2. JEP 309:动态类文件常量

扩展类文件格式以支持新的常量池形式CONSTANT_Dynamic、目标语言设计者和编译器实现者。

进一步阅读

3. JEP 315:改进 Aarch64 内部函数

优化了现有的字符串和数组内在函数Math.sin()Math.cos()Match.log()在 Arm64 或Aarch64 处理器上实现了新的内在函数。这意味着更好的性能。

PS内在函数用于利用特定于 CPU 体系结构的汇编代码来提高性能。

进一步阅读

4. JEP 318:Epsilon:无操作垃圾收集器(实验性)

一个新的 No-Op(无操作)垃圾收集器,它分配内存但不会收集任何垃圾(内存分配),一旦 Java 堆耗尽,JVM 将关闭。

几个用例:

  • 性能测试
  • 虚拟机接口测试
  • 短期工作

此 GC 是一个实验性功能;我们需要使用以下选项来启用新的 Epsilon GC。


-XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC

进一步阅读

5. JEP 320:删除 Java EE 和 CORBA 模块

Java 9 弃用了以下 Java EE 和 CORBA 模块,现在已在 Java 11 中删除。如果您想迁移到 Java 11,请确保您的项目未使用以下任何包或工具。

删除的包:

  • java.xml.ws (JAX-WS)
  • java.xml.bind (JAXB)
  • java.activation (JAF)
  • java.xml.ws.annotation(通用注解)
  • java.corba (CORBA)
  • java.transaction(JTA)
  • java.se.ee(上述六个模块的聚合器模块)

删除的工具:

  • wsgen 和 wsimport(来自 jdk.xml.ws)
  • schemagen 和 xjc(来自 jdk.xml.bind)
  • idlj、orbd、servertool 和 tnamesrv(来自 java.corba)

进一步阅读

6. JEP 321:HTTP 客户端(标准)

HTTP Client API,在java.net.http包是在Java的9中引入,在Java 11更新Java的10,现在的标准功能。

一个 Java 11HttpClient发送一个简单的GET请求。


    HttpClient httpClient = HttpClient.newBuilder()
            .version(HttpClient.Version.HTTP_1_1)
            .connectTimeout(Duration.ofSeconds(10))
            .build();

    HttpRequest request = HttpRequest.newBuilder()
            .GET()
            .uri(URI.create("https://httpbin.org/get"))
            .setHeader("User-Agent", "Java 11 HttpClient Bot")
            .build();

    HttpResponse<String> response =
      httpClient.send(request, HttpResponse.BodyHandlers.ofString());

    HttpHeaders headers = response.headers();
    headers.map().forEach((k, v) -> System.out.println(k + ":" + v));

    System.out.println(response.statusCode());
    System.out.println(response.body());

进一步阅读

7. JEP 323:Lambda 参数的局部变量语法

此 JEP 添加了对varlambda 参数中的关键字的支持。


  List<String> list = Arrays.asList("a", "b", "c");
  String result = list.stream()
          .map((var x) -> x.toUpperCase())
          .collect(Collectors.joining(","));
  System.out.println(result2);

但是,lambda 可以进行类型推断;上面的例子相当于:


  List<String> list = Arrays.asList("a", "b", "c");
  String result = list.stream()
          .map(x -> x.toUpperCase())
          .collect(Collectors.joining(","));

那么,为什么这个 JEP 添加var了 lambda 参数?好处是现在我们可以为 lambda 参数添加注释,请参见此示例:


import org.jetbrains.annotations.NotNull;

  List<String> list = Arrays.asList("a", "b", "c", null);
  String result = list.stream()
          .map((@NotNull var x) -> x.toUpperCase())
          .collect(Collectors.joining(","));
  System.out.println(result3);

进一步阅读

8. JEP 324:与 Curve25519 和 Curve448 的关键协议

Java 密码学相关项目。它用Curve25519Curve448算法取代了现有的椭圆曲线 Diffie-Hellman (ECDH) 方案,这是RFC 7748 中定义的密钥协议方案。

KeyPairGenerator使用该Curve25519算法生成密钥对的简单示例。

GenerateKeyPairs.java

package com.mkyong.java11.jep324;

import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.NamedParameterSpec;

public class GenerateKeyPairs {

    public static void main(String[] args) throws NoSuchAlgorithmException,
        InvalidAlgorithmParameterException {

        KeyPairGenerator kpg = KeyPairGenerator.getInstance("XDH");
        NamedParameterSpec paramSpec = new NamedParameterSpec("X25519");
        kpg.initialize(paramSpec); // equivalent to kpg.initialize(255)
        // alternatively: kpg = KeyPairGenerator.getInstance("X25519")
        KeyPair kp = kpg.generateKeyPair();

        System.out.println("--- Public Key ---");
        PublicKey publicKey = kp.getPublic();

        System.out.println(publicKey.getAlgorithm());   // XDH
        System.out.println(publicKey.getFormat());      // X.509

        // save this public key
        byte[] pubKey = publicKey.getEncoded();

        System.out.println("---");

        System.out.println("--- Private Key ---");
        PrivateKey privateKey = kp.getPrivate();

        System.out.println(privateKey.getAlgorithm());  // XDH
        System.out.println(privateKey.getFormat());     // PKCS#8

        // save this private key
        byte[] priKey = privateKey.getEncoded();
    }
}

进一步阅读

9. JEP 327:Unicode 10

这意味着更多的代码点,更多的表情符号 🙂 下面的例子打印了一个 Unicode 代码点。

PrintUnicode.java

package com.mkyong.java11;

public class PrintUnicode {

    public static void main(String[] args) {
        String codepoint = "U+1F92A";   // crazy face
        System.out.println(convertCodePoints(codepoint));
    }

    // Java, UTF-16
    // Convert code point to unicode
    static char[] convertCodePoints(String codePoint) {
        Integer i = Integer.valueOf(codePoint.substring(2), 16);
        char[] chars = Character.toChars(i);
        return chars;

    }

}

进一步阅读

10. JEP 328:飞行记录器

Java Flight Recorder (JFR) 是 Oracle JDK 中的一个商业产品,现在它在 OpenJDK 11 中开源。这个 JFR 是一个分析工具,用于诊断正在运行的 Java 应用程序。以下命令在 Java 应用程序上启动 60 秒 JFR 记录,将记录的数据转储到“.jfr”文件中。

终端

$ java -XX:StartFlightRecording=duration=60s,settings=profile,filename=app.jfr MyHelloWorldApp

那么如何处理.jfr文件呢?我们可以使用Java Mission Control (JMC)来分析和可视化.jfr文件。

进一步阅读

11. JEP 329:ChaCha20 和 Poly1305 加密算法

ChaCha20是一种高速流密码,一种加解密算法。ChaCha20-Poly1305表示ChaCha20在 AEAD 模式下与Poly1305身份验证器、加密和身份验证一起运行,两者都在RFC 7539中定义。这个ChaCha20加密算法的JEP 更新是对不安全的RC4流密码的替代。

的输入ChaCha20是:

  • 一个 256 位的密钥(32 字节)
  • 96 位随机数(12 字节)
  • 32 位初始计数(4 字节)

    Cipher cipher = Cipher.getInstance("ChaCha20");

    ChaCha20ParameterSpec param = new ChaCha20ParameterSpec(nonce, counter);

    cipher.init(Cipher.ENCRYPT_MODE, key, param);

    byte[] encryptedText = cipher.doFinal(pText);

请参考这个Java 11 – ChaCha20 Stream Cipher 示例

的输入ChaCha20-Poly1305是:

  • 一个 256 位的密钥(32 字节)
  • 96 位随机数(12 字节)

   Cipher cipher = Cipher.getInstance("ChaCha20-Poly1305");

   // IV, initialization value with nonce
   IvParameterSpec iv = new IvParameterSpec(nonce);

   cipher.init(Cipher.ENCRYPT_MODE, key, iv);

   byte[] encryptedText = cipher.doFinal(pText);

进一步阅读

12. JEP 330:启动单文件源代码程序

这个单文件源代码程序是指在一个源代码.java文件中的整个 Java 程序。这个JEP是早期学习Java的一个友好特性,但是对Java开发没有太大的好处,大家都用IDE。

查看单个文件源代码。

HelloJava.java

public class HelloJava {

    public static void main(String[] args) {

        System.out.println("Hello World!");

    }
}

在 Java 11 之前。

终端

$ javac HelloJava.java

$ java HelloJava

Hello World!

现在是 Java 11。

终端

$ java HelloJava.java

Hello World!

舍邦#!
现在,单个 Java 程序可以使用 Linux Shebang 作为脚本运行。

run.sh

#!/opt/java/openjdk/bin/java --source 11
public class SheBang {

    public static void main(String[] args) {

        System.out.println("Hello World!");

    }
}

进一步阅读

13. JEP 331:低开销堆分析

Java 虚拟机工具接口 (JVMTI) 是在 J2SE 5、JDK 5 (Tiger) 中引入的,它提供了用于分析或监视工具以访问 JVM 状态的 API。这个 JEP 在 JVMIT 中添加了新的低开销堆分析 API。

进一步阅读

14. JEP 332:传输层安全 (TLS) 1.3

Java 11 支持RFC 8446传输层安全 (TLS) 1.3 协议。但是,并非所有 TLS 1.3 功能都已实现,请参阅此JEP 332了解详细信息。

Java 安全套接字扩展 (JSSE) + TLS 1.3 示例。


import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;

SSLSocketFactory factory =
        (SSLSocketFactory) SSLSocketFactory.getDefault();
socket =
        (SSLSocket) factory.createSocket("google.com", 443);

socket.setEnabledProtocols(new String[]{"TLSv1.3"});
socket.setEnabledCipherSuites(new String[]{"TLS_AES_128_GCM_SHA256"});

进一步阅读

15. JEP 333:ZGC:可扩展的低延迟垃圾收集器(实验性)

Z Garbage Collector (ZGC) 是一个实验性的垃圾收集器;它具有不超过 10 毫秒的低暂停时间。此 ZCG 仅在 Linux/64 上支持。

进一步阅读

16. JEP 335:弃用 Nashorn JavaScript 引擎

Nashorn JavaScript 脚本引擎和jjs工具已弃用,并且可能会在未来版本中删除。

历史

  • Java 8 JEP 174引入了 Nashorn,作为 Rhino Javascript 引擎的替代品。
  • Java 11 JEP 335弃用了 Nashorn。
  • Java 15 JEP 372删除了 Nashorn JavaScript 引擎和 jjs 工具。

进一步阅读

17. JEP 336:弃用 Pack200 工具和 API

这JEP弃用了pack200unpack200工具,以及Pack200在APIjava.util.jar包,它会在将来的版本中可能删除。

PS Java 14 JEP 367删除了 Pack200 工具和 API。

进一步阅读

下载源代码

$ git clone https://github.com/mkyong/core-java

$ cd java-11

参考