写点什么

从本地原生到云原生,Alibaba Dragonwell 静态编译的实践与挑战

  • 2019-10-25
  • 本文字数:3083 字

    阅读完需:约 10 分钟

从本地原生到云原生,Alibaba Dragonwell静态编译的实践与挑战

近些年来,云原生(Cloud Native)的概念席卷业界,其核心元素之一就是如何提高云上业务的响应速度。随着应用微服务化、容器化程度的不断提高,应用的执行响应速度也在不断提升,逐渐触及到了Java程序速度提升的天花板——Java 自身的启动运行开销。


虽然 Java 从最初的单独解释执行演进到 JIT(实时编译)和 AOT(提前编译)后,在运行时 peak performance 和冷启动性能方面都取得了大幅进步,但如虚拟机启动、代码解释执行、JNI 调用、反射开销、静态初始化检查开销等 Java 虚拟机和运行时本身的耗时点始终存在,并且耗时占比随着应用程序运行时间的降低而愈加突出。要进一步提高云原生应用的启动执行速度,突破 Java 自身的启动运行开销性能瓶颈,就必须在传统的 Java 程序编译启动执行过程之外,另辟蹊径。

Java 静态编译简介

Java 静态编译技术是一种激进的 AOT 技术,通过单独的编译阶段将 Java 程序编译为本地代码,在运行时无需传统 Java 虚拟机和运行时环境,只需操作系统类库支持即可。目前较成熟、受到业界广泛关注的开源 Java 静态编译器是由 Oracle 开发的GraalVM SubstrateVM(以下简称 SVM),图 1 展示了目前基于 SVM 的阿里巴巴静态编译项目的基本编译过程。


SVM 遵循封闭性假设(closed-world assumption, 即运行时所需的所有内容必须在编译时提供),将应用程序代码及其所依赖的三方 jar 文件和Alibaba Dragonwell代码编译为本地机器码,同时也将用 Java 编写的 Runtime 编译为机器码,两者被编到一个 elf 可执行文件或 so 共享库文件中,实现代码的自举。运行阶段只需直接执行 elf 文件,或者在其他 C/C++程序中调用 so 文件中发布的 API 即可。



图 1:SVM 静态编译基本过程


可以认为静态编译技术实现了 Java 语言与原生 Native 程序的“合体”,将原本的 Java 程序编译成为了一个自举的具有 Java 行为的原生 Native 程序,由此兼有 Java 程序和原生 Native 程序的优点。

Alibaba Dragonwell 静态编译实践

极速启动:Meta 节点应用 Serverless 化

从 Java 程序角度看,经过静态编译后 Java 程序具有更快的启动速度、更低的内存占用、更小的发布体积,在云上部署时从服务拉起到响应用户的请求所需的时间更短,非常适合云原生的需求。


以蚂蚁开源中间件项目 sofastack 的服务注册中心Meta节点应用为例,该项目验证了静态编译在 Serverless 应用上的可行性。图 2 展示了以传统 Java 方式运行和静态编译程序运行的几项数据的比较。



图 2:Sofastack 注册中心 Meta 节点静态编译前后性能对比图


左上图的服务启动时间指服务完全启动到可以接受用户请求的状态所需的时间;右上图的可执行文件大小指包含了运行 Java 程序所需的所有依赖资源的 fat jar 包和静态编译出的 elf 可执行文件的大小比较,虚线框代表没有显式打入 fat jar 的 Alibaba Dragonwell;底图的运行时内存消耗则是以相同压力请求测试时,两个版本应用各自的内存使用情况。从图中可见静态编译的代码在这些指标上较传统 Java 程序有质的提升,服务启动时间降低了 17 倍,可执行文件大小降低了 3.4 倍,运行时内存降低了一半。

多语言支持:RocketMQ 客户端应用

从 Native 原生代码角度看,在静态编译的帮助下开发人员可以用 Java 编写出 Native 代码,较以往的 C/C++开发效率更高、为同一业务维护多个语言版本的成本更低。


在这方面的探索中,阿里巴巴发布了静态编译版本的 RocketMQ 客户端,为 RocketMQ 进一步 Serverless 化提供了语言无关的运行时保障,实现了一套内核的多语言支撑。图 3 展示了 RocketMQ 客户端的多语言维护的示意。



图 3:RocketMQ 客户端多语言实现示意图


在引入静态编译技术之前,同一需求需要用两种语言分别实现不同的 SDK,最终运行在不同的环境中,开发和维护成本高。在静态编译的支持下,同一需求只用 Java 单一语言开发,然后沿图中绿色路径静态编译得到 Native Code。当然此外还需要一部分适配工作,将拟暴露的 API 用 SVM 定义的 C-Java 转化协议包装起来。


与先前单独编写 C++客户端相比,静态编译方案给多语言客户端的快速开发和后续管理带来了诸多优势:


  • 基于 Java 统一内核实现,避免功能重复开发;

  • 面向接口设计开发,内核实现插件化加载;

  • 功能升级只需分发内核,用户无感知;

  • 客户端实现闭包,运行时无任何第三方依赖。


目前静态编译版本的 RocketMQ 客户端已稳定可靠地服务阿里巴巴集团内部以及阿里云超过 10+ 业务场景,包括网络延迟在内的客户端启动时间相比 Java 原生客户端提升 30%,达到与 C++版应用同等的启动性能。

静态编译的挑战和 Alibaba Dragonwell 的应对

然而世界上没有银弹,静态编译技术也不例外。兼有 Java 和原生 Native 代码两者的优势是以牺牲部分 Java 动态特性为代价换取来的,表格 1 列出了在 SVM 中受限制的 Java 特性。封闭性假设要求在编译时必须获取运行时所需的全部信息,这与 Java 的动态性相矛盾,是静态编译对传统 Java 限制最大的部分。代码 Native 化是指由于丢弃了 Bytecode,传统上基于 Bytecode 的特性便不再被支持。缺少工具指缺少调试静态编译后代码的工具,如 Heap Dump、Thread Dump、代码调试等功能在 SVM 社区版中都没有提供。


原因分类存在限制的特性具体解释
封闭性反射、动态类加载、动态代理、JNI反射、序列化反序列化、MethodHandler编译时需要完全掌握运行时的信息
代码native化插桩、JVMTI、agent编译为本地代码后已不存在bytecode
缺少工具Heap dump,Thread dump、调试部分存在于企业版中,社区版为提供


表格 1:SVM Java 特性限制一览


可以看到 SVM 静态编译仅支持了传统 Java 特性的子集,而且对生产级的应用还缺少良好的工具支持。阿里巴巴正在结合自己的业务场景与 SVM 开源社区紧密合作,以 Alibaba Dragonwell 和 SVM 为基础,积极探索如何缩小静态编译和传统 Java 之间的鸿沟。


一方面逐步扩展静态编译能够支持的特性子集,使静态编译能够适用于更多的业务场景。比如针对 JDK 原生序列化反序列化的需求,通过预执行输出动态加载的类,将其加入静态编译的代码范围中,并自动生成需要的反射配置信息提供给编译器,最终实现对序列化反序列化特性的支持。另一方面探索适合面向静态编译的 Java 编程模型,帮助开发人员便捷地开发出适合静态编译的 Java 程序。


阿里巴巴对 Alibaba Dragonwell 进行静态化剪裁,一边定义了使用反射、动态类加载等不完全支持特性时的规则,并通过 javac 做强制检查。一边将静态编译完全不能支持的特性从 Alibaba Dragonwell 中去除,帮助开发人员以静态编译的思维开发新的 Java 程序。最后增加了对 Thread dump,Heap dump 支持,并开发了针对阿里巴巴业务场景的更有效的 GC 算法。这些对业务场景的不断实验和打磨,在成熟后也会贡献反哺到社区。

总结

静态编译技术是一种兼具传统 Java 程序和本地原生代码程序二者优点的技术。以静态编译的原生代码助力云原生应用,既保持了传统 Java 的开发流程和效率,又消除了 Java 自身固有的性能瓶颈,显著改善服务拉起响应请求的速度,阿里巴巴也通过自身实践,证明了静态编译技术在实际生产中的可行性。


在长期的 Java 开发实践中,阿里巴巴对 OpenJDK 不断优化总结开发出了其下游 Alibaba Dragonwell JDK,现已运行在 100,000+服务器上,为阿里巴巴的各项业务提供基础服务。相信随着 Alibaba Dragonwell 静态编译版本进一步成熟,将能够支持更多原生代码应用部署上云。


作者介绍:


林子熠,阿里巴巴集团 JVM 团队技术专家。上海交通大学软件工程专业工学博士,毕业后加入华为编译器与编程语言实验室参与方舟编译器的研发工作,现于阿里巴巴 JVM 团队主要负责 Java 静态编译技术在 Java 服务端的开发与应用。


2019-10-25 14:435921

评论 2 条评论

发布
用户头像
看起来牛逼,性能提升上来,直接Java能干很多活了
2019-11-06 16:03
回复
后续应该缺少架构方面的内容了吧,基本上不能反射。更多应该关注到业务层了,简化了架构部分
2020-01-04 16:34
回复
没有更多了
发现更多内容

技术领先、“忠”于业务,用友走出多维数据库的价值之路

用友BIP

面对职业焦虑,我们能做些什么?| 社区征文

三掌柜

三周年征文

行走的Offer收割机!首次公布Java10W字面经,Github访问量破百万

Java java面试 Java八股文 Java面试题 Java面试八股文

看火山引擎DataLeap如何做好电商治理(二):案例分析与解决方案

字节跳动数据平台

短视频 DataLeap 电商治理 达人治理 商品安全

发布会实录|悠易科技CTO李旸:洞察新引擎 品牌新增长

游读分享

真香! GitHub大牛呕心沥血整理的5000页Java学习手册

Java你猿哥

Java MySQL redis Spring Boot java基础

一顿饭的事儿,搞懂了Linux5种IO模型

Java你猿哥

Java Linux 后端 ssm io

ThottleStop 软件的应用场景

汪子熙

cpu intel 三周年连更

真香!阿里P8微服务实战心得首次公开,涵盖架构设计所有知识点

Java你猿哥

Java 架构 微服务架构 架构设计 架构师

Istio权威指南,华为云云原生团队倾情巨献!

博文视点Broadview

代码注释的艺术,优秀代码真的不需要注释吗?

阿里技术

代码注释

被 ChatGPT 点燃的向量数据库们

Bytebase

人工智能 数据库 openai AIGC ChatGPT

主网NFT铸造交易商城dapp系统开发搭建

开发v-hkkf5566

HTAP for MySQL 在腾讯云数据库的演进

NineData

MySQL 腾讯云 NineData HTAP for MySQL 2023云数据库技术沙龙

精品!阿里P8爆款《SpringBoot+vue全栈开发实战项目》笔记太香了

Java 架构 Spring Boot Vue 前后端分离

华为研究院19级研究员几年心得终成趣谈网络协议文档,附大牛讲解

Java 计算机网络 网络协议

最具有中国特色的微服务组件!阿里新一代SpringCloud学习指南

Java 架构 微服务 Spring Cloud spring cloud alibaba

KubeEdge在边缘计算领域的安全防护及洞察

华为云开发者联盟

开源 边缘计算 华为云 华为云开发者联盟 企业号 5 月 PK 榜

一站式统一返回值封装、异常处理、异常错误码解决方案—最强的Sping Boot接口优雅响应处理器 | 京东云技术团队

京东科技开发者

Spring Boot 处理器 企业号 5 月 PK 榜 Graceful Response web接口开发

学习java没规划?2023最新路线图,大堆资源秒变大神

Java你猿哥

Java 数据库 前端 后端 java基础

如何选择合适的共享电动车厂商

共享电单车厂家

共享电动车厂家 共享电单车厂商 景区共享电单车 校园共享电动车 共享电动车生产

美团太细了!HashMap可以存null,ConcurrentHashMap不可以为什么

Java你猿哥

Java hashmap ssm

数字人是否能成为企业智能化的门户?

Onegun

人工智能 数字人

低代码为什么需要专业代码

牛刀专业低代码

项目终于用上了 DDD 领域驱动,太强了!

Java 架构 DDD

精准测试之过程与实践 | 京东云技术团队

京东科技开发者

精准测试 质量保障 企业号 5 月 PK 榜

鬼知道我经历什么,从Java外包到了阿里P7,没想到我也有今天

Java你猿哥

Java Spring Boot JVM java面试 Java八股文

mosn基于延迟负载均衡算法 -- 走得更快,期待走得更稳

Java你猿哥

Java 负载均衡 ssm 架构师

面对本地缓存和分布式缓存,我们该如何选择?

深入理解 MySQL 索引底层数据结构

Java你猿哥

Java MySQL 算法 ssm sql

LinkFlow发布会实录|食品饮料品牌洞察应用实践分享

游读分享

从本地原生到云原生,Alibaba Dragonwell静态编译的实践与挑战_服务革新_林子熠_InfoQ精选文章