JDK9新特性(二)

在上一篇的文章我记述了JDK9的两个最重要的特性:一个是模块化,一个是jShell。另外就是String底层存储结构和StreamAPI的一些改动与优化。本次要记述主要的特性是全新的多分辨率图像API、全新的HTTP客户端API(其实是借鉴OkHTTP的框架,或者说是整合吧)、Deprecated相关API、智能Java编译工具与动态编译器、统一的JVM日志系统、javadoc对H5的支持、JavaScript引擎升级:Nashorn。然后再谈谈JDK9还需要什么吧,也就是对未来Java的展望。

多分辨率图像API

在Mac上,JDK已经支持视网膜显示,但在Linux和Windows上,并没有支持。Java程序在当前的高分辨率屏幕上可能看起来很小,不能使用它们。这是因为像素用于这些系统的大小计算(无论像素实际有多大)。毕竟,高分辨率显示器的有效部分是像素非常小。

JEP 263以这样的方式扩展了JDK,即Windows和Linux也考虑到像素的大小。为此,使用比现在更多的现代API:Direct2D for Windows和GTK+,而不是Xlib for Linux。图形,窗口和文本由此自动缩放。JEP 251还提供处理多分辨率图像的能力,即包含不同分辨率的相同图像的文件。根据屏幕的DPI度量,然后以适当的分辨率使用图像。

  • 新的API定义在java.awt.image包下
  • 将不同分辨率的图像封装到一张(多分辨率的)图像中,作为它的变体
  • 获取这个图像的所有变体
  • 获取特定分辨率的图像变体-表示一张已知分辨率单位为DPI的特定尺寸大小的逻辑图像,并且这张图像是最佳的变体。
  • 基于当前屏幕分辨率大小和运用的图像转换算法,java.awt.Graphics类可以从接口MultiResolutionImage获取所需的变体。
  • MultiResolutionImage的基础实现是java.awt.image.BaseMultiResolutionImage。

全新的HTTP客户端

http://openjdk.java.net/jeps/110 ,这个是改动说明文档。2015年,HTTP2成为标准。HTTP/1.1和HTTP/2的主要区别是如何在客户端和服务器之间构建和传输数据。HTTP/1.1依赖于请求/响应周期。 HTTP/2允许服务器push数据:它可以发送比客户端请求更多的数据。 这使得它可以优先处理并发送对于首先加载网页至关重要的数据。

Java 9中有新的方式来处理HTTP调用。它提供了一个新的HTTP客户端(HttpClient),它将替代仅适用于阻塞模式的HttpURLConnection (HttpURLConnection是在HTTP 1.0的时代创建的,并使用了协议无关的方法),并提供对WebSocket 和 HTTP/2的支持。

其实在Android中就已经有了异步调用API,这些API已经被封装在了新的AndroidSDK中,现在Java终于支持了。此外,HTTP客户端还提供API来处理HTTP/2的特性,比如流和服务器推送等功能。全新的HTTP客户端API可以从jdk.incubator.httpclient模块中获取。因为在默认情况下,这个模块是不能根据classpath获取的,需要使用add modules命令选项配置这个模块,将这个模块添加到classpath中。

 1public class HTTPAPITest {
 2    public static void main(String[] args) throws IOException, InterruptedException {
 3        HttpClient client = HttpClient.newHttpClient();
 4        HttpRequest req = HttpRequest.newBuilder(URI.create("http://zouchanglin.cn"))
 5                .GET()
 6                .build();
 7        HttpResponse<String> response = client.send(req, HttpResponse.BodyHandler.asString());
 8        System.out.println(response.statusCode());
 9        System.out.println(response.version().name());
10        System.out.println(response.body());
11    }
12}

Deprecated的相关API

Java 9 废弃或者移除了几个不常用的功能。其中最主要的是 Applet API,现在是标记为废弃的。随着对安全要求的提高,主流浏览器已经取消对 Java 浏览器插件的支持。HTML5 的出现也进一步加速了它的消亡。开发者现在可以使用像 Java Web Start 这样的技术来代替 Applet,它可以实现从浏览器启动应用程序或者安装应用程序。同时,appletviewer 工具也被标记为废弃。

智能Java编译工具

官方Feature:http://openjdk.java.net/jeps/199

智能Java编译工具(sjavac) 的第一个阶段始于JEP139这个项目,用于在多核处理器情况下提升JDK的编译速度。如今,这个项目已经进入第二阶段,即JEP199,其目的是改进Java编译工具,并取代目前JDK编译工具javac,继而成为Java环境默认的通用的智能编译工具。 JDK 9 还更新了javac 编译器以便能够将Java9的代码编译运行在低版本 Java 中。

统一的JVM日志系统

官方Feature:

日志是解决问题的唯一有效途径:曾经很难知道导致JVM性能问题和导致JVM崩溃的根本原因。不同的JVM日志的碎片化和日志选项(例如:JVM组件对于日志使用的是不同的机制和规则),这使得JVM难以进行调试。

解决该问题最佳方法:对所有的JVM组件引入一个单一的系统,这些JVM组件支持细粒度的和易配置的JVM日志

javadoc的H5支持

官方Feature:

jdk 8 :生成的java帮助文档是在HTML4 中,而HTML4 已经是很久的标准了。 jdk 9 :javadoc的输出,现在符合兼容HTML5 标准。

Javascript引擎升级:Nashorn

官方Feature:

Nashorn 项目在 JDK 9 中得到改进(因为Nashorn是在JDK8中被引入的),它为 Java 提供轻量级的 Javascript 运行时。Nashorn 项目跟随 Netscape 的 Rhino 项目,目的是为了在 Java 中实现一个高性能但轻量级的Javascript 运行时。Nashorn 项目使得 Java 应用能够嵌入 Javascript。它在 JDK 8 中为 Java 提供一个Javascript 引擎。

JDK 9 包含一个用来解析 Nashorn 的 ECMAScript 语法树的 API。这个 API 使得 IDE 和服务端框架不需要依赖 Nashorn 项目的内部实现类,就能够分析 ECMAScript 代码。

java的动态编译器

官方Feature:

Oracle 一直在努力提高 Java 启动和运行时性能,希望其能够在更广泛的场景达到或接近本地语言的性能。但是,直到今天,谈到 Java,很多 C/C++ 开发者还是会不屑地评价为启动慢,吃内存。简单说,这主要是因为 Java 编译产生的类文件是 Java 虚拟机可以理解的二进制代码,而不是真正的可执行的本地代码,需要 Java 虚拟机进行解释和编译,这带来了额外的开销。

JIT(Just-in-time)编译器可以在运行时将热点编译成本地代码,速度很快。但是 Java 项目现在变得很大很复杂,因此 JIT 编译器需要花费较长时间才能热身完,而且有些 Java 方法还没法编译,性能方面也会下降。AOT 编译就是为了解决这些问题而生的。 在 JDK 9 中, AOT(JEP 295: Ahead-of-Time Compilation)作为实验特性被引入进来,开发者可以利用新的 jaotc工具将重点代码转换成类似类库一样的文件。虽然仍处于试验阶段,但这个功能使得 Java 应用在被虚拟机启动之前能够先将 Java 类编译为原生代码。此功能旨在改进小型和大型应用程序的启动时间,同时对峰值性能的影响很小。这个AOT特性我在之前的文章中也说过: 《 HotSpot JVM类型以及编译模式 》

另外 JVMCI (JEP 243: Java-Level JVM Compiler Interface)等特性,对于整个编程语言的发展,可能都具有非常重要的意义,虽然未必引起了广泛关注。目前 Graal Core API 已经被集成进入 Java 9,虽然还只是初始一小步,但是完全用 Java 语言来实现的可靠的、高性能的动态编译器,似乎不再是遥不可及,这是 Java 虚拟机开发工程师的福音。与此同时,随着 Truffle 框架和 Substrate VM 的发展,已经让个别信心满满的工程师高呼One VM to Rule Them All!, 也许就在不远的将来 Ploygot 以一种另类的方式成为现实。

对Java未来的期望

标准化的JSON API

一个标准化和轻量级的JSON API被许多java开发人员所青睐。但是由于资金问题无法在Java 9中见到,但并不会削减掉。Java平台首席架构师Mark Reinhold在JDK 9邮件列中说:“这个JEP将是平台上的一个有用的补充,但是在计划中,它并不像Oracle资助的其他功能那么重要,可能会重新考虑JDK 10或更高版本中实现。 ” 但是我们目前使用的仍然是阿里的FastJSON或者谷歌的Gson等API。

新的货币 API

对许多应用而言货币价值都是一个关键的特性,但JDK对此却几乎没有任何支持。严格来讲,现有的java.util.Currency类只是代表了当前ISO 4217货币的一个数据结构,但并没有关联的值或者自定义货币。JDK对货币的运算及转换也没有内建的支持,更别说有一个能够代表货币值的标准类型了。

此前,Oracle 公布的JSR 354定义了一套新的Java货币API:JavaMoney,计划会在Java 9中正式引入。但是目前没有出现在JDK 9 中。

不过,如果你用的是Maven的话,可以做如下的添加,即可使用相关的API处理货币。代码参考,可以访问https://github.com/JavaMoney,里面已经给出了使用说明和示例。

1<dependency>
2	<groupId>org.javamoney</groupId>
3	<artifactId>moneta</artifactId>
4	<version>0.9</version>
5</dependency>

面临的其他问题

随着云计算和 AI 等技术浪潮,当前的计算模式和场景正在发生翻天覆地的变化,不仅对 Java 的发展速度提出了更高要求,也深刻影响着 Java 技术的发展方向。传统的大型企业或互联网应用,正在被云端、容器化应用、模块化的微服务甚至是函数(FaaS, Function-as-a-Service)所替代。

Java虽然标榜面向对象编程,却毫不顾忌的加入面向接口编程思想,又扯出匿名对象之概念,每增加一个新的东西,对Java的根本所在的面向对象思想的一次冲击。反观Python,抓住面向对象的本质,又能在函数编程思想方面游刃有余。Java对标C/C++,以抛掉内存管理为卖点,却又陷入了JVM优化的噩梦。选择比努力更重要,选择Java的人更需要对它有更清晰的认识。

Java 需要在新的计算场景下,改进开发效率。这话说的有点笼统,我谈一些自己的体会,Java 代码虽然进行了一些类型推断等改进,更易用的集合 API 等,但仍然给开发者留下了过于刻板、形式主义的印象,这是一个长期的改进方向,但是不得不说Java确实还是越变越优秀了。