一帆磨砺

生活所迫,一叶孤舟

0%

Java版本特性-JDK10

引用参考文档链接

  1. JDK10特性列表
  2. megamorphic-virtual-calls
  3. class-data-sharing
  4. javah

写在开头

  1. JDK10的更新内容不多,核心就是局部变量类型推断
  2. Heap Allocation on Alternative Memory Devices可能在未来会发挥相当重要的作用,不过是在运维层面了,是和机器的物理架构相结合的技术
  3. 有一些面对运行性能的优化,比如G1的全并行Thread-Local Handshakes基于 Java 的 JIT 编译器,分别针对垃圾回收、多线程场景、代码编译,并且这几项技术启用需要做额外的性能测试,以确认是否在生产环境使用

局部变量类型推断

简单来说就是在部分场景里,降低了对类型的关注度,减轻编码负担

1
2
var list = new ArrayList<String>();  // infers ArrayList<String>
var stream = list.stream(); // infers Stream<String>

局限

  1. var声明对象必须初始化,初始化也不可以为null
    1
    2
    3
    4
    // Cannot infer type: 'var' on variable without initializer
    var a;
    // Cannot infer type: variable initializer is 'null'
    var b = null;
  2. var声明对象不可接收lambda表达式
    1
    2
    // Cannot infer type: lambda expression requires an explicit target type
    var c = () -> 1;
  3. var声明对象初始化数组时必须指定数组类型
    1
    2
    3
    // 编译器会直接异常提示
    // var k = { 1 , 2 };
    var k = new int[]{1, 2};

JDK源码整合为一个工程

特性详情页来看,该特性主要是为了bug修复方便,因为多工程模式下,存在部分bug涉及多工程,这样bug的修复提交就不是原子性的了,工程合并之后,bug修复提交就是原子性操作。

1
2
3
4
5
6
7
8
$ROOT/jdk/src/java.base
...
$ROOT/langtools/src/java.compiler
...
变更为
$ROOT/src/java.base
$ROOT/src/java.compiler
...

垃圾收集器接口

虚拟机内部的代码重构,对外部不影响,方便JDK的内部GC开发人员扩展垃圾收集器和虚拟机开发人员更容易理解垃圾收集器相关代码(容易找到,之前的代码是散落的,甚至部分由if-else维护),不过以下这段原文可能需要额外注意

There is a risk that performance could be harmed, for example if additional virtual calls would be introduced. This risk can be mitigated by continuous performance testing.

大致意思是性能可能会受到影响,并用virtual calls的额外调用举例。因此JDK10+版本需要多做性能测试,以避免该影响。关于virtual call可参考megamorphic-virtual-calls,大体场景可以理解为父类声明变量接收子类对象,调用函数时,因是在运行时确定,该情况可以称作virtual call。(主要还是看编译后的字节码,反编译为汇编时,看到指令invokevirtual基本就是了)

G1的GC全并行

万恶的JDK9将G1设置为默认垃圾收集器的尾声,在JDK10之前,mark-sweep-compact的算法实现(full GC场景)采取的单线程,在JDK10中,该实现修改为多线程实现,线程数与年轻代和混合代(?Mixed)收集线程数一致,并且该线程数可通过启动参数-XX:ParallelGCThreads指定。
但是原文中有这么一句话

The fact that G1 uses regions will most likely lead to more wasted space after a parallel full GC than for a single threaded one.

具体没说是怎么样的浪费空间,内存是一定回收了的,我推测是并行可能会导致空间碎片比较多,影响后续内存使用

CDS(Class-Data Sharing)的应用级拓展

CDS(Class-Data Sharing)在JDK5中引入(感兴趣可以研究class-data-sharing原文)
在JDK10中将JDK内部的CDS拓展到应用级别,可以指定类到归档文件(archive file),可以有效的减少应用启动时间和内存消耗。但是根据原文描述,个人理解该技术仅限于多个Java应用程序在同一个系统镜像内运行,才可以有效的发挥作用,对于目前大多数公司的实际运行环境(一个应用一个镜像)来说,该技术没有什么实际意义。
JDK8/JDK9已经有APPCDS的实现,因此在长期的测试中,基本不需要考虑风险和稳定性问题….

Thread-Local Handshakes

实在不知道怎么翻译,用了原文,该技术是想通过减少全局安全点从而降低JVM的延迟,尤其是在GC领域。
没说具体实现,但在偏向锁、堆栈追踪、G1有良好的优化功能

删除了javah

功能被JDK8的javac的拓展功能所取代,在JDK10中才删除
javah就是当java代码调用native方法(C/C++本地实现)时,生成对应的文件头,方便JVM运行时调用
应该是安卓场景会用到

Unicode拓展

增强了类java.util.Locale及相关API拓展支持bcp47.
JDK7就已经在日期和数字上针对bcp 47进行了补充实现,在JDK10中进行了更完整的拓展实现。

An IETF BCP 47 language tag is a standardized code or tag that is used to identify human languages in the Internet.
——-wiki

从wiki的这段话来理解就是各国语言的标识,在国际化场景中会有重要的作用,例如安卓…..

Heap Allocation on Alternative Memory Devices

痛苦,没办法精确的翻译,还没确定Alternative Memory Devices指代的是什么,从原文的理解来说,应该是一台物理机器有多个内存系统,尤其是针对non-DRAM内存系统,可以通过指令-XX:AllocateHeapAt=<path>去辅助JVM在这种类型的内存上进行堆分配。
这应该是一项未来将会发挥很大作用的功能,尤其是在简单了解NV-DIMM之后。这算是硬件适配。

基于 Java 的 JIT 编译器

可以预先把Java代码编译为本地代码,以提高运行效率。通过-XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler开启。
存在以下风险:

  1. 启动会变慢
  2. 堆的使用将会难以评估
    需要额外的性能测试指标去覆盖,以确认是否需要开启该功能。

根证书

为了推广OpenJDK和降低OpenJDKOracle JDK差异的。

基于时间的发布版本控制

新的JDK版本号规则,影响不大,直观影响就是java -v显示信息会和以往不同…

1
$FEATURE.$INTERIM.$UPDATE.$PATCH

欢迎关注我的其它发布渠道