赶紧收藏,Java 9~Java 17主要更新都在这了

简介: 这是James Gosling最近在接受采访时,被问及“Java 的版本一直以来更新得比较快,几个月前发布了最新的 Java 17 版本,但 Java 8 仍然是开发人员使用的主要版本,新版本并未‘得宠’,您认为主要的原因是什么?”时的回答。

James Gosling:对继续坚守 Java8 的朋友,我想说“是时候作出改变了”。新系统全方位性更强、速度更快、错误也更少、扩展效率更高。无论从哪个角度看,大家都有理由接纳 JDK17。确实,大家在从 JDK8 升级到 JDK9 时会遇到一个小问题,这也是 Java 发展史中几乎唯一一次真正重大的版本更替。大多数情况下,Java 新旧版本更替都非常简单。只需要直接安装新版本,一切就能照常运作。长久以来,稳定、非破坏性的升级一直是 Java 的招牌特性之一,我们也不希望破坏这种良好的印象。


这是James Gosling最近在接受采访时,被问及“Java 的版本一直以来更新得比较快,几个月前发布了最新的 Java 17 版本,但 Java 8 仍然是开发人员使用的主要版本,新版本并未‘得宠’,您认为主要的原因是什么?”时的回答。


而随着即将正式发布的Spring framework 6 和Spring Boot 3,最低的Java版本就直接以Java 17起步:


14.png


这么一来,如果到时候为了使用最新版本的Spring功能,我们不得不从Java 8升级到Java 17,而期间跳过的版本主要内容如果我们不了解的话,必定会遇到许多问题。


所以,这里,强哥就帮大家总结了Java 9到Java 17的主要内容更新,值得大家收藏。


Java 9


主要更新内容:


  • 平台模块系统(Jigsaw项目)
  • 接口私有方法
  • Try-With Resources
  • @SafeVarargs注释
  • 集合工厂方法
  • Process API改进
  • JShell:javashell(REPL)
  • 流API改进

Java 9最大特性就是引入了模块化的概念。就是将类型和资源封装在模块中,并仅导出其他模块要访问其公共类型的软件包。有些类似前端框架中的export和import。


如果模块中的软件包未导出或打开,则表示模块的设计人员不想在模块外部使用这些软件包。这样的包可能会被修改或甚至从模块中删除,无需任何通知。


与此同时,模块化将rt.jar包做了拆分,导致了ClassLoader的相应调整:


Java 9之前的ClassLoader


  • Bootstrap ClassLoader加载rt.jar,jre/lib/endorsed
  • Ext ClassLoader加载jre/lib/ext
  • Application ClassLoader加载-cp指定的类


Java 9及之后的ClassLoader


  • Bootstrap ClassLoader加载lib/modules
  • Ext ClassLoader更名为Platform ClassLoader,加载lib/modules
  • Application ClassLoader加载-cp,-mp指定的类
  • Application ClassLoader父类不再是URLClassLoader


而接口私有方法,允许我们声明有助于在非抽象方法之间共享公共代码的私有方法。在Java 9之前,在接口中创建私有方法会导致编译时错误。


Java 10


主要更新内容:


  • 局部变量的类型推断。
  • 应用类数据共享。为改善启动和占用空间,在现有的类数据共享(“CDS”)功能上再次拓展,以允许应用类放置在共享存档中
  • 向G1引入并行Full GC
  • 线程局部管控。允许停止单个线程,而不是只能启用或停止所有线程
  • 基于Java的JIT 编译器(试验版本)


局部变量类型推断是Java10中为开发人员提供的最大的新特性。它将类型推断添加到带有初始值设定项的局部变量声明中。局部类型推断只能在以下情况下使用:


  • 仅限于具有初始值设定项的局部变量
  • 增强for循环的索引
  • 在for循环中声明的本地


其实就是类似JS的var变量,用法如下:


var numbers = List.of(1, 2, 3, 4, 5); // inferred value ArrayList<String>// Index of Enhanced For Loopfor (var number : numbers) {    System.out.println(number);}// Local variable declared in a loopfor (var i = 0; i < numbers.size(); i++) {    System.out.println(numbers.get(i));}

向G1引入并行FullGC:G1垃圾收集器在jdk9中是默认的。G1垃圾收集器避免了任何完全的垃圾收集,但是当用于收集的并发线程不能足够快地恢复内存时,用户的体验就会受到影响。


此更改通过使完全GC并行来改善G1最坏情况下的延迟。G1收集器的mark-sweep compact算法作为此更改的一部分被并行化,当用于收集的并发线程不能足够快地恢复内存时,它将被触发。


基于Java的实验性 JIT 编译器:Java 10 中开启了基于Java 的JIT编译器Graal,并将其用作Linux/x64平台上的实验性JIT编译器开始进行测试和调试工作。


Graal 是一个以 Java 为主要编程语言、面向Java bytecode 的编译器。与用C++实现的C1及C2相比,它的模块化更加明显,也更加容易维护。将 Graal 编译器研究项目引入到 Java 中,或许能够为 JVM 性能与当前 C++ 所写版本匹敌(或有幸超越)提供基础。


Java 11(LTS)


主要更新内容:


  • GC垃圾回收器
  • 本地变量类型推断
  • 字符串加强
  • 集合加强
  • Stream 加强
  • Optional 加强
  • InputStream 加强
  • HTTP Client API
  • 化繁为简,一个命令编译运行源代码


最大变化是Linux版本新增了ZGC。ZGC在Linux X64下的JDK 11以上可用,Mac和Windows上需要JDK 15可用。Java 11 ZGC实测gc时间稳定在3ms左右(当然也许跟场景有关,官方口径一般在10ms以下)。


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


ZGC  avg: 1.091ms (+/-0.215ms)  95th percentile: 1.380ms  99th percentile: 1.512ms  99.9th percentile: 1.663ms  99.99th percentile: 1.681ms  max: 1.681ms  G1  avg: 156.806ms (+/-71.126ms)  95th percentile: 316.672ms  99th percentile: 428.095ms  99.9th percentile: 543.846ms  99.99th percentile: 543.846ms  max: 543.846ms


同时,不得不提的一点是:随着Java 11的发布,在2018.9之后,Oracle JDK正式商用(开发不收费,但是运行线上业务收费)。但是与此同时,Oracle宣布,OpenJDK与Oracle JDK在功能上不会有区别。并且,OpenJDK 11 RTS将会由红帽社区进行维护。这样,更加增加了可靠性与保证问题的及时解决。

Java 12


主要更新内容:


  • Shenandoah: 低暂停时间的GC
  • Switch表达式
  • JVM常量API
  • 默认类数据共享归档文件
  • 可终止的G1 Mixed GC
  • G1及时返回未使用的已分配内存


Java 12中引入一个新的垃圾收集器:Shenandoah,它是作为一中低停顿时间的垃圾收集器而引入到Java 12中的,其工作原理是通过与Java应用程序中的执行线程同时运行,用以执行其垃圾收集、内存回收任务,通过这种运行方式,给虚拟机带来短暂的停顿时间。


同时,Java12中继续改善了G1 GC:为了实现向操作系统返回最大内存量的目标,G1 将在应用程序不活动期间定期执行或触发并发周期以确定整体 Java 堆使用情况。这将导致它自动将 Java 堆的未使用部分返回给操作系统。而在用户控制下,可以可选地执行完整的 GC,以使返回的内存量最大化。


如果混合 GC 的 G1 存在超出暂停目标的可能性,则使其可中止。


Java 13


主要内容:


  • 增强 ZGC 释放未使用内存
  • Socket API 重构
  • Switch 表达式扩展(预览功能)
  • 文本块(预览功能)

Java 13主要功能就是增强ZGC:释放未使用内存。ZGC在Java 11中是实验性的引入,主要用来改善 GC 停顿时间,并支持几百 MB 至几个 TB 级别大小的堆,并且应用吞吐能力下降不会超过 15%。


通过在实际中的使用,发现 ZGC 收集器中并没有像 Hotspot 中的 G1 和 Shenandoah 垃圾收集器一样,能够主动将未使用的内存释放给操作系统的功能。对于大多数应用程序来说,CPU 和内存都属于有限的紧缺资源,特别是现在使用的云上或者虚拟化环境中。如果应用程序中的内存长期处于空闲状态,并且还不能释放给操作系统,这样会导致其他需要内存的应用无法分配到需要的内存,而这边应用分配的内存还处于空闲状态,处于"忙的太忙,闲的太闲"的非公平状态,并且也容易导致基于虚拟化的环境中,因为这些实际并未使用的资源而多付费的情况。由此可见,将未使用内存释放给系统主内存是一项非常有用且亟需的功能。


Java 13 中对 ZGC 的改进,主要体现在下面几点:


  • 释放未使用内存给操作系统
  • 支持最大堆大小为 16TB
  • 添加参数:-XX:SoftMaxHeapSize 来软限制堆大小


Java 13 中,ZGC 内存释放功能,默认情况下是开启的,不过可以使用参数:-XX:-ZUncommit 显式关闭,同时如果将最小堆大小 (-Xms) 配置为等于最大堆大小 (-Xmx),则将隐式禁用此功能。


还可以使用参数:-XX:ZUncommitDelay = <seconds>(默认值为 300 秒)来配置延迟释放,此延迟时间可以指定释放多长时间之前未使用的内存。


Java 14


主要内容:


  • 改进的switch表达式,第一次出现在Java 12和13中,在Java 14中获得了完全的支持
  • instanceof支持模式匹配(语言特性)
  • record 特性,省去写get,equals()等方法
  • NullPointerException(JVM特性),精确到哪一行
  • 加入了java打包工具jpackage的预览版。


Switch表达式, 可以使用箭头->代替break:


var log = switch (event) {  case PLAY -> "User has triggered the play button";  case STOP, PAUSE -> "User needs a break";  default -> {     "default"  }};


instanceof支持模式匹配(语言特性)


Object obj = "java 14";//测试一把if (obj instanceof String sss && sss.length() > 5) {    System.out.println(sss.contains("b"));    System.out.println("这是字符串!sss" + sss);} else {    System.out.println("其他~");}


同时,扩展ZGC,使得ZGC能够在macOS和 Windows(版本有限制)上使用,主要是兼容这两个系统和 linux 系统底层的内存映射机制的不同带来的差异;


Java 15


主要内容:


  • ZGC将从实验功能升级为产品
  • Char在CharSequence中添加了isEmpty默认方法
  • 支持Unicode 13.0
  • JEP 371 隐藏类
  • TreeMap方法的专用实现
  • 增加了为远程JMX配置第三个端口的能力


Java 15版本,ZGC将从实验功能升级为产品。


ZGC已集成到2018年9月发布的JDK 11中,是一个可扩展的低延迟垃圾回收器。引入ZGC是一项实验功能,因为Java的开发人员决定应谨慎而逐步地引入这种大小和复杂性的功能。从那时起,已经添加了许多改进,从并发类卸载,未使用内存的未提交,对数据类共享的支持到改进的NUMA感知和多线程堆预触。此外,最大堆大小已从4 TB增加到16 TB。支持的平台包括Linux,Windows和MacOS。


同样的,还有Shenandoah GC。


Java 16


主要内容:


  • Record正式使用
  • jpackage 的工具正式使用
  • instanceof正式使用


哈哈,这个版本确实没什么太多更新,网上有一个笑话如下:


美国的一个大公司发通知,说公司上周决定要不预装JRE,因为工厂抱怨装了JRE之后,系统启动的时间增加了,即使是1-2分钟,工厂也决定不接受JRE.于是Sun就急了,为我们定制了一版update 16,主要更新就是在安装参数增加了一个命令(好像是noupdate)....


Java 17(LTS)


主要内容:


  • 增强了伪随机数算法。
  • 移除AOT提前编译和JIT即时编译的功能,Oracle JDK16 未包含此功能。
  • sealed修饰的类和接口限制其他的类或者接口的扩展和实现。说白了就是限制类的继承或者接口的实现数量。
  • 进一步增强了switch语法的模式匹配,万物皆可switch下使用了。


这个版本更新的内容也不多,不过也是个长期支持版本。同时,Oracle JDK宣布可以免费商用了。外加我们文章开头提到的,Spring framework 6 和Spring Boot 3 都将基于Java 17。所以,这个版本对开发者来说还是比较重要的。


好了,终于把Java 9~Java 17的主要更新都整理完了。强哥的整理有部分版本的内容也做了选择性的忽略。主要还是为了突出重点。想要更深入地了解各个版本的具体更新内容,大家也可以到JDK官网查看。


就到这啦~

相关文章
|
6月前
|
Java API
java.se和java.base的关系(java 17)
java.se和java.base的关系(java 17)
|
6月前
|
存储 SQL 算法
八个理由:从java8升级到Java17
八个理由:从java8升级到Java17
254 0
|
算法 搜索推荐 Java
Java8 到 Java17 升级指南(Bug大全)
Java8 到 Java17 升级指南(Bug大全)
534 0
|
1月前
|
编解码 Oracle Java
java9到java17的新特性学习--github新项目
本文宣布了一个名为"JavaLearnNote"的新GitHub项目,该项目旨在帮助Java开发者深入理解和掌握从Java 9到Java 17的每个版本的关键新特性,并通过实战演示、社区支持和持续更新来促进学习。
79 3
|
27天前
|
Java 大数据 API
别死脑筋,赶紧学起来!Java之Steam() API 常用方法使用,让开发简单起来!
分享Java Stream API的常用方法,让开发更简单。涵盖filter、map、sorted等操作,提高代码效率与可读性。关注公众号,了解更多技术内容。
|
1月前
|
Java 编译器 API
从Java 8到Java 17,这些新特性让你的代码起飞!
【10月更文挑战第10天】在软件开发领域,Java作为一种历史悠久且广泛使用的编程语言,不断进化以适应新的需求和挑战。从Java 8到Java 17,每一次版本更新都带来了诸多新特性和改进,极大地提升了开发效率和代码质量。今天,我们就来一起探讨这些新特性,看看它们是如何让我们的代码“起飞”的。
131 0
|
4月前
|
Oracle Java API
Java演进问题之Java 9模块化的改造成本大如何解决
Java演进问题之Java 9模块化的改造成本大如何解决
|
4月前
|
Rust Cloud Native Java
Java演进问题之Java 9的模块化潜在的陷阱如何解决
Java演进问题之Java 9的模块化潜在的陷阱如何解决
|
5月前
|
缓存 Java
java: 警告: 源发行版 17 需要目标发行版 17,java17 无效的目标发行
java: 警告: 源发行版 17 需要目标发行版 17,java17 无效的目标发行
3590 3
|
5月前
|
存储 缓存 算法
ConcurrentHashMap的演进:从Java 8之前到Java 17的实现原理深度剖析
ConcurrentHashMap的演进:从Java 8之前到Java 17的实现原理深度剖析