从 1995 年第一个版本诞生到现在,Java 已经走过了 20 多个年头。本文主要从 JavaSE 开源现状、OpenJDK 版本生态到 OpenJDK 技术趋势三个方面讲述当前基础 Java 技术的发展,进一步讨论在云原生、AI、多语言生态领域支撑 Java 应用的基石——Java Virtual Machine (JVM) 技术,面向未来的演进趋势。
背景
1991 年,James Gosling 带领团队开始了一个叫 "Oak" 的项目,这个就是 Java 的前身。1995 年,Java1.0 发布。“Write once, run anywhere" 这句 Java 口号想必大家耳熟能详。Java 刚开始出现的时候主要面向 Interactive Television 领域,直至后来几年的发展,当时的 SUN(后来在 2010 年被 Oracle 收购)一度想用 Java 来打造桌面的网络操作系统,取代当时如日中天的 Windows。不过 Java 后来的发展,不曾想虽未在桌面领域内取得多大的建树,出乎意料地,却在企业级应用领域开花结果,占据了如今几乎统治的地位。失之東隅,却收之桑榆。
JavaSE 开源现状
Sun 在 2006 年的 Java One 大会上,宣布 Java 技术开源,随后 2006 年底在 GPL 协议下发布 HotSpot 以及 javac,这是 Java 发展中的里程碑事件。阿里巴巴最早在 2012 签署 OCA,并参与到了 OpenJDK 的开发。
OpenJDK 是 JavaSE 开源的 Reference Implementation。在 JavaOne 2017 的 Keynote 上 (2018 年 JavaOne 被 Oracle 重命名为 CodeOne),Oracle 承诺将开源所有的 OracleJDK 里包含的商业实现功能 [1]。
在 2018 年发布的 Java11, Oracle 已经让 OpenJDK 和 Oracle JDK 两者的二进制文件在功能上尽可能相互接近,尽管 OpenJDK 与 OracleJDK 两者在一些选项之间仍然存在一些差异 [2]。
另外,除了 OpenJDK 这条主线,在最近的几年里,Java 基础技术的开源有愈演愈烈趋势:2017 年,IBM 将内部使用 20 多年之久的 J9 虚拟机开源,并贡献到 Eclipse Foundation, 而随后 2018 年,Oracle 开源 GraalVM 1.0,其核心包含用 Java 写的 Just-in-Time compiler/Graal, SubstrateVM 以及支持多语言解释器的 Truffle 框架。各个企业开源的主要动机,想通过开源构建并受益于一个更为强大的语言生态系统。
云 + 开源结合在一起,使得普通开发者以较低的门槛获得一流工具 (链) 的使用和体验,任何一家企业都可以像任何大型组织一样,使用的相同技术 (democratizing),这是开发者的黄金时代。
Java is Still Free: 你该选择什么样的 JDK?
Java 仍然免费,但随着 OracleJDK License 变化开始转向收费,OpenJDK 会逐渐取代 OracleJDK 成为市场主流,这点也可以从 JVM 2020 生态报告中看出趋势:OracleJDK 从前一年的 70% 的开发者选择使用率降到 2020 年的 34%。
OracleJDK 收费,在客观上也加剧了 OpenJDK 生态的碎片化趋势,出现了包括 Alibaba Dragonwell 在内的多个基于 OpenJDK 的可选实现。
企业在选择使用那个 Java Vendor 的 JDK 版本时,几个方面的考虑因素可以参考:
安全与稳定:是否会及时同步上游的最新更新,包括安全补丁,关键的问题修复等。
JavaSE 标准兼容 :是否与标准 Java 兼容。
性能与效率:是否可以在问题诊断,性能调优方面提供有效的工具支持,帮助一线的开发同学高效地解决 Java 问题。在 JVM,到 JDK (Class library) 层面,是否有面向企业业务场景的优化特性,可以帮助提升资源的利用率,生产系统的稳定性等等。
快速的新技术采纳:伴随收费,Oracle 管理 Java 版本生命周期采用了 Long Term Support(LTS) 的概念,Oracle 每三年会指定一个 LTS 的 Java 版本, Java 8/11 都是 LTS 版本。大部分企业,尤其是大中型企业很难跟上 Java 每六个月一发布的节奏,像 Java 12,13 这样的 Feature Release(FR) 版本。那么问题来了,如果你选择 Stay 在 LTS 版本上,比如 Java 11,在新版本 (Java11+) 发布的 JVM/JDK 技术,是否可以在不升级的情况下,提前享受这些技术红利?
这里分享下 Alibaba Dragonwell 在这些方面的计划与思考。
Alibaba Dragonwell 是阿里巴巴内部广泛使用的 AJDK (AlibabaJDK) 的开源版本,Alibaba Dragonwell 作为基石,支撑了阿里经济体内几乎所有的 Java 业务,经过了双 11 等大促的考验。Alibaba Dragonwell 主要针对的场景是数据中心大规模 Java 应用部署情况下,Java 应用稳定性、效率以及性能的优化与提高。
2019 年 3 月阿里开源 Alibaba Dragonwll 8.0.0,我们也一直正在践行开源时候的承诺,AJDK 内部使用的特性在逐步开源。到刚刚发布 Alibaba Dragonwell 8.3.3,我们已经开源了 JWarmup、ElasticHeap、多租户、JFR 等众多功能、协程 Wisp 2.0、GCIH 等也在开源的规划上。
同时,Alibaba Dragonwell 作为 OpenJDK 的下游,每个发行版都会同步上游最新更新,包括安全更新、问题修复等,并经过阿里内部大规模的应用集群测试。
在新技术 Adoption 方面,Alibaba Dragonwell 目前发布和维护了 Java 8,11 两个 LTS 版本,阿里 JVM 团队会根据实际业务状况,移植 Java11+ 的相关功能到 Java 8 和 11 两个版本,这样 Alibaba Dragonwell 用户可以在不跟进 Java 12,13 等这些 FR 版本的情况下,提前享受这些功能带来的技术红利。
OpenJDK 技术趋势
纵观 Java 技术 20 多年的发展,始终围绕着两大主题:Productivity 以及 Performance。在很多情况下,Java 在设计上 Productivity 是优于 Performance 考虑的。Java 引入的 Garbage Collector 把程序员从复杂的内存管理中解脱出来,但在另一方面 Java 应用始终困扰于 GC 暂停时间的影响。Java 基于栈式虚拟机的中间字节码设计,很好地抽象了不同平台 (Intel、ARM 等) 的差异性,同时通过 Just-in-Time (JIT) 编译技术,解决的 Java 应用 peak 性能, 但在另一方面 JIT 不可避免引入了 Warmup 的代价,正常情况下 Java 程序永远需要先 load class,解释执行,然后再到高度优化的代码执行。
如果从 JVM 视角来总结梳理下目前 OpenJDK 社区正在发生,孵化的相关技术,主要从工具、GC、编译器,以及 Runtime 四个方面进行一个主要概括:
JFR/JMC
Oracle 从 Java 11 开源了其之前一直作为商业功能的 JFR,JFR 是功能强大的 Java 应用问题诊断与性能剖析工具。阿里巴巴也是作为主要的贡献者,与社区包括 RedHat 等,一起将 JFR 移植到了 OpenJDK 8, 预计 2020 年 7 月即将发布的 OpenJDK 8u262 (Java8) 将会默认带有 JFR 功能,这样 Java 8 的用户可以基于这个版本免费使用 JFR 功能。
ZGC/shenandoah
无论是 Oracle 在 Java 11 发布的 ZGC,还是 RedHat 已经做了好几年的 shenandoah,都实现了 concurrent copy GC,解决 Large Heap 情况下的 GC 停机性能。ZGC 最新状态,在 9 月份即将发布的 JDK 15,ZGC 将从 Experimental 功能变为生产可用 [3] 。实际上,在 AJDK 11 上,阿里巴巴团队 JVM 团队已经做了大量 Java 11+ 到 Java 11 的 ZGC 移植工作,以及相关问题修复,2019 年双 11 和阿里数据库团队一起,让数据库应用运行在 ZGC 上,100+ GB Heap 情况下 GC 暂停时间可以保持在 <10ms 以内, 详细讨论参考 [4]。
Graal
用 Java 开发的新一代 Just-in-Time 编译技术,用来替代目前 HostSot JVM 的 C1/C2 编译器,OpenJDK 上的 Ahead-of-Time (AOT) 技术也是基于 Graal 编译器开发。
Loom
OpenJDK 社区协程项目,对应于 AJDK 的 Wisp 2.0 实现,详细讨论可以参考 [5]。
进击的 Java:面向未来演进
2020,站在一个全新的节点上,本文也从三个大的方面 Cloud Native, AI,以及多语言生态三个方面展望下未来的发展,有些讨论本身是超越 Java 本身的。
面向 Cloud Native 的语言进化
云原生时代,软件的交付方式发生的根本性变化。以 Java 为例,在之前 Java 开发者交付的是应用本身,具体体现在以 “jar”, “war” 的形式交付, 而云原生则是以 Container 为交付单位的:
在运行方面,面向 Cloud Native 的应用要求:
Reactive
Always Watching
Extreme low memory footprint
Quick boot time
Java 语言作为企业计算,互联网领域的王者,拥有一致性,丰富的构建在 Java 语言之上的生态系统, 丰富的三方库,多样的 Serviceability 支持等,随着云时代应用微服务化,Serverless,这些新的架构逐渐触及到了 Java 程序速度提升的天花板 —— Java 自身的启动运行开销。
在 Cloud Native 这个新的上下文里, 我们谈论语言的进化,绝不仅仅限于运行时,编译器层面, 新的计算形态一定伴随着编程模型的变革,这涉及围绕程序语言的 Library、Framework、Tools 等一系列配套的改革。从目前业界来看,也有不少的项目正在发生:配合 GraalVM/SVM (Java 静态编译技术) 的下一代编程框架 Quarkus, Micronaut, 以及 Helidon,Quarkus 更是提出了“container first” ,他们提倡的分层的 lightweight uber-jar 的概念正是符合了 container 交付这一趋势。而 Red Hat 的 Java 团队与 OS 团队合作的 "Checkpoint Restore Fast Start-up" 技术 (AZul 在 JVM 技术峰会 '2019 上也提出过类似的想法) 则是在更加底层的技术栈上解决 Java 快速拉起问题。
在 Java for Cloud Native 方向,我们也开展了相关研发工作。Java 是静态语言,但是包含了大量的动态特性,包括反射,Class Loading,Bytecode Instrument (BCI) 等等,这些动态特性本质上都是违反 GraalVM/SVM 所要求的 Closed-World Assumption (CWA) 原则,这也是导致传统跑在 JVM 的 Java 应用不容易在 SVM 编译运行的主要原因。阿里巴巴 JVM 团队对 AJDK 做了静态化裁剪,务求在 Java 静 / 动态特性之间找到一个确定的边界,从 JDK 的层面为 Java 静态编译提供可能性。同时向上,与蚂蚁中间团队合作,定义面向静态编译的 Java 编程模型,通过编程框架来约束 - Java 应用的开发是面向静态编译友好的。我们静态编译了基于蚂蚁开源中间件 SOFAStack 构建的服务注册中心 Meta 节点应用,相较于传统 的运行在 JVM 上,性能有量级的提升:服务启动时间降低了 17 倍,可执行文件大小降低了 3.4 倍,运行时内存降低了一半。详见 [6]。
AI 的兴起,编程语言异构计算的新挑战
2005 年,时任 Intel CTO 的 Justin Rattner,说过 “We are at the cusp of a transition to multicore, multithreaded architectures”, 在前后的十几年中, 编程语言与编译器领域一直在努力面向 parallel architectural paradigm 做优化探索。随着 AI 这些年的兴起, 不同的时间节点,相似的场景,面向 FPGA/GPU 异构计算场景,对编程语言与编译器领域提出了新的挑战。
除了传统 Compiler 诸如 IBM XL Compilers, Intel Compilers 等做的 Automatic Parallelizing 工作,在极致性能探索方面,基于多面体模型 (polytope model) 的编译优化技术作为解决程序并行化、数据局部性优化的一种手段,成为编译优化领域的研究热点。
而在 Parallel Languages 层面,对 C&C++ 开发人员,CUDA 的出现降低了 GPU 的编程门槛,但 GPU 和 CPU 两种硬件模型本质区别,导致过高的开发成本,需要学习和了解更多底层硬件细节,还更不用说更高级语言的开发语言像 Java 等所面临的底层硬件模型与高级语言之间巨大的 GAP。
在 Java 领域,最早在 JVM 技术峰会 2014,AMD 曾经分享过他们的 Sumatra 项目,尝试实现 JVM 与 Heterogeneous System Architecture 目标硬件交互。而在最近,由 The University of Manchester 发起的 TornadoVM 项目,实现包含:一个 Just-in-Time 编译,支持从 Java bytecode 到 OpenCL 的映射,一个优化的运行时引擎,以及可以保持 Java 堆和异构设备堆内存一致性的内存管理器。TornadoVM 的目标是开发人员不需要了解 GPU 编程语言或者相关的 GPU 体系结构知识就可以编写面向异构的并行程序。TornadoVM 可以透明地运行在 AMD GPUs, NVIDIA GPUs, Intel integrated GPUs 以及 multi-core CPUs 上。
在通用 CPU 领域, OpenJDK 社区的 Vector API 项目 (Panama 的子项目),依赖 CPU 的 SIMD 指令,获得计算性能的成倍提升,Vector API 在大数据,AI 计算也有非常广的应用场景。阿里 JVM 团队把 Vector API 移植到了 AJDK 11,后续会开源到 Alibaba Dragonwell,分享下我们获得的基础性能数据:
Polyglot Programing,链接多语言生态
Polyglot Programming 并不是一个新的概念。在 Managed Runtime 领域, 2017 年 IBM 开源 Open Managed Runtime(OMR), 以及 2018 年 Oracle 开源 Truffle/Graal 技术。OMR 和 Graal 技术让开发人员实现一个新的语言成本大幅下降。前者 OMR 以 C、C++ 组件的形式提供了 Garbage Collection (GC), Just-in-Time (JIT) 以及 Reliability, availability and serviceability (RAS,工具) 等, 开发人员可以依赖这些组件,通过 ‘glue’ 的方式基于这些组件实现自己的高性能语言。而后者 Truffle/Graal, Truffle 是一个依赖 AST parser 实现新的语言的 Java 框架,本质上是将你的新的语言映射到 JVM 世界。不同于 Scala, JRuby 这些围绕 JVM 生态本身构建的语言,他们本质是还是 Java, 无论是 OMR, 还是 Truffle/Graal,他们都提供了生产级的 GC,JIT,以及 RAS 服务支持,新开发的语言完全不需要再重新实现这些底层技术。
从业界来看,面向特定领域的 Domain Specific Language (DSL) 语言已经有向这些技术迁移的趋势,高盛正在与 Graal 社区合作,把他们的 DSL 迁移到 Graal 上。另外 Ruby/OMR, Python/Graal, JS/Graal,WASM/Graal 等这些真正链接不同语言生态的项目,也正在迅速发展起来。
回到 AJDK, Graal 已经在 AJDK 8 开始支持, JS/Graal 这样成熟的技术,已经在阿里内部业务上线。
最后
Java 是一项二十多年前被发明出来的技术,她历经磨难,几易其主,但却历久弥新。这篇文章旨在为 Java 的开发者们梳理下目前的 Java 技术现状,以及讨论在云、AI 等重要领域内 Java 技术的演进趋势。在介绍的相关部分,我们也穿插了阿里的一些工程实践。作为世界上最大的 Java 用户之一,我们也一直在探索把前沿的 Java 技术,通过在阿里丰富的业务场景的试验,真正把这些技术应用于真实的生产环境。我们也非常乐于分享和贡献 Java 领域的经验、实践与技术洞见,共同促进 Java 的发展。
参考:
[1] https://www.infoq.com/news/2017/10/javaone-opening/
[2] https://www.oracle.com/technetwork/java/javase/11-relnote-issues-5012449.html#Diffs
[3] https://openjdk.java.net/jeps/377
[4] https://mp.weixin.qq.com/s/FQpvT5wIy9xwhX2jHMU7aw
[5] https://mp.weixin.qq.com/s/K1us6aH-gjHsWGhQ3SulFg
[6] https://www.infoq.cn/article/uzHpEbpMwiYd85jYslka
作者介绍:
李三红,阿里 / 蚂蚁程序语言与编译器团队负责人,Chief JVM Architect。在加入阿里之前,一直从事 IBM Java 虚拟机 J9 的开发工作,在 Java 虚拟机领域拥有多项技术专利。活跃于 Java 技术社区,GreenTea JUG(Java User Group) 组织者,JVM 顶会 JVMLS’17 受邀演讲嘉宾,JavaOne、QCon、JPoint、Joker 等国际会议受邀嘉宾,VMIL’18 会议程序委员会委员。