Java 20 年:JVM 虚拟化技术的发展

  • 郭蕾

2015 年 5 月 26 日

话题:JavaJVM语言 & 开发架构

虚拟化技术已经有了几十年的发展历史,并且在硬件、操作系统层面都已经得到了广泛的应用。虚拟化不但可以显著节省成本,而且还可以提升管理性。同样,虚拟化技术也可以应用在 JVM 中,以提高资源利用率,降低单应用的部署成本。早在 2004 年,Sun 公司就提出过 Java 应用虚拟化的设想,并且还制定过两个 JSR 规范。那现在 JVM 虚拟化技术发展到了哪一步?基于 JVM 的虚拟化技术在实现过程中有哪些难点?为了回答这些问题,InfoQ 采访了蚂蚁金服的 JVM 专家李三红

定义以及历史

InfoQ:能介绍下什么是 JVM 的虚拟化吗?JVM 的虚拟化价值在哪里?

李三红:传统的 Java 应用部署模式,一般遵循“硬件 -> 操作系统 ->JVM->Java 应用”这种自底向上的部署结构,其中 Java EE 应用可以细化为“硬件 -> 操作系统 ->JVM->JavaEE 容器 ->JavaEE 应用”的部署结构。这种部署结构往往比较重,操作系统、JVM 和 JavaEE 容器造成的 overhead 很高,而很多时候一个 Java 应用并不需要跑满整个硬件的资源,导致这种模式的资源利用率是比较低的。

而另一方面,硬件虚拟化技术逐渐成熟:VMware Hypervisor、Xen、KVM、Power LPAR 等技术能够帮助我们在同一个硬件上部署多个操作系统实例(每个操作系统实例可以理解为宿主机的租户),而时下流行的 OS Container 技术如 LXC、Docker 等,则是把操作系统虚拟化为多个实例,实现更轻量级的虚拟化。无论哪个层面的虚拟化,其目的都是对资源利用率更加高效的追求。

同样的思路,我们也可以在 JVM 层面,或者容器框架层面做虚拟化,类似于 Hypervisor 或者 OS Container,让虚拟化的 JVM/ 容器框架可以支持多租户的运行模式,这是比 OS 虚拟化更高一层的做法:



如上图,从左到右来看,随着虚拟化层次的提高,从 Hardware 到 OS,到 JVM,再到容器,单个租户应用的部署成本也在下降,最右边的“多租户”的 JavaEE Container(Multitenant-Container)是在容器框架层面的虚拟化,可以支持更高密度的应用部署,而不是传统的 APP : Container = 1:1 的部署方式。

什么是单个租户应用部署成本?举一个简单的例子,在没有虚拟化之前,传统的部署模式,一个 JavaEE 应用需要独占所有的硬件资源(CPU、MEM、网络等)。Hypervisor 的出现,使得一个共享的硬件资源上可以同时跑多个 OS,这种资源使用上的节约本质上是通过 Over-Commit(即允许租户超量使用物理资源)来达到的,即我们假设跑在同一个虚拟化环境的不同租户不会在同一个时间消费同样的资源。同样的道理可以来理解 JVM/ 容器框架的虚拟化。

多个 JavaEE 应用可以部署在同一个 JVM/ 容器内,但逻辑上它们各自会认为是运行在一个独立的 JVM/ 容器内,从而可以更大程度的提高资源利用率,降低单应用的部署成本。

InfoQ:JVM 虚拟化的概念是什么时候出现的?能聊聊它的发展历史吗?

李三红:早在 2004 年,Sun 公司就提出过 JVM 虚拟化这方面的想法,当时 Grzegorz Czajkowski 领导了一个叫做巴塞罗那的研究项目,该项目基于 Java HotSpot 虚拟 1.5 版本开发了 Multi-Tasking Virtual Machine(MVM)。MVM 旨在提高 Java 程序的启动速度,节省内存开销。不过自从 Sun 被甲骨文收购后,我们没有听到关于该项目的任何新的进展。尽管没有看到 MVM 成功产品化,不过它却留下两个重要的 JSR(Java Specification Request)规范:JSR121 和 JSR284。JSR284 目前在 java.net 上有一个实现它的孵化项目 jsr284-ri-tck(ri: Reference Implementation, tck: Test Compatible Kit)。

从 2009 年开始,IBM Java 团队也开始着手研究 JVM 的虚拟化技术,并于 2013 年发布第一个基于 IBM J9 虚拟机的 Bata 版本。IBM Multi-tenant JVM 是 JVM 层面的虚拟化,其思路是把多个标准的 Java 应用运行在同一个 JVM 上,让这些应用共享底层的 GC、JIT、Java 运行时库等基础组件。

Waratek 也在 2012 年的 Red Hat 技术峰会上发布了 CloudVM Beta 版本,支持多租户。与 IBM Multi-tenant JVM 类似,Waratek 允许多个应用运行在同一个 CloudVM 上,每一个应用运行在一个叫 Java Virtual Container(JVC)的容器里。

应用场景以及发展前景

InfoQ:JVM 虚拟化最适合应用在什么场景中?

李三红:虚拟化的本质就是把本来独占的资源共享出来,即在 A 不需要的时候,B 可以拿来用,从而提高资源的利用率。

如果我们能把独占资源的应用,通过 JVM 的虚拟化的能力,同时部署在同一个“多租户”JVM 里,或者是同一个“多租户”容器里, CPU、Heap 这些资源就可以极大程度地共享了,部署的密度也就可以成倍的提高,其结果就是单应用的部署成本成倍的下降。打个简单的比喻,如果按照 1:1 的部署密度,机器的成本是 1000 台,如果我们能把部署的密度提高到 1:10,机器的成本就是 1000/10=100 台。

多租户的 JVM 或者容器,其最大的应用场景就是高密度的应用部署场景。也许有人有疑问,OS 虚拟化也可以提高部署密度, 为什么要选择 JVM 虚拟化?

我们就拿 Docker 作为一个例子来比较一下。比如利用 Docker 可以把运行在同一个实际操作系统上的单个 JVM 进程互相隔离,每个 JVM 进程可以看作是实际操作系统的一个租户,下面是一个简化的例子(先不考虑复杂的 OS 内存交换场景):



左图表示在 OS 之上,使用 Docker 虚拟出来两个租户,即两个独立的 JVM 进程分别运行在两个隔离的 Docker 容器里。右图则表示 JVM/ 容器的虚拟化方案。在 Docker 的方案里,由于两个 App1 和 App2 是跨 JVM 进程的,所以 Heap 资源对于它们来说不是共享的,很难在 Heap 内存在 App1 不使用的时候,可以拿来给 App2 使用,这个就是一个限制 Docker 这种方案部署密度的因素,比如你有 8G 内存,你可能会选择部署两个 Docker 容器,每个 4G。而这个因素对于 JVM 虚拟化方案,则不存在这样的限制,因为所有的 App 都是在一个进程里的,Heap 对大家来说都是共享的,完全可以通过合理的安排选择部署更多的 App。

InfoQ:你认为多租户 JVM 的前景如何?为什么现在做多租户 JVM 的厂商这么少?

李三红:在 IBM 的时候,其实我们内部有过很多次的讨论。如果我们从虚拟化的这个角度来看,从硬件, 到 OS, 再到 JVM, 以及容器, JVM 的虚拟化(多租户 JVM)以及容器的虚拟化(多租户容器)是一个技术的发展趋势。但是,现实的情况是,根据我们这些年在这个领域的经验与积累,基于传统的 JVM 实现 JVM 虚拟化,技术上碰到的很多的挑战,其中一些的确难于在短期内找到一个好的解决方案。(关于里面的一些实现细节,读者可以参考我之前的文章,高密度 Java 应用部署的一些实践) 。简单列举一个例子,在多租户 JVM 中,每一个租户都有自己独立的 Region, 但是如果租户与租户之间出现交叉引用的情况,就会导致 object leakage,这个是我们内部使用的一个技术术语。其结果是,在某些条件下,某个租户退出 Region 不能合理释放。这个问题头痛的地方在于,每次 Java class library 的代码改动,都有可能造成新的 object leakage。类似这样的问题, 需要 Java Class Library 开发者和多租户 JVM 之间有一种约定,或者范式来共同约束解决这类问题。

我们再来谈第二个问题。 就像你说的,目前做多租户 JVM 的厂商的确很少,事实上本来做商业 JVM 的厂商也就那么几家。IBM J9 是比较早切入这个领域的 JVM,主要是由中国和加拿大的团队一起开发, IBM 也只是做了 JVM 这层的虚拟化,并没有支持到容器级别。不过据我所知, 这个项目已经停了, 停的原因可能很多,我个人认为主要的原因是: 第一,IBM 没有真实的应用场景来检视高密度部署的实际价值。第二,资源和优先级上的考虑,Java 技术中心有更重要的东西来做。不过到目前为止,IBM 好像还没有在正式场合公布这个东西。

如果我们广义上来谈 JVM 虚拟化,而不要局限于多租户 JVM(即一个 JVM 上跑多个 Java 应用的场景), 我个人觉得 JVM 虚拟化技术在高密度部署领域是有非常大的价值,尤其是在云计算大行其道的当今, 我想这也是 Waratek 一直所信奉的。 这里谈到应用的前景,我想有两个问题值得再深入考虑: 第一,在云计算的环境下为 JVM 虚拟化找到高密度部署的应用场景,单个租户应用部署成本是关键的考量因素。第二,基于特定的场景,规避一些技术实现上难点。

Java 语言的发展

InfoQ:一晃眼,Java 就已经 20 岁了,你认为 Java 的发展经历了哪几个阶段?

李三红: James Gosling 带领团队在 1991 年开始了一个叫”Oak”的项目,这个就是 Java 的前身。1995 年,Java1.0 发布。“Write once, run anywhere” 这句 Java 口号想必大家耳熟能详。Java 刚开始出现的时候主要面向 Interactive Television 领域,直至后来几年的发展,SUN 一度想用 Java 来打造桌面的网络操作系统,取代当时如日中天的 Windows。不过不曾想,Java 虽未在 Embedded、Desktop 领域内取得多大的建树,出乎意料地,却在企业级应用领域开花结果,占据了如今几乎统治的地位。失之東隅,却收之桑榆。

Sun 在 2006 年的 Java One 大会上,宣布 Java 技术开源,随后年底的时候在 GPL 协议下发布 HotSpot 以及 javac,这是 Java 发展中的里程碑事件。从 2006 到 2010 年,这期间 SUN 一路磕磕绊绊,尽管手握 Java 这个金矿,但在商业上一直找不到好的盈利点,直到 2010 被 Oracle 收购。 2010 年,也是 Java 发展的一个重要的分水岭,Java 面临分家的风险, 一方是 Apache Harmony 为代表的, 其后是 IBM 的支持, 另一方是 OpenJDK 及其背后的 Oracle。最后博弈的结果现在大家都知道了, IBM 转向 OpenJDK,Apache Harmony 也结束了它的历史使命,被 Apache 之后束之高阁。Harmony 为 IBM 在 Java 上赢得的应有的话语权,另外一个副产品,就是给移动端 Android 平台贡献了 Java 核心类库代码。 2010 年是 Java 重生的一年。随后 2011 年 OpenJDK 7 发布, OpenJDK 7 是第一个 Java SE 的参考实现。

InfoQ:反过头来看,你认为为什么 Java 能够如此成功?

李三红: 好像有这么一句话,原话不太记得了,一流的公司建生态,二流的公司定标准,三流的公司卖产品。 这句话也可以用在 Java 上。 Java 的成功,离不开逐步完善,日臻成熟的 Java 技术生态圈,这个是远远超出语言层面优劣的东西。 在产品的选型上,无论纵向上,还是横向上,以 Java 技术构建的产品都有着无比的丰富性,Apache 社区的繁荣,可以作为这个故事的佐证。这个也是许多小众语言诸如 Scala、JRuby 愿意选择运行在 JVM 上的原因。

如果单从语言这个层面,谈论 Java 的成功,我就借用 Mark Reinhold 的一句总结,四个词概括 Java 的特征:Readability、Simplicity、 Universality 和 Compatibility。这也是 Java 语言能够风行,并被大家所接受的重要因素。

受访嘉宾介绍

李三红,蚂蚁金服 JVM Architect,前 IBM Multi-tenant JVM 项目技术负责人。目前在蚂蚁金服基础技术部,负责 OpenJDK/HotSpot 相关的开发优化工作。 十多年的 Java 开发经验,2008 年加入 IBM,参与基于 OSGi 框架的安全方面的开发,2010 年加入 Java 技术中心,参与 IBM Java 虚拟机 J9 的开发,在 Java/JVM 技术的领域拥有多项专利。 在 JavaOne、OSTC、IBM Technical Summit、IBM APN Summit 等会议上担任演讲嘉宾,上海 Java 技术社区 JUG(Java User Group)组织者。

JavaJVM语言 & 开发架构