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 工具也被标记为废弃。
- http://openjdk.java.net/jeps/211
- http://openjdk.java.net/jeps/214
- http://openjdk.java.net/jeps/277
- http://openjdk.java.net/jeps/289
- http://openjdk.java.net/jeps/291
智能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确实还是越变越优秀了。