`

Java9新功能之HTTP2和REPL

阅读更多

对Java 9的炒作将不再局限于模块化(modularity),Java 9正在搜罗大量额外的功能模块,这些功能模块正作为Java增强提案(JEP)提交,并在OpenJDK (Java SE的参考实现项目)中实现。

在这篇文章中,我们将重点关注一些或将在Java 9整个生命周期中,对开发者的工作生活影响最大的JEP,包括新的HTTP/2支持和JShell REPL(读取-求值-打印-循环),后者带来了基于shell的交互式Java开发环境和探索性开发API。

HTTP/2

HTTP/2标准是HTTP协议的最新版本。当前版本HTTP/1.1始于1999年,存在着非常严重的问题,包括:

对头阻塞

在HTTP/1.1中,响应接收的顺序和请求发送的顺序相同。这意味着,例如,当查看一个包含许多小图像的大HTML页面时,图像资源将不得不在HTML页面资源之后排队,在浏览器完全加载完HTML页面之前,图像资源无法被发送。这就是“对头阻塞”,会导致许多潜在的页面渲染问题。

在HTTP/2中,响应数据可以按块(chunk)传输,甚至可以交叉传输,因此真正实现了请求和响应的多路复用。

一个站点的连接数限制

在HTTP/1.1标准中有这样的描述:“一个单用户的客户端不能与任何服务器保持2个以上的连接”。这个限制和对头阻塞问题一起,严重限制了页面的性能。

HTTP/2打破这种限制并认为连接是持久的,只有当用户跳转后或者发生技术性故障事件时,连接才会关闭。对多路复用的使用将有助于降低页面性能瓶颈。

HTTP控制头的开销

当前的HTTP版本使用简单的、基于文本的HTTP头信息来控制通信。这样做的优点是非常简单且易于理解,调试也很简单,只需通过连接指定端口并输入一些文本。然而,使用基于文本的协议会让小的响应包不成比例地膨胀。此外,大量的HTTP响应几乎没有或者根本没有有效负载(比如,HEAD请求只是要确定资源是否发生变化)。为实际上只包含最后修改时间的响应,使用完全基于文本的头信息(大约有700个字节,在HTTP1.1中,它们不能被压缩,尽管很容易做到)是当前HTTP标准中,不可思议的浪费。

另一个思路是对HTTP头信息使用二进制编码。这种方式能够极大地提高较小请求的速度且占用的网络带宽非常小。这正是HTTP/2已经选择的方法,虽然以协议精神制定标准应该选择基于文本的协议,但是二进制的效率有令人信服的理由,让我们这样做。

HTTP/2带来的期望

HTTP/2标准是由IETF HTTP工作组创建的,该组织由来自Mozilla、Google、 Microsoft、Apple,以及其他公司的代表和工程师组成,由来自CDN领军公司Akamai的高级工程师Mark Nottingham任主    席。因此,HTTP/2是一个为优化大型、高流量的网站而生的版本,它在实现简单、易于调试的基础上,确保了性能和网络带宽消耗。

该组织主     席总结了一些HTTP/2的关键属性:

  • 相同的HTTP API
  • 成本更低的请求
  • 网络和服务器端友好
  • 缓存推送
  • 思维革命
  • 更多加密方式

带给Java的意义

自从1.0版本开始,Java就支持HTTP,但是多数代码出自完全不同的时代。例如,Java对HTTP的支持是围绕相对协议无关的框架(URL类)设计的,因此在网站成为主导地位的90年代,这种实现显得很不清晰。

Java对HTTP的支持是基于当时最好的设计思想,但是时过境迁,最重要的是Java对HTTP原始的支持出来时,HTTPS还没有出现。因此,Java的API将HTTPS作为一种移花接木,导致了不能简化的复杂性。

在现代社会,HTTPS开始变得无所不在,让HTTP日渐成为落后的技术。甚至,美国政府现在都通过了完全迁到HTTPS-only的计划。

JDK内核对HTTP的支持已经无法跟上现实网络的发展步伐。实际上,甚至JDK8也只不过是交付了一个支持HTTP/1.0的客户端,然而,大多数的开发者早已转而使用第三方客户端库了,比如Apache的HttpComponents。

所有这一切意味着,对HTTP/2的支持将是Java未来十年的核心功能。这也让我们重新审视我们的固有思维,重新写一套API并提供重新来过的机会。HTTP/2将是未来数年内,每位开发者主要面对的API。

新的API不再坚持协议中立性,使开发者可以完全抛弃过去的使用方式。这套API只关注HTTP协议,但是要进一步理解的是HTTP/2并没有从根本上改变原有的语义。因此,这套API是HTTP协议独立的,同时提供了对新协议中帧和连接处理的支持。

在新的API中,一个简单的HTTP请求,可以这样创建和处理:

    HttpResponse response = HttpRequest
        .create(new URI("http://www.infoq.com"))
        .body(noBody())
        .GET().send();
    int responseCode = response.responseCode();
    String responseBody = response.body(asString());
         
    System.out.println(responseBody);

这种符合流畅风格/建造者模式(fluent/builder)的API,与现存的遗留系统相比,对开发者来说,更具现代感和舒适感。

虽然当前的代码库只支持HTTP/1.1,但是已经包含了新的API。这使得在对HTTP/2支持完成对过程中,开发者可以实验性地使用和验证新的API。

相关代码已经进入OpenJDK沙箱仓库中,并很快登陆JDK 9的主干。到那个时候,新的API将开始自动构建到Oracle的二进制beta版本中。现在,对HTTP/2的支持已经可用,并将在未来数月内最终完成。

在此期间,你可以使用Mercurial迁出源代码,并根据AdoptOpenJDK构建指导编译你迁出地代码,这样你就可以实验性地使用新的API了。

第一批完成的功能之一是当前版本力不能及的异步API。这个功能让长期运行的请求,可以通过sendAsync()方法,切换到VM管理的后台线程中:

    HttpRequest req = HttpRequest
        .create(new URI("http://www.infoq.com"))
        .body(noBody())
        .GET();
    CompletableFuture<HttpResponse> aResp = req.sendAsync();
    Thread.sleep(10);
    if (!aResp.isDone()) {
        aResp.cancel(true);
        System.out.println("Failed to reply quickly...");
        return;
    }
    HttpResponse response = aResp.get();

相比HTTP/1.1的实现,新的API带给开发者最多的是方便性,因为HTTP/1.1没有提供对已经发送到服务器端的请求的取消机制,而HTTP/2可以让客户端向已经被服务器端处理的请求,发送取消命令。

JShell

很多语言都为探索性开发提供了交互式环境。在某些情况下(特别是Clojure和其他Lisp方言),交互式环境占据了开发者的大部分编码时间,甚至是全部。其他语言,比如Scala或者JRuby也广泛使用REPL。

当然,此前Java曾经推出过Beanshell脚本语言,但是它没有实现完全标准化,而且近年来,该项目已经处于不活跃状态。在Java 8(以及jjs REPL)中引入的Nashorn Javascript实现打开了更广泛地考虑REPL并将交互式开发成为可能的大门。

一项努力将现代REPL引入Java 9的工作,以JEP 222作为开始,收录在OpenJDK的Kulla项目中。Kulla这个名字来自古巴比伦神话,是建造之神。该项目的主旨是提供最近距离的“完整Java”体验。该项目没有引入新的非Java语义,并禁用了Java语言中对交互式开发没有用处的语义(比如上层的访问控制修改或同步的语义)。

与所有REPL一样,JShell提供了命令行,而不是类似IDE的体验。语句和表达式能够在执行状态上下文中,被立即求值,而不是非得打包到类中。方法也是自由浮动的,而不必属于某个特定的类。相反,JShell使用代码片断“snippets”来提供上层执行环境。

与HTTP/2 API相似,JShell已经在独立的项目开发,以免在快速发展的时期影响主干构建的稳定性。JShell预计在2015年8月期间合并到主干。

现在,开发者可以参考AdoptOpenJDK说明指导,从头构建Kulla(源代码可以从Mercurial地址获得)。

对于一些上手实验,最简单的可能是使用一个独立的试验jar。这些jar包是社区专为不想从头构建的开发者构建好的。

这些试验jar包可以从AdoptOpenJDK CloudBees的CI构建实例中获得。

要使用它们,你需要安装Java 9 beta版(或者OpenJDK 9的构建版本)。然后下载jar文件,重命名为kulla.jar,然后在命令行输入如下:

$ java -jar kulla.jar
|  Welcome to JShell -- Version 0.610
|  Type /help for help

->

这是REPL的标准界面,和往常一样,命令是从单个字符开始并最终发出的。

JShell有一个相当完整(但仍在发展)的帮助语法,可以通过如下命令轻松获得:

-> /help
Type a Java language expression, statement, or declaration.
Or type one of the following commands:

/l  or /list [all]                -- list the source you have typed
       /seteditor <executable>    -- set the external editor command to use
/e  or /edit <name or id>         -- edit a source entry referenced by name or id
/d  or /drop <name or id>         -- delete a source entry referenced by name or id
/s  or /save [all|history] <file> -- save the source you have typed
/o  or /open <file>               -- open a file as source input
/v  or /vars                      -- list the declared variables and their values
/m  or /methods                   -- list the declared methods and their signatures
/c  or /classes                   -- list the declared classes
/x  or /exit                      -- exit the REPL
/r  or /reset                     -- reset everything in the REPL
/f  or /feedback <level>          -- feedback information: off, 
concise, normal, verbose, default, or ?
/p  or /prompt                    -- toggle display of a prompt
/cp or /classpath <path>          -- add a path to the classpath
/h  or /history                   -- history of what you have typed
       /setstart <file>           -- read file and set as the new start-up definitions
       /savestart <file>          -- save the default start-up definitions to the file
/?  or /help                      -- this help message
       /!                         -- re-run last snippet
       /<n>                       -- re-run n-th snippet
       /-<n>                      -- re-run n-th previous snippet

Supported shortcuts include:
       -- show possible completions for the current text
Shift- -- for current method or constructor invocation, 
show a synopsis of the method/constructor

JShell支持TAB键自动补全, 因此我们可以很容易找到println()或者其他我们想使用的方法:

-> System.out.print
print(     printf(    println(

传统的表达式求值也很容易,但是相比其他动态类型语言,Java的静态类型特征会更严格一点。JShell会自动创建临时变量来保存表达式的值,并确保它们保持在上下文域内供以后使用:

-> 3 * (4 + 5)
|  Expression value is: 27
|    assigned to temporary variable $1 of type int

-> System.out.println($1);
27

我们还可以使用/list命令,查看到目前为止输入的所有源代码:

-> /list

   9 : 3 * (4 + 5)
  10 : System.out.println($1);

使用/vars命令显示所有的变量(包括显式定义的和临时的),以及他们当前持有的值:

-> String s = "Dydh da"
|  Added variable s of type String with initial value "Dydh da"

-> /vars
|    int $1 = 27
|    String s = "Dydh da"

除了支持简单的代码行,REPL还允许非常简单地创建类和其它用户定义的类型。例如,可以用如下短短一行来创建类(请注意,开始和结束括号是必需的):

-> class Pet {}
|  Added class Pet

-> class Cat extends Pet {}
|  Added class Cat

JShell代码非常简洁、自由浮动的性质意味着我们可以非常简单地使用REPL来演示Java语言的功能。例如,让我们来看看著名的类型问题,即Java数组的协变问题:

-> Pet[] pets = new Pet[1]
|  Added variable pets of type Pet[] with initial value [LPet;@2be94b0f

-> Cat[] cats = new Cat[1]
|  Added variable cats of type Cat[] with initial value [LCat;@3ac42916

-> pets = cats
|  Variable pets has been assigned the value [LCat;@3ac42916

-> pets[0] = new Pet()
|  java.lang.ArrayStoreException thrown: REPL.$REPL13$Pet
|        at (#20:1)

这样的功能使JShell成为一种伟大的教学或研究工具,而且最接近Scala REPL的体验。使用/classpath切换,可以加载额外的jar包,从而可以在REPL直接使用互动式探索性API。

参与

主要的IDE已开始提供支持JDK 9早期版本的构建——包括Netbeans和Eclipse Mars。IntelliJ 14.1据称支持JDK9,但目前还不清楚对新的模块化JDK扩展的支持力度。

到目前为止,这些IDE还不支持HTTP/2和JShell,因为这些功能还没有登陆OpenJDK的主干,但是开发者应该很期望它们能够早日出现在标准的JDK beta版本中,并且有IDE插件可以紧随其后。这些API仍在开发中,项目的领导者正在积极寻求最终用户的使用和参与。

The JDK 9 Outreach programme is also underway to encourage developers to test their code and applications on JDK 9 before it arrives. HTTP/2 & JShell aren’t the only new features being worked on – other new JDK 9 functionality under development as JEPs includes

JDK 9的宣传计划也正在鼓励开发者测试他们的代码并在JDK 9上运行应用程序。正在开发的新功能不止包括HTTP/2和JShell—— 其他作为JEP,JDK 9正在开发的新功能还包括:

  • 102 Process API的更新(Process API Updates)
  • 165 编译器控制(Compiler Control)
  • 227 Unicode 7.0
  • 245 验证虚拟机代码行标记参数(Validate JVM Command-Line Flag Arguments)
  • 248: G1作为默认的垃圾回收器(Make G1 the Default Garbage Collector)
  • TLS的一系列更新(TLS Updates) (JEP 219, 244, 249)
分享到:
评论

相关推荐

    JavaREPL是一个Java语言读入-求值-打印-循环(Read-Eval-Print-Loop)功能实现

    JavaREPL,全称为Java Read-Eval-Print Loop,是Java开发者的一种实用工具,它允许程序员在交互式环境中测试代码片段、快速实验新概念或调试程序。REPL是许多编程语言的标准特性,如Python和Lisp,而在Java世界中,...

    java9新特性

    在理解了上述知识后,我们能够认识到Java 9是Java语言进化过程中的一个关键里程碑,它不仅仅是一个新版本的简单迭代,更是一个承载了深远意义的更新,它代表了Java平台在现代编程语言竞争中的持续适应和创新。

    某硅谷java9新特性源码

    Java 9是Java平台的重大更新,它引入了许多新特性,旨在提高开发人员的生产力和系统的性能。...每个文件(如4_代码)可能代表一个特定特性的示例,通过阅读和运行这些代码,你将更好地掌握Java 9的新功能。

    core java 9-核心JAVA 9 卷1卷2 中文版

    总而言之,《核心JAVA 9 卷1卷2 中文版》这本书涵盖了Java 9的模块化系统、JShell、新的API、HTTP客户端、内存管理和JVM改进等多个关键知识点,是深入理解和应用Java 9不可多得的资源。通过阅读和实践书中的内容,...

    Java9 API 下载

    1. **模块系统(Project Jigsaw)**:Java 9 的核心改进之一是引入了模块系统,它使得大型应用程序的构建、打包和运行更加可控和高效。模块化有助于提高代码的隔离性和可维护性,减少依赖冲突,并改善JVM启动时间。 ...

    2019最新 java9新特性课程讲解.rar

    4. **HTTP客户端API(JEP 110)**:Java 9提供了一个新的内置HTTP客户端API,使得开发者可以更方便地进行HTTP通信,支持HTTP/1.1和HTTP/2协议。 5. **进程API增强(JEP 208)**:Java 9对`java.lang.Process`及其...

    Java 9 Programming By Example

    2. **JShell(REPL)**:Java 9引入了一个交互式的命令行工具JShell,即Read-Eval-Print Loop,允许开发者即时测试和调试代码片段,极大地提升了开发效率。了解如何使用JShell进行快速原型开发和测试,是理解Java 9...

    java-repl,Java的EVE打印循环.zip

    虽然这个项目已被声明为"未维护",这表明它可能不再接收新的更新或功能增强,但作为一个开源项目,它的源代码仍然可供社区学习和参考。对于那些想要了解如何构建自己的Java REPL或者对已有的REPL实现感兴趣的开发者...

    Java.9.Cookbook

    这本书深入浅出地介绍了Java 9的新特性和改进,旨在帮助开发者更好地理解和利用这个版本的强大功能。以下是对该书内容的一些关键知识点的概述: 1. **模块系统**:Java 9引入了全新的模块系统(Project Jigsaw),...

    java-jdk9-jdk-9.0.1-windows-x64-bin.zip

    Java JDK 9是Java开发工具包的一个重要版本,专为Windows...总的来说,这个压缩包为Windows x64用户提供了一个便捷的方式来获取和安装Java 9开发环境,使他们能够利用Java 9的新功能和改进来开发高质量的Java应用程序。

    JDK9,Java9

    7. **接口私有方法和默认方法**:Java 9允许在接口中定义私有方法,增强了接口的功能。 8. **Process API的改进**:提供了更多的控制选项,如控制子进程的输出流,使得进程管理更加强大。 9. **改进的Javadoc**:...

    Java 9 - 在线API中文手册中文版 - 函数查询助手

    对于Android开发者来说,虽然Java 9的一些特性可能不直接适用于Android平台,但了解这些新功能可以帮助他们提升个人技能,更好地利用Java生态系统中的资源。同时,这个中文版的手册降低了语言障碍,使国内开发者能更...

    Packt.Java9.with.JShell

    《Java 9 with JShell》是一本专注于Java 9新特性和JShell工具的专业书籍。Java 9作为Java平台的一个重大版本更新,引入了一系列增强功能和改进,旨在提高开发效率和程序性能。JShell,也被称为Java REPL(Read-Eval...

    java9开发文档中文版.rar

    Java 9 开发文档中文版是为Java开发者提供的详尽指南,主要涵盖了Java平台标准版(Java SE)9的新特性和改进。这个压缩包包含了一个名为"java9.chm"的文件,它是一个Windows帮助文件格式,通常用于存放文档和教程。...

    java9 sdk api specification docs API参考文档 英文版 HTML格式

    这个英文版的HTML格式文档包含了全面的API(应用程序编程接口)指南,帮助程序员理解和使用Java 9的新功能,提升开发效率。下面我们将深入探讨其中的关键知识点。 1. 模块系统 (Module System): Java 9引入了模块化...

    java jdk9 windows x64免安装版(openjdk9.0.4)

    总的来说,Java JDK 9的Windows 64位免安装版提供了一种便捷的方式来体验和利用这个版本的新特性,只需解压缩并配置环境变量,开发者就能在自己的系统上轻松使用JDK 9的功能。为了确保能正常使用Java开发工具,别忘...

    mastering java 9

    其次,Java 9带来了增强的JShell(也称为REPL,Read-Eval-Print Loop),这是一种交互式环境,允许开发者即时测试和调试代码片段,极大地提高了开发效率。书中会教授如何利用JShell进行快速原型设计和学习新的API。 ...

    corejava9_java_whistlezfu_zip_

    通过深入研究这些源码,开发者不仅可以加深对Java 9新特性的理解,还能学习到如何在实际项目中有效应用这些新功能,提升编程技能。这些代码示例对于初学者和经验丰富的开发者都是宝贵的参考资料。

    Java 9 api 中文版 JDK9 中文版

    在JDK9中,Java平台经历了重大更新,引入了一系列新功能和改进,以提升性能、安全性和可维护性。以下是一些关键的API和特性: 1. **模块系统(Module System)**:Java 9引入了Jigsaw项目,实现了模块化设计。模块...

Global site tag (gtag.js) - Google Analytics