JDK10 揭秘

Posted 程序员阿凯

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JDK10 揭秘相关的知识,希望对你有一定的参考价值。

前言

Java自1995年发布至今,已经度过23个年头;JAVA也已经推出了10个大的版本,2018年3月20日正式推出JDK10正式版本。新的版本也隐藏了许多新的奥秘,那么本课就将深入浅出的探究一下JDK10新特性。

课程简介

大家都知道开发的核心是JDK,那么每一版新的JDK发布,都标志着Java的进程,Java的前进方向。工欲善其事,必  先利其器。作为老牌军 Java 在发行二十多年的今天,战胜了C 和 C++,成为诸多开发者的宠儿,且如今从其更新速度来看,也是不甘落后。JDK 10 是 Java 10 标准版的部分实现,于 2018 年 3 月 20 日发布,改进的关键点包括一个本地类型推断、一个垃圾回收的“干净”接口。

JDK10 揭秘

知识点

新特性之一个局部变量类型推断

新特性之一个干净的垃圾收集器接口新特性之G1  垃圾收集器的优化

新特性之支持备用内存设备

新特性之基于Java实验性的JIT编辑器新特性之应用程序数据共享

新特性之线程本地握手

新特性之基于时间发布的版本控制

新特性之整合源树sourcetree的JDK库


第一章 OpenJDK

1.1简介

Sun 公司在 2006 年的 JavaOne 大会上称将对 Java 开放源代码,于2009年4月15日正式发布 OpenJDK。

 OpenJDK做为GPL许可(GPL-licensed)的Java平台的开源化实现.从发布那一时刻起,Java社区的大众们就又开始  努力学习,以适应这个新的开源代码基础(code-base)。OpenJDK在2013年发展迅速,被著名IT杂志SD     Times 评选为2013 SD Times 100,位于“极大影响力”分类第9位。在 2015 年年底,Google宣布,他们将 Oracle JavaJDK 替换为了开源的 OpenJDK。

闭源的Oracle JDK和OpenJDK之间并不存在显著的性能差异。但是,我看到 了一个明确的消息(至少是最近), 那就是开源版本总是跟随着Oracle的产品,这可能是开始评估使用开源版本的一个原因。

JDK10 揭秘

1.2JDK10 新特性

新的特性和增强一般通过Java Enhancement Process(JEP)或Java Community  Process标准请求(JSR)进行跟踪。因为Java   10的时间线较短,范围也相对较小,所以Java   10的变更将通过JEP进行跟踪。


被包含在Java     10中的特性是那些已经处于确定或推荐状态状态的JEP,它们包括(详情页):

286:局部变量类型推断

296:统一JDK仓库

304:垃圾收集器接口

307:G1的并行Full  GC

310:应用程序类数据共享

312:线程本地握手

313:移除本地报头生成工具(javah)

314:附加Unicode语言标签扩展

316:替代存储设备上的堆分配

317:基于实验Java的JIT编译器

319:根证书

322:基于时间的版本控制

JDK10 揭秘

第二章 下载安装

去官网下载,按步骤安装即可。略......


第三章 局部变量类型推断

3.1概述

每次JDK版本的提升,都会有很多特性出来,对于一般的程序员来讲,可以很直观学习到的就是规范了,比如JDK5中  泛型的出现,提高了程序的灵活性;又比如JDK5中增强for循环,简便了代码的书写,大大提高了开发效率……这些  例子不胜枚举,就不一一赘述了。对于JDK10来讲最为显著的就是引入了局部类型变量推断这个特性。这个特性可   以理解为是JDK8开始可推导可省略的思想的延伸。

在JDK8出现的新特性中加入了函数式接口,即适用于函数式编程场景的接口。而Java中的函数式编程体现就是

Lambda,所以函数式接口就是可以适用于Lambda使用的接口。只有确保接口中有且仅有一个抽象方法,Java中  的Lambda才能顺利地进行推导。


3.2练习:使用Lambda标准格式(有参有返回)


JDK10 揭秘

题目

给定一个计算器 Calcuator 接口,内含抽象方法 calc 可以将两个int数字相加得到和值:

1public interface Calculator { 
2    int calc(int a, int b);
3}

在下面的代码中,请使用Lambda的标准格式调用 方法,完成120和130的相加计算:

1public class InvokeCalc {
2    public static void main(String[] args) {
3      // TODO 请在此使用Lambda【标准格式】调用invokeCalc方法来计算120+130的结果ß
4    }
5    private static void invokeCalc(int a, int b, Calculator calculator) {
6        int result = calculator.calc(a, b);
7        System.out.println("结果是:" + result);
8    }
9}

解答

1public static void main(String[] args) {
2    invokeCalc(120, 130, (int a, int b) ‐> {return a + b;});
3}

备注:小括号代表 Caluator 接口 calc 抽象方法的参数,大括号代表 calc 的方法体。


3.3Lambda省略格式


可推导即可省略

Lambda强调的是“做什么”而不是“怎么做”,所以凡是可以根据上下文推导得知的信息,都可以省略。例如上例还可  以使用Lambda的省略写法:

1public static void main(String[] args) { 
2    invokeCalc(120, 130, (a, b) ‐> a + b);
3}


省略规则

在Lambda标准格式的基础上,使用省略写法的规则为:

1.小括号内参数的类型可以省略;

2.如果小括号内有且仅有一个参,则小括号可以省略;

3.如果大括号内有且仅有一个语句,则无论是否有返回值,都可以省略大括号、return关键字及语句分号。


3.3 局部变量类型推断

这一版本最明显的一个新特性就是局部变量类型推导,在OpenJDK JEP  286中有详细的介绍,那么本文就将深入浅出的学习一下新特性的使用方式。

OpenJDK中的 JEP指的是JDK提供了一些更好的特性和高级支持。286: Local-Variable Type Inference

概要:增强Java语言,用来将类型推断扩展到有初始值设定项的局部变量声明。

这种处理方式必须是具有可推导性的,并且具有约束条件的。

其他静态类型语言, 如 C++, Scala, 和 Go,都已经实现了局部变量类型推断。

因为Java仍缺乏这样的功能,它要求开发人员显式声明变量的预期清单类型。为了解决这个问题,Java开发工具包

(  JDK)改进建议(  JEP)286提出了一个上下文敏感的关键字var,允许局部变量被以下方式初始化。


描述

Java开发人员在开发过程中经常会发现标准样板代码体积臃肿。

也就是说使用变量的时候,用来声明名字重点在于名字起得是什么,重点并不是接收的数据类型。该计划限制了类  型推断的使用场景:  有初始值的局部变量,  增强型for循环中的index,  普通for循环里的局部变量。

由于var关键字是上下文敏感的,它的使用有下面的规则定义:



备注:“语法糖”是指使用更加方便,但是原理不变的代码语法。例如在遍历集合时使用的for-each语法,其实 底层的实现原理仍然是迭代器,这便是“语法糖”。从应用层面来讲,Java中的Lambda可以被当做是匿名内部  类的“语法糖”,但是二者在原理上是不同的。

它其实是个语法糖,在语义上并没有任何变化。接下来演示一下使用场景:

有初始值的局部变量:

1public static void main(String[] args){
2var itcast = new Student("KK爱Java");// 原型为 Student 类型
3}

增强型for循环中的index:

1public static void main(String[] args){
2    var list = new ArrayList<String>();// 原型为 ArrayList<String> 类型
3    list.add("1");
4    list.add("3");
5    list.add("4");
6    for (var i : list) { //原型为 String 类型
7        System.out.println(i);
8    }
9}

普通for循环里的局部变量:

 1public static void main(String[] args){
2    var arr = new String[3];// 原型为 String[]类型
3    arr[0]="小明";
4    arr[1]="小红";
5    arr[2]="小张";
6    for (var i = 0; i < arr.length; i++) {
7        var value = arr[i]; //原型为 String 类型
8        System.out.println(value);
9    }
10}

既然是可推导的,那么作为类型接收同样可以用在有返回值方法接收上,以及有返回值lambda表达式上。

1public class Student {
2    public static void main(String[] args){
3        var sum = sum(2,4);
4        var read = new Thread(()‐> System.out.println("青铜卡了好久了"));
5    }
6    public static int sum(int a ,int b){
7        return a+b;
8    }
9}


第四章 JDK10有趣的特性


4.1整合的JDK库

296:Consolidate the JDK Forest into a Single Repository

统一JDK仓库,目前,JDK9有8个不同的Mercurial存储库用于存储包含JDK的大量源代码:

(1)root(2)corba(3)hotspot(4)jaxp(5)jaxws(6)JDK(7)langtools(8)nashorn

虽然过多的存储库提供了对组成JDK的各种组件并清晰分离,但管理多个存储库存在一些主要的缺点。其中最重要   的一点是,在JDK的两个不同部分,单个错误修复程序不能被原子跟踪。例如,如果一个bug修复需要对独立存储     库中包含的系统的两个部分进行更改,那么必须提交两个提交:每个存储库中一个。这种不连续性很容易地降低项目  和源代码管理工具的可跟踪性和复杂性。    为了解决这个问题,JEP  296建议将所有现有存储库合并到一个

Mercurial存储库中。这种合并的一个次生效应是,这个单一的Mercurial存储库比现有的8个存储库要更容易的被  镜像(作为一个Git存储库)。虽然在这个整合过程中,外部开发人员有一些阻力,但是JDK开发团队似乎已经致力于  使这一更改成为JDK 10的一部分。有关更多信息,请参见JEP 296,并提议整合由Michael Redlich发布的JDK 10 OpenJDK  Mercurial存储库声明。

简而言之,将 JDK  的多个存储库合并成一个,简化开发。目前的代码库被分解成了多个库,容易出现源代码的管理问题。

—— corba:不流行的多语言、分布式通讯接口

 —— hotspot:Java 虚拟机

 —— jaxp:XML 处理 

——  jaxws:一组 XML web services 的 Java API

 —— jdk:java 开发工具包 

—— share:针对操作系统的部分 , 与平台无关的实现

 —— langtools:Java 语言工具

 —— nashorn:JVM 上的 javascript 运行时


4.2应用程序类数据共享

310: Application Class-Data Sharing

应用程序类数据共享,JEP  310对类数据共享(CDS)进行了扩展,JVM可以将一些类记录到一个共享的压缩文件里,在JVM下一次启动时可以将这个文件映射到JVM进程,以此来减少启动时间。该文件也可以在多个JVM间共     享,在同一个机器上运行多个JVM时,这样做可以减少内存占用。

该功能在Java  5中就已存在,但截止到Java  9,该功能只允许bootstrap类加载器加载压缩的类。JEP  310的目的是扩展该功能,让应用程序和自定义类加载器也能加载压缩的类。该特性目前仅在Oracle  JDK中可用,OpenJDK并不包含该特性。JEP计划将该特性从Oracle私有仓库中迁移到公共仓库,从Java     10往后,常规版本(非LTS)将会使用OpenJDK的二进制包。此举表明有用户正在使用该特性,所以需要在OpenJDK中也支持该特性。

简而言之,应用程序类数据共享,通过跨进程共享通用类元数据来减少占用空间。启动时间也得到了改善。


4.3常规更新

313: Remove the Native-Header Generation Tool (javah)

去掉 javah 工具。

从 JDK 8 开始,javah 的功能已经集成到了 javac 中。所以,javah 可以删掉了。Java9 开始了一些对 JDK 的家务管理,这项特性是对它的延续。当编译 JNI 代码时,已不再需要单独的工具来生成头文件,因为这可以通过 javac 完成。在未来的某一时刻,JNI  将会被  Panama  项目的结果取代,但是何时发生还不清楚。


314: Additional Unicode Language-Tag Extensions

额外的 Unicode 语言标签扩展。

增强java.util.Locale和相关 API,包括:cu (货币类型)、fw (每周第一天为星期几)、rg (区域覆盖)、tz (时区)等。


316: Heap Allocation on Alternative Memory Devices

在备用内存设备上分配堆内存。

允许 HotSpot 虚拟机在备用内存设备上分配 Java 对象堆。硬件技术在持续进化,现在可以使用与传统 DRAM 具有相同接口和类似性能特点的非易失性 RAM( NV-DIMM) 。这项 JEP 将使得 JVM 能够使用适用于不同类型的存储机制的堆。


317: Experimental Java-Based JIT Compiler

实验性的基于 Java 的 JIT 编译器。

支持基于 Java 的 JIT 编译器。相关工作主要基于 Graal。Graal 也是 Java 9 中引入的 AOT 编译器的基础。乍一想, 觉得很奇怪。如果 JVM 是用 Java 编写的,那么是否需要一个 JVM 来运行 JVM ? 相应的,这导致了一个很好的镜像类比。 现实情况是,使用 Java 编写 JVM 并不意味着必须将其编译为字节码,你可以使用 AOT 编译,然后在运行时编译代码以提高性能。


319: Root Certificates

根证书。

开源 Java SE Root CA 程序中的根证书。目标是开源 Oracle 的 Java SE Root CA 程序中的根证书,以使 OpenJDK 对开发人员更具吸引力。这是 Oracle 正在努力确保 OpenJDK 二进制和 Oracle JDK 二进制功能上一样的工作的一部分,是一项有用的补充内容。


322: Time-Based Release Versioning

基于时间的版本字符串。

修改 Java SE 平台和 JDK 版本字符串机制。

Oracle Java 平台组首席架构师 Mark Reinhold 在博客上介绍了有关 Java 未来版本的一些想法(你能接受Java 9的 下一个版本是Java 18.3吗?)。他提到,Java  计划按照时间来发布,每半年一个版本,而不是像之前那样按照重要特性来确定大版本,如果某个大的特性因故延期,这个版本可能一拖再拖。  当时,Mark  也提出来一种基于时间命名版本号的机制,比如下一个将于 2018 年 3 月发布的版本,就是 18.3,再下一个版本是 18.9,依此类推。 不过经过讨论,考虑和之前版本号的兼容等问题,最终选择的命名机制是: INTERIM.

PATCH $FEATURE,每次版本发布加 1,不考虑具体的版本内容。(之前的主版本号部分)2018 年 3 月的版本是JDK 10,9 月的版本是 JDK 11,依此类推。 $INTERIM,中间版本号,在大版本中间发布的,包含问题修复和增强的版本,不会引入非兼容性修改。


第五章 JVM优化

304: Garbage-Collector Interface 

307: Parallel Full GC for G1 

312: Thread-Local Handshakes


304: 垃圾收集器接口,在 hotspot/gc 代码实现方面,引入一个干净的垃圾收集器接口,改进不同垃圾收集器源代码的隔离性。这样添加新的或者删除旧的   GC,都会更容易。

可以这样理解,增加GC接口意味着厂商可以更自由地选择特定的GC算法来构建JDK,因为现在有多种处于开发当     中的GC,如Shenandoah、ZGC和Epsilon,在未来可以使用这些GC算法。这样做是为了更好地模块化 HotSpot  虚拟机中的内部垃圾回收代码,使向  HotSpot  添加新的垃圾回收器更加容易。

307:   G1的并行Full   GC,从JDK8开始启用G1,在JDK9中移除JDK8中废除的GC组合,在32/64位服务器版配置中,

G1成为默认垃圾回收策略。使用低停顿时长的垃圾回收器如G1相较之前默认的流量优先的回收器如Parellel  GC, 能为大部分用户提供更好的体验。改进G1可用性、决策和性能,弃用CMS垃圾回收器。

当在命令行指定     -  XX:+UseConcMarkSweepGC时会有警告信息。G1垃圾回收器会取代大部分CMS的使用场景。

JDK10又对G1进行了提升,而且还有加入人体工学的设想(这个版本并没有),为了减少JDK  9之外的JDK版本中垃圾收集的影响,G1收集器将被并行化(以匹配并行收集器的特征)。虽然目前还没有关于这个并行化的实现细节的信息,但是可以在JEP   307规范中找到关于此更改的更多细节。有关GC实现的更多信息,请参阅Oracle的G1指南和并行收集器指南。简 单理解,解决了G1垃圾回收器的一个问题——截止到Java  9,G1的Full  GC采用的是单线程算法。也就是说,G1在发生Full  GC时会严重影响性能。JEP  307的目的就是要采用并行GC算法,在发生Full  GC时可以使用多个线程进行 并行回收。

312:  线程本地握手,修改安全点机制,使得部分回调操作只需要停掉单个线程,而不像以前那样,只能选择或者停掉所有线程,或者都不停止。

旨在改进虚拟机性能,在应用程序线程上调用回调不再需要执行全局虚拟机安全点操作,这意味着JVM可以停止单  个线程。一些底层小改进包括:

降低堆栈跟踪取样所带来的影响(如进行profiling)。减少信号依赖以获得更好的堆栈取样。

通过停止单独线程改进偏向锁。从JVM移除了一些内存屏障。

“局部变量的类型推断”可以说是这 12 个 JEP 中最受关注的,为支持此特性,开发团队也对 Java 语言规范做了一些更改,包括改变具有相同名称的静态类型的导入规则、将  var   作为局部变量类型推断的特殊标识符等等。

此外还包括新增的 73 个标准类库,对 JVM 规范的更改,以及一些其他更改项。


第六章 新API

有 73 项新增内容添加到了标准类库中。

java.awt.Toolkitint getMenuShortcutKeyMaskEx(): 确定哪个扩展修饰符键是菜单快捷键的适当加速键。

java.awt.geom.Path2D:

void trimToSize(): 将此 Path2D 实例的容量计算到它当前的大小。应用可使用此操作将路径的存储空间最小化。这个方法也被添加到 Path2D.Double 和 Path2D.Float 类。

java.io.ByteArrayOutputStream:String toString(Charset): 重载 toString(),通过使用指定的字符集解码字节,将缓冲区的内容转换为字符串。

java**.io.PrintStream:lang.io.PrintWriter:**

这两个类都有三个新的构造函数,它们需要额外的  Charset  参数。

java.io.Reader:long transferTo(Writer): 从这个 Reader 中读取所有字符,并按照所读的顺序将字符写入给定的 Writer 。


java.lang.Runtime.Version:

有四种新方法返回新(JEP 322)版本字符串字段的整数值: feature()、interim()、patch() 和 update() 。

java.lang.StackWalker.StackFrame:

String getDescriptor(): 按照 JVM 标准返回此堆栈帧所代表的方法的描述符。

String getMethodType():返回此堆栈帧所代表的方法类型,描述参数类型和返回值类型。java.lang.invoke.MethodType:Class<?>  lastParameterType():返回这个方法类型的最后一个参数类型。如果这个方法类型没有参数,则返回空类型作为岗哨值(Sentinel Value)。java.lang.management.RuntimeMXBean:long getPid(): R 返回正在运行的 JVM 的进程 ID 。java.lang.management.ThreadMXBean:ThreadInfo[] dumpAllThreads(boolean, boolean, int): 返回所有活动线程的线程信息,其中有指定的最大元素数量和同步信息的堆栈跟踪。

ThreadInfo[] getThreadInfo(long[], boolean, boolean, int): 返回每个线程的线程信息,这些线程的标识位于输入数组中,其中有指定的最大元素数量和同步信息的堆栈跟踪。

java.lang.reflect.MalformedParameterizedTypeException:  添加了一个新的构造函数,它以字符串的形式作为参数来获取详细信息。

java.net.URLDecoder:java.net.URLEncoder:

java.nio.channels.Channels:

两个新的静态重载方法,允许使用  Charset  的  newReader(ReadByteChannel,Charset)和

newWriter(WriteByteChannel,Charset)。

java.nio.file.FileStore:long  getBlockSize():  在这个文件存储中返回每个块的字节数。

java.time.chrono: 这个包里有三个类,HijrahEra、MiinguoEra 和 ThaiBuddhistEra ,都有同样的方法。

String getDisplayName(TextStyle, Locale): 这将返回用于识别 era 的文本名称,适合于向用户展示。

java.time.format.DateTimeFormatter:localizedBy(Locale):   返回指定格式器的一个副本,其中包含地区、日历、区域、小数和/或时区的本地化值,这将取代该格式器中的值。

java.util: DoubleSummaryStatistics、IntSummaryStatistics 和 LongSummaryStatistics 都有一个新的构造函数,它包含  4   个数值。它使用指定的计数、最小值、最大值和总和构造一个非空实例。

java.util.List:java.util.Map:java.util.Set:     这些接口中的每一个都增加了一个新的静态方法,

copyOf(Collection)。这些函数按照其迭代顺序返回一个不可修改的列表、映射或包含给定集合的元素的集  合。

java.util.Optional:java.util.OptionalDouble:java.util.OptionalInt:java.util.OptionalLong:        每 一 个 类都有一个新的方法,orElseThrow() ,它本质上和 get() 一样,也就是说,如果 Optional 有值则返回。否则, 将抛出 NoSuchElementException 。

java.util.Formatter: java.util.Scanner:

这两个类都有三个新的构造函数,除了其他参数之外,它们都带有一个  charset  参数。

java.util.Properties: 这有一个新的构造函数,它接受一个 int 参数。这将创建一个没有默认值的空属性列表,并且指定初始大小以容纳指定的元素数量,而无需动态调整大小。还有一个新的重载的 replace 方法,接受三个 Object 参数并返回一个布尔值。只有在当前映射到指定值时,才会替换指定键的条目。java.SplittableRandom:

void nextBytes(byte[]): 用生成的伪随机字节填充一个用户提供的字节数组。

java.util.concurrent.FutureTask: 添加了 toString() 方法,该方法返回一个标识 FutureTask 的字符串,以及它的完成状态。在括号中,状态包含如下字符串中的一个,“Completed   Normally”   、“Completed

Exceptionally”、 “Cancelled” 或者 “Not completed”。java.util.concurrent.locks.StampedLock:

boolean isLockStamp(long): 返回一个标记戳表示是否持有一个锁。

boolean isOptimisticReadStamp(long): 返回一个标记戳代表是否成功的进行了乐观读(optimistic

read)。


boolean isReadLockStamp(long): 返回一个标记戳表示是否持有一个非独占锁(即 read lock )。

boolean isWriteLockStamp(long): 返回一个标记戳表示是否持有一个独占锁(即 write lock )。

java.jar.JarEntry:

String getRealName(): 返回这个 JarEntry 的真实名称。如果这个 JarEntry 是一个多版本 jar 文件的入口, 它被配置为这样处理,这个方法返回的名字是  JarEntry   所代表的版本条目的入口,而不是

ZipEntry.getName() 返回的基本条目的路径名。如果 JarEntry 不代表一个多版本 jar 文件的版本化条目或者 jar 文件没有被配置为作为一个多版本 jar 文件进行处理,这个方法将返回与 ZipEntry.getName() 返回的相同名称。

java.util.jar.JarFile:

Stream versionedStream(): 返回 jar 文件中指定版本的入口对应 Stream 。与 JarEntry 的 getRealName 方法类似,这与多版本 jar 文件有关。java.util.spi.LocaleNameProvider:getDisplayUnicodeExtensionKey(String, Locale): 为给定的

Unicode  扩展键返回一个本地化名称。

getDisplayUnicodeExtensionType(String, String, Locale): 为给定的 Unicode 扩展键返回一个本地化名称 。     java.util.stream.Collectors:toUnmodifiableList():toUnmodifiableSet():toUnmodifiableMap(Functi         on,  Function):

toUnmodifiableMap(Function, Function, BinaryOperator): 这四个新方法都返回 Collectors ,将输入元素聚集到适当的不可修改的集合中。

java.lang.model.SourceVersion: 现在有了一个字段,它代表了 JDK 10 的版本。java.lang.model.util.TypeKindVisitor6: javax.lang.model.util.TypeKindVisitor9:

(我必须承认,我从来没听说过这些类)

R visitNoTypeAsModule(NoType, P): 访问一个 MODULE 的 pseudo-type 。我不确定为什么只有这两个类得到这个方法,因为还有 Visitor7 和 Visitor8 变量。javax.remote.management.rmi.RMIConnectorServer:

这个类已经添加了两个字段: CREDENTIALS_FILTER_PATTERN 和 SERIAL_FILTER_PATTERN 。

javax.ButtonModel:看,Swing  还在更新!

ButtonGroup getGroup(): 返回按钮所属的组。通常用于单选按钮,它们在组中是互斥的。

javax.plaf.basic.BasicMenuUI:

Dimension  getMinimumSize(JComponent):  返回指定组件适合观感的最小大小。


从整体来看,Java  10似乎并没有包含重大新特性或性能改进。这是可以理解的,毕竟这是新发布周期下的第一个版本。

如上所述,尽管距离 JDK 9 发布仅有六个月的时间,但 JDK 10 实际上有相当多的变化。当然,它们中的一些是非常小的变更,但我认为这表明目前每 6  个月发布一次的节奏,将在 Java  平台快速迭代改进方面起到作用。

同时也让我们期待 JDK 11 将带来些什么…

 JDK 11 的页面已经出现了四个 JEP ,包括:动态类文件常量(JEP 309,Dynamic Class-File Constants)、低开销垃圾收集器 Epsilon(JEP 318)、移除 Java EE 和 CORBA 模块(JEP 320),以及 Lambda 参数的本地变量语法

(JEP 323)。JDK 11 计划于 2018 年 9 月发布,并有望成为新的 LTS 版本。


 

以上是关于JDK10 揭秘的主要内容,如果未能解决你的问题,请参考以下文章

拼多多探究Java并发底层原理JDK源码解析大揭秘,由浅入深看源码

揭秘Java高效随机数生成器

揭秘 Python 中的 with 关键字

C 主导C++与 C# 为辅,揭秘 Windows 10 源代码!

JDK常用数据结构

# Java 常用代码片段