目录

jdk15新特性

大背景

25岁的Java

java的现状

2020 年是 Java 诞生的第 25 个年头。Oracle表示,目前java仍然流行编程语言,广泛使用在企业中。目前全世界有超过69%的专职开发人员使用Java,全世界有510亿台活动Java虚拟机(JVM)在部署中,目前Java主要被用于分析,数据管理,大数据,DevOps,移动,持续开发工具和聊天机器人等服务。

历史版本中的主要新特性

在过去的这些年中,Java 在过去增强功能的推动下为用户提供了超过二十年的创新。例如:

  • JDK 5:enum、泛型、自动装箱与拆箱、可变参数、增强循环等
  • JDK 6:支持脚本语言、JDBC4.0API
  • JDK 7:支持try-with-resources、switch语句块增加String支持、NIO2.0包
  • JDK 8:lambda表达式、Stream API、新的日期时间的API、方法引用、构造器引用
  • JDK 9:模块化系统、jshell
  • JDK 10:局部变量的类型推断
  • JDK 11:ZGC的引入、Epsilon GC
  • JDK 12:switch表达式、Shenandoah GC、增强G1
  • JDK 13:switch表达式引入yield、文本块
  • JDK 14:instanceof模式识别、Records、弃用Parallel Scavenge+Serial GC组合、删除CMS GC

近期版本发布及维护时间

OpenJDK发版路线图:

http://img.cana.space/picStore/20201102132703.png

名词解释

因为是小步快跑,快速迭代,因此此处解释下这两个词:孵化器模块(Incubator)和预览特性(Preview)。

孵化器模块(Incubator/孵化版/实验版) 尚未定稿的API/工具,主要用于从Java社区收集使用反馈,稳定性无保障,后期有较大可能性移除

预览特性(Preview/预览版) 规格已成型,实现已确定,但还未最终定稿。这些特性还是存在被移除的可能性,但一般来说最后都会被固定下来。

新特性关注点

角度一:语法层面

lambda表达式,switch,自动装箱和拆箱、enum、接口中的静态方法、默认方法、私有方法

角度二:API层面

Stream API、新的日期时间的API、Optional、String、集合框架

角度三:底层优化

JVM的优化、元空间、GC、GC的组合、GC的参数、js的执行引擎、集合底层的实现

版本选择的建议

JDK的版本更新非常快,目前已经到了JDK15了,但绝大部分人估计都还在用着jdk8. 在大版本方面,目前可以选的就是8和11了,其他都不是LTS。(至于java10,2018年9月就已经失去官方支持了),JDK12其实是一个非LTS(long time support 长期支持版)版本,而11与8一样是LTS版,意味着下个通用的版本将从8直接到11,毕竟11包含了9和10的所有新特性,因此9和10估计就直接被废弃啦。不过9、10、11、12面向开发者的新特性其实并不是很多,大部分都是一些优化、收集器加强以及增加了一些新功能等等

我个人的建议: 1. 如果是项目已经上线,尽量选择和线上一样的大版本,以免出现什么线下能跑,线上有问题的情况,毕竟java领域开源框架组件众多,并不是每一个框架,组件都能很好的兼容所有的高版本。 2. 个人学习(喜欢新特性尝鲜),可以安装一些高版本,但暂时也不要高于JDK11,毕竟学习期间用到的一些开源组件可能是依赖低版本的JDK。最多安装到JDK11即可(如不想踩坑,JDK8是最成熟的版本了).

新特性概述

主要功能

这次发布的主要功能有: Java 15为用户提供了14项主要的增强/更改,包括一个孵化器模块,三个预览功能,两个不推荐使用的功能以及两个删除功能。 http://openjdk.java.net/projects/jdk/15/

对应中文特性:(JEP:JDK Enhancement Proposals,JDK 增强建议,也就是 JDK 的特性新增和改进提案。)

339: Edwards-Curve Digital Signature Algorithm (EdDSA) EdDSA 数字签名算法
360: Sealed Classes (Preview) 密封类(预览)
371: Hidden Classes 隐藏类
372: Remove the Nashorn JavaScript Engine 移除 Nashorn JavaScript 引擎
373: Reimplement the Legacy DatagramSocket API 重新实现 Legacy DatagramSocket API
374: Disable and Deprecate Biased Locking 禁用偏向锁定
375: Pattern Matching for instanceof (Second Preview) instanceof 模式匹配(第二次预览)
377: ZGC: A Scalable Low-Latency Garbage Collector ZGC:一个可扩展的低延迟垃圾收集器
378: Text Blocks 文本块
379: Shenandoah: A Low-Pause-Time Garbage Collector Shenandoah:低暂停时间垃圾收集器
381: Remove the Solaris and SPARC Ports 移除 Solaris 和 SPARC 端口
383: Foreign-Memory Access API (Second Incubator) 外部存储器访问 API(第二次孵化版)
384: Records (Second Preview) Records(第二次预览)
385: Deprecate RMI Activation for Removal 废弃 RMI 激活机制

JDK15整体来看新特性方面并不算很亮眼,它主要是对之前版本预览特性的功能做了确定,如文本块、ZGC等,这么一来我们就可以放心大胆的使用了。

开发工具

目前,官方博文说支持Java15的工具,就下面这三款:

  • JetBrains IDEA
  • Apache NetBeans
  • Eclipse Marketplace

运行JDK15需要IDEA 2020.2才能支持。(JDK14要求IDEA 2020.1)

jdk15下载

使用IDEA时记得配置

  • Project language level
  • Java Compiler -> Targe bytecode version

jdk15新特性(主菜)

密封类的使用

介绍

JEP 360:Sealed Classes(Preview)密封的类和接口(预览)

通过密封的类和接口来增强 Java 编程语言,这是新的预览特性。用于限制超类的使用,密封的类和接口限制其它可能继承或实现它们的其它类或接口。

这个特性的目标包括——允许类或接口的开发者来控制哪些代码负责实现,提供了比限制使用超类的访问修饰符声明方式更多选择,并通过支持对模式的详尽分析而支持模式匹配的未来发展。

在Java中,类层次结构通过继承实现代码的重用,父类的方法可以被许多子类继承。但是,类层次结构的目的并不总是重用代码。有时,其目的是对域中存在的各种可能性进行建模,例如图形库支持的形状类型或金融应用程序支持的贷款类型。当以这种方式使用类层次结构时,我们可能需要限制子类集从而来简化建模。

具体使用

因为我们引入了sealed class或interfaces,这些class或者interfaces只允许被指定的类或者interface进行扩展和实现。

使用修饰符sealed,您可以将一个类声明为密封类。密封的类使用reserved关键字permits列出可以直接扩展它的类。子类可以是最终的,非密封的或密封的。

示例程序

有如下类继承结构

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
package com.eh.jdk15.sealed;

public class Person {
}

class Teacher extends Person {
}

class Student extends Person {
}

class MiddleSchoolStudent extends Student {
}

class GraduateStudent extends Student {
}

class Worker extends Person {
}

当使用密封类关键字sealed修饰父类Person时,子类Teacher、Student和Worker均报编译错误

1
2
public sealed class Person {
}

正确示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.eh.jdk15.sealed;

/**
 * 只允许Teacher, Student, Worker继承
 */
public sealed class Person permits Teacher, Student, Worker {
}

// 子类可以是最终的
final class Teacher extends Person {
}

// 子类可以是密封的
sealed class Student extends Person {
}

final class MiddleSchoolStudent extends Student {
}

non-sealed class GraduateStudent extends Student {
}

// 子类可以是非密封的
non-sealed class Worker extends Person {
}

class RailWayWorker extends Worker{
}

隐藏类的理解

JEP 371:Hidden Classes(隐藏类)

该提案通过启用标准 API 来定义无法发现且具有有限生命周期的隐藏类,从而提高 JVM 上所有语言的效率。JDK内部和外部的框架将能够动态生成类,而这些类可以定义隐藏类。通常来说基于JVM的很多语言都有动态生成类的机制,这样可以提高语言的灵活性和效率。

  • 隐藏类天生为框架设计的,在运行时生成内部的class。
  • 隐藏类只能通过反射访问,不能直接被其他类的字节码访问。
  • 隐藏类可以独立于其他类加载、卸载,这可以减少框架的内存占用。

Hidden Classes是什么呢?

  • Hidden Classes就是不能直接被其他class的二进制代码使用的class。Hidden Classes主要被一些框架用来生成运行时类,但是这些类不是被用来直接使用的,而是通过反射机制来调用。
  • 比如在JDK8中引入的lambda表达式,JVM并不会在编译的时候将lambda表达式转换成为专门的类,而是在运行时将相应的字节码动态生成相应的类对象。
  • 另外使用动态代理也可以为某些类生成新的动态类。

那么我们希望这些动态生成的类需要具有什么特性呢?

  • 不可发现性。因为我们是为某些静态的类动态生成的动态类,所以我们希望把这个动态生成的类看做是静态类的一部分。所以我们不希望除了该静态类之外的其他机制发现。
  • 访问控制。我们希望在访问控制静态类的同时,也能控制到动态生成的类。
  • 生命周期。动态生成类的生命周期一般都比较短,我们并不需要将其保存和静态类的生命周期一致。

API的支持

所以我们需要一些API来定义无法发现的且具有有限生命周期的隐藏类。这将提高所有基于JVM的语言实现的效率。比如:

  • java.lang.reflect.Proxy可以定义隐藏类作为实现代理接口的代理类。
  • java.lang.invoke.StringConcatFactory可以生成隐藏类来保存常量连接方法;
  • java.lang.invoke.LambdaMetaFactory可以生成隐藏的nestmate类,以容纳访问封闭变量的lambda主体;

普通类是通过调用ClassLoader::defineClass创建的,而隐藏类是通过调用Lookup::defineHiddenClass创建的。这使JVM从提供的字节中派生一个隐藏类,链接该隐藏类,并返回提供对隐藏类的反射访问的查找对象。调用程序可以通过返回的查找对象来获取隐藏类的Class对象。

instanceof模式匹配

JEP 375:Pattern Matching for instanceof (Second Preview) instanceof 自动匹配模式

在Java 14中作为预览语言功能引入的instanceof模式匹配,在Java 15中处于第二次预览,而没有任何更改。

模式匹配允许程序中的通用逻辑(主要是从对象中的条件提取组件)可以更简洁地表达。Haskell 和 C# 等语言已采用模式匹配来实现简洁和安全性。

旧写法:

1
// 先判断类型if (obj instanceof String) {    // 然后转换    String s = (String) obj;    // 然后才能使用}

新写法:

1
新写法:(自动匹配模式if (obj instanceof String s) {    // 如果类型匹配 直接使用} else {    // 如果类型不匹配则不能直接使用}

示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.eh.jdk15.sealed;

public class InstanceofTest {
}

class Monitor{
    private String model;

    // 以前的写法
    /*public boolean equals(Object o) {
        if (o instanceof Monitor) {
            Monitor other = (Monitor) o;
            if (model.equals(other.model)) {
                return true;
            }
        }
        return false;
    }*/
    // 使用新特性
    public boolean equals(Object o) {
        return o instanceof Monitor other && model.equals(other);
    }
}

注意instanceof 定义的变量other作用域,只在if语句块内有效。

ZGC功能转正

JEP 377:ZGC: A Scalable Low-Latency Garbage Collector (Production) ZGC 功能转正

ZGC是Java 11引入的新的垃圾收集器(JDK9以后默认的垃圾回收器是G1),经过了多个实验阶段,自此终于成为正式特性。

自 2018 年以来,ZGC 已增加了许多改进,从并发类卸载、取消使用未使用的内存、对类数据共享的支持到改进的 NUMA 感知。此外,最大堆大小从 4 TB 增加到 16 TB。支持的平台包括 Linux、Windows 和 MacOS。

ZGC是一个重新设计的并发的垃圾回收器,通过减少 GC 停顿时间来提高性能。

但是这并不是替换默认的GC,默认的GC仍然还是G1;之前需要通过-XX:+UnlockExperimentalVMOptions -XX:+UseZGC来启用ZGC,现在只需要-XX:+UseZGC就可以。相信不久的将来它必将成为默认的垃圾回收器。

相关的参数有

1
2
3
4
5
6
7
8
ZAllocationSpikeTolerance
ZCollectionInterval
ZFragmentationLimit
ZMarkStackSpaceLimit
ZProactive
ZUncommit
ZUncommitDelay 
ZGC-specific JFR events(ZAllocationStall、ZPageAllocation、ZPageCacheFlush、ZRelocationSet、ZRelocationSetGroup、ZUncommit)也从experimental变为product

文本块功能转正

JEP 378:文本块功能转正

Text Blocks首次是在JDK 13中以预览功能出现的,然后在JDK 14中又预览了一次,终于在JDK 15中被确定下来,可放心使用了。

文本块是一种多行字符串文字,它避免了大多数转义序列的需要,以一种可预测的方式自动设置字符串的格式,并在需要时使开发人员可以控制格式,简化编写 Java 程序的任务。

文本块建议的目标是提高 Java 程序中的字符串的可读性,这些字符串表示以非 Java 语言编写的代码。 另一个目标是支持从字符串文本迁移,规定任何新构造都可以表达与字符串文本相同的字符串集,解释相同的转义序列,并且以与字符串文本相同的方式进行操作。OpenJDK 开发人员希望添加转义序列来管理显式空白和换行控件。

示例程序:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package com.eh.jdk15;


import org.testng.annotations.Test;

public class TextBlockTest {
    @Test
    public void test1() {
        String text1 = "The Sound of silence\n" +
                "Hello darkness, my old friend\n" +
                "I've come to talk with you again\n" +
                "Because a vision softly creeping\n" +
                "Left its seeds while I was sleeping\n" +
                "And the vision that was planted in my brain\n" +
                "Still remains\n" +
                "Within the sound of silence";

        System.out.println(text1);

        //jdk13中的新特性:
        String text2 = """
                The Sound of silence
                Hello darkness, my old friend
                I've come to talk with you again
                Because a vision softly creeping
                Left its seeds while I was sleeping
                And the vision that was planted in my brain
                Still remains
                Within the sound of silence\
                """;
        System.out.println();
        System.out.println(text2);

        System.out.println(text1.length());
        System.out.println(text2.length());
    }

    //html
    @Test
    public void test2() {
        String html1 = "<html lang=\"en\">\n" +
                "<head>\n" +
                "    <meta charset=\"UTF-8\">\n" +
                "    <title>java14新特性</title>\n" +
                "</head>\n" +
                "<body>\n" +
                "    <p>hello,atguigu</p>\n" +
                "</body>\n" +
                "</html>";
        //jdk13中的新特性:
        String html2 = """
                <html lang="en">
                <head>
                    <meta charset="UTF-8">
                    <title>java14新特性</title>
                </head>
                <body>
                    <p>hello,atguigu</p>
                </body>
                </html>
                """;
    }

    //json
    @Test
    public void test3() {
        //jdk13之前的写法
        String myJson = "{\n" +
                "    \"name\":\"Song Hongkang\",\n" +
                "     \"address\":\"www.atguigu.com\",\n" +
                "    \"email\":\"shkstart@126.com\"\n" +
                "}";
        System.out.println(myJson);

        //jdk13的新特性
        String myJson1 = """
                {
                    "name":"Song Hongkang",
                     "address":"www.atguigu.com",
                    "email":"shkstart@126.com"
                }""";
        System.out.println(myJson1);
    }

    //sql
    @Test
    public void test4() {
        String sql = "SELECT id,NAME,email\n" +
                "FROM customers\n" +
                "WHERE id > 4\n" +
                "ORDER BY email DESC";

        //jdk13新特性:
        String sql1 = """
                SELECT id,NAME,email
                FROM customers
                WHERE id > 4
                ORDER BY email DESC
                """;
    }

    //jdk14新特性
    @Test
    public void test5() {
        String sql1 = """
                SELECT id,NAME,email
                FROM customers
                WHERE id > 4
                ORDER BY email DESC
                """;
        System.out.println(sql1);

        // \:取消换行操作
        // \s:表示一个空格
        String sql2 = """
                SELECT id,NAME,email \
                FROM customers\s\
                WHERE id > 4 \
                ORDER BY email DESC\
                """;
        System.out.println(sql2);
        System.out.println(sql2.length());
    }
}

Records

JEP 384:Records Class(预览)

早在2019年2月份,Java 语言架构师 Brian Goetz,曾经写过一篇文章,详尽的说明了并 吐槽了Java语言,他和很多程序员一样抱怨“Java太啰嗦”或有太多的“繁文缛节”,他 提到:开发人员想要创建纯数据载体类(plain data carriers)通常都必须编写大量低价值、 重复的、容易出错的代码。如:构造函数、getter/setter、equals()、hashCode()以及 toString()等。

以至于很多人选择使用IDE的功能来自动生成这些代码。还有一些开发会选择使用一些第 三方类库,如Lombok等来生成这些方法,从而会导致了令人吃惊的表现(surprising behavior)和糟糕的可调试性(poor debuggability)。

我们有时候需要编写许多低价值的重复代码来实现一个简单的数据载体类:构造函数,访问器,equals()。hashCode(),toString()等。为了避免这种重复代码,Java 14推出record

Java14也许最令人兴奋,同时也是最令人惊讶的创新就是:Record类型的引入

使用record来减少类声明语法,效果类似lombok的@Data注解, Kotlin 中的data class。它们的共同点是类的部分或全部状态可以直接在类头中描述,并且这个类中只包含了纯数据而已。

该预览特性提供了一种更为紧凑的语法来声明类。值得一提的是,该特性可以大幅减少定义类似数据类型时所需的样板代码。

当你用record声明一个类时,该类将自动拥有以下功能:

  • 获取成员变量的简单方法,以上面代码为例name()和partner()。注意区别于我们平常的getter写法。

  • 一个equals方法的实现,执行比较时会比较该类的所有成员属性

  • 重写equals当然会重写hashCode

  • 一个可以打印该类所有成员属性的toString方法。

  • 请注意只会有一个构造方法。

和枚举类型一样,记录也是类的一种受限形式。作为回报,记录对象在简洁性方面提供了显著的好处。

示例程序:

1
2
3
4
5
6
7
package com.eh.jdk15.sealed;

public record Child(
        String name,
        Child Partner
) {
}

编译后的字节码文件:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
  // IntelliJ API Decompiler stub source generated from a class file
  // Implementation of methods is not available

package com.eh.jdk15.sealed;

public final class Child extends java.lang.Record {
    private final java.lang.String name;
    private final com.eh.jdk15.sealed.Child Partner;

    public Child(java.lang.String name, com.eh.jdk15.sealed.Child Partner) { /* compiled code */ }

    public final java.lang.String toString() { /* compiled code */ }

    public final int hashCode() { /* compiled code */ }

    public final boolean equals(java.lang.Object o) { /* compiled code */ }

    public java.lang.String name() { /* compiled code */ }

    public com.eh.jdk15.sealed.Child Partner() { /* compiled code */ }
}

注意:

  • 还可以声明构造器、静态的变量、静态的方法、实例方法
  • 不可以在Record中定义实例变量
  • Record不可以声明为abstract的
  • Record不可以显式的继承于其他类
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
 * @author shkstart  Email:shkstart@126.com
 * @create 2020 15:57
 */
public record Customer(String name,Customer partner) {
    //还可以声明构造器、静态的变量、静态的方法、实例方法

    public Customer(String name){
        this(name,null);
    }

    public static String info;

    public static void show(){
        System.out.println("我是一个客户");
    }

    public void showName(){
        System.out.println("我的名字是:" + name());
    }

    //不可以在Record中定义实例变量
//    public int id;

}

//Record不可以声明为abstract的
//abstract record User(){}

//Record不可以显式的继承于其他类
//record User() extends Thread{}

jdk15新特性(配菜)

EdDSA 数字签名算法

JEP 339:Edwards-Curve Digital Signature Algorithm(EdDSA 数字签名算法)

这是一个新的功能。新加入基于Edwards-Curve数字签名算法(EdDSA-Edwards-Curve Digital Signature Algorithm)的加密签名,即爱德华兹曲线数字签名算法。

该算法在许多其它加密库(如 OpenSSL 和 BoringSSL)中得到支持。与 JDK 中的现有签名方案相比,EdDSA 具有更高的安全性和性能,因此备受关注。它已经在OpenSSL和BoringSSL等加密库中得到支持,在区块链领域用的比较多。

EdDSA是一种现代的椭圆曲线方案,具有JDK中现有签名方案的优点。EdDSA将只在SunEC提供商中实现。

重新实现 DatagramSocket API

JEP 373:Reimplement the Legacy DatagramSocket API(重新实现 DatagramSocket API)

新的计划是JEP 353的后续,该方案重新实现了遗留的套接字API。java.net.datagram.Socket和java.net.MulticastSocket的当前实现可以追溯到JDK 1.0,那时IPv6还在开发中。因此,当前的多播套接字实现尝试调和IPv4和IPv6难以维护的方式。

通过替换 java.net.datagram 的基础实现,重新实现旧版 DatagramSocket API。更改java.net.DatagramSocket 和 java.net.MulticastSocket 为更加简单、现代化的底层实现。提高了 JDK 的可维护性和稳定性。

通过将java.net.datagram.Socket和java.net.MulticastSocket API的底层实现替换为更简单、更现代的实现来重新实现遗留的DatagramSocket API。

新的实现:1.易于调试和维护;2.与Project Loom中正在探索的虚拟线程协同。

禁用偏向锁定

JEP 374: Disable and Deprecate Biased Locking 禁用偏向锁定

在默认情况下禁用偏向锁定,并弃用所有相关命令行选项。目标是确定是否需要继续支持偏置锁定的高维护成本的遗留同步优化,HotSpot虚拟机使用该优化来减少非竞争锁定的开销。尽管某些Java应用程序在禁用偏向锁后可能会出现性能下降,但偏向锁的性能提高通常不像以前那么明显。

该特性默认禁用了biased locking(-XX:+UseBiasedLocking),并且废弃了所有相关的命令行选型(BiasedLockingStartupDelay, BiasedLockingBulkRebiasThreshold, BiasedLockingBulkRevokeThreshold, BiasedLockingDecayTime, UseOptoBiasInlining, PrintBiasedLockingStatistics and PrintPreciseBiasedLockingStatistics)

Shenandoah 垃圾回收算法转正

Shenandoah垃圾回收算法终于从实验特性转变为产品特性,这是一个从 JDK 12 引入的回收算法,该算法通过与正在运行的 Java 线程同时进行疏散工作来减少 GC 暂停时间。Shenandoah 的暂停时间与堆大小无关,无论堆栈是 200 MB 还是 200 GB,都具有相同的一致暂停时间。

Shenandoah和ZGC的异同点大概如下:

  • 相同点:性能几乎可认为是相同的
  • 不同点:ZGC是Oracle JDK的,根正苗红。而Shenandoah只存在于OpenJDK中,因此使用时需注意你的JDK版本

打开方式:使用-XX:+UseShenandoahGC命令行参数打开。

Shenandoah在JDK12被作为experimental引入,在JDK15变为Production;之前需要通过-XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC来启用,现在只需要-XX:+UseShenandoahGC即可启用

外部存储器访问 API

JEP 383:Foreign-Memory Access API (Second Incubator) 外部存储器访问 API(孵化器版)

目的是引入一个 API,以允许 Java 程序安全、有效地访问 Java 堆之外的外部存储器。如本机、持久和托管堆。

有许多Java程序是访问外部内存的,比如Ignite和MapDB。该API将有助于避免与垃圾收集相关的成本以及与跨进程共享内存以及通过将文件映射到内存来序列化和反序列化内存内容相关的不可预测性。该Java API目前没有为访问外部内存提供令人满意的解决方案。但是在新的提议中,API不应该破坏JVM的安全性。

Foreign-Memory Access API在JDK14被作为incubating API引入,在JDK15处于Second Incubator,提供了改进。

移除 Solaris 和 SPARC 端口

JEP 381:Remove the Solaris and SPARC Ports (移除 Solaris 和 SPARC 端口)

删除对Solaris/SPARC、Solaris/x64和Linux/SPARC端口的源代码和构建支持,在JDK 14中被标记为废弃,在JDK15版本正式移除。

许多正在开发的项目和功能(如Valhalla、Loom和Panama)需要进行重大更改以适应CPU架构和操作系统特定代码。

近年来,Solaris 和 SPARC 都已被 Linux 操作系统和英特尔处理器取代。放弃对 Solaris 和 SPARC 端口的支持将使 OpenJDK 社区的贡献者能够加速开发新功能,从而推动平台向前发展。

移除the Nashorn JS引擎

JEP 372:Remove the Nashorn JavaScript Engine

Nashorn是在JDK提出的脚本执行引擎,该功能是 2014 年 3 月发布的 JDK 8 的新特性。在JDK11就已经把它标记为废弃了,JDK15完全移除。

在JDK11中取以代之的是GraalVM。GraalVM是一个运行时平台,它支持Java和其他基于Java字节码的语言,但也支持其他语言,如JavaScript,Ruby,Python或LLVM。性能是Nashorn的2倍以上。

JDK15移除了Nashorn JavaScript Engine及jjs 命令行工具。具体就是jdk.scripting.nashorn及jdk.scripting.nashorn.shell这两个模块被移除了。

Graal VM在HotSpot VM基础上增强而成的跨语言全栈虚拟机,可以作为“任何语言”的运行平台使用。语言包括:Java、Scala、Groovy、Kotlin;C、C++、JavaScript、Ruby、Python、R等

废弃RMI 激活机制

JEP 385:Deprecate RMI Activation for Removal

RMI Activation被标记为Deprecate,将会在未来的版本中删除。RMI激活机制是RMI中一个过时的部分,自Java 8以来一直是可选的而非必选项。RMI激活机制增加了持续的维护负担。RMI的其他部分暂时不会被弃用。

RMI jdk1.2引入,EJB有大量使用

在RMI系统中,我们使用延迟激活。延迟激活将激活对象推迟到客户第一次使用(即第一次方法调用)之前。

既然RMI Activation这么好用,为什么要废弃呢?因为对于现代应用程序来说,分布式系统大部分都是基于Web的,web服务器已经解决了穿越防火墙,过滤请求,身份验证和安全性的问题,并且也提供了很多延迟加载的技术。所以在现代应用程序中,RMI Activation已经很少被使用到了。并且在各种开源的代码库中,也基本上找不到RMI Activation的使用代码了。

为了减少RMI Activation的维护成本,在JDK8中,RMI Activation被置为可选的。现在在JDK15中,终于可以废弃了。

jdk15新特性(饭后甜点)

添加项

  • Support for Unicode 13.0 (JDK-8239383)

    升级了Unicode,支持Unicode 13.0

  • Added isEmpty Default Method to CharSequence (JDK-8215401)

    给CharSequence新增了isEmpty方法 java.base/java/lang/CharSequence.java

  • Specialized Implementations of TreeMap Methods (JDK-8176894)

    JDK15对TreeMap提供了putIfAbsent, computeIfAbsent, computeIfPresent, compute, merge方法提供了overriding实现

  • New Option Added to jcmd for Writing a gzipped Heap Dump (JDK-8237354)

    jcmd的GC.heap_dump命令现在支持gz选型,以dump出gzip压缩版的heap;compression level从1(fastest)到9(slowest, but best compression),默认为1

  • Added Support for SO_INCOMING_NAPI_ID Support (JDK-8243099)

    jdk.net.ExtendedSocketOptions新增了SO_INCOMING_NAPI_ID选型

  • New System Properties to Configure the TLS Signature Schemes (JDK-8242141)

    新增了jdk.tls.client.SignatureSchemes及jdk.tls.server.SignatureSchemes用于配置TLS

  • Signature Schemes Support for certificate_authorities Extension (JDK-8206925)

    支持certificate_authorities的扩展

移除&废弃项

移除:

Obsolete -XX:UseAdaptiveGCBoundary (JDK-8228991)

废弃:

  • Deprecated -XX:ForceNUMA Option (JDK-8243628)

  • Disable Native SunEC Implementation by Default (JDK-8237219)

    默认禁用了Native SunEC Implementation

其他事项

  • java.net.HttpClient Does Not Override Protocols Specified in SSLContext Default Parameters (JDK-8239594)

    HttpClient现在没有覆盖在SSLContext Default Parameters中指定的Protocols

  • DatagramPacket.getPort() Returns 0 When the Port Is Not Set (JDK-8237890)

    当DatagramPacket没有设置port的时候,其getPort方法返回0

  • Improved Ergonomics for G1 Heap Region Size (JDK-8241670)

    优化了默认G1 Heap Region Size的计算