11 月 19 - 20 日 Apache Pulsar 社区年度盛会来啦,立即报名! 了解详情
写点什么

Java on Truffle:实现真正的元循环

一种全新的、非常令人兴奋的运行 Java 代码的方式

  • 2021-02-10
  • 本文字数:3338 字

    阅读完需:约 11 分钟

Java on Truffle:实现真正的元循环

GraalVM 21.0 引入了一个新的 JVM 实现 Java on Truffle,这是一个使用 Java 编写的 Java 虚拟机,从而提供了一种在 GraalVM 上运行 Java 代码的新方式。


本文最初发表于 GraalVM 的Medium博客站点,经原作者 Oleg Šelajev 授权由 InfoQ 中文站翻译分享。


到目前为止,GraalVM 已经提供了两种运行 Java 程序的方式:组合使用 Java HotSpot VM 和 GraalVM JIT(just-in-time)编译器,以及使用 GraalVM Native Image 编译成原生可执行文件。


如今,我们很高兴地宣布一种在 GraalVM 运行 Java 的新方法。GraalVM 21.0 引入了一个新的可安装的组件,叫做espresso,它提供了一个使用 Java 编写的 JVM 实现。


Java on Truffle 在 Java 架构中的位置


Espresso 使得通过 Truffle 框架运行 Java 代码成为可能,从而将 Java 提升到与 GraalVM 所支持的其他语言相同的级别。

尝试运行


尝试 Java on Truffle 是非常简单直接的。它可以使用 gu 命令,作为一个组件安装到基础 GraalVM 发行版中。


gu install espressogu install -L espresso-installable.jar # if downloaded manually
复制代码


安装之后,要在 Java on Truffle 运行你最喜欢的应用,只需要为java命令传递-truffle参数即可。


java -truffle -jar myApp.jar
复制代码


请下载 Java on Truffle 并尝试一下。这里有一些带有指令的示例应用,阐述了 Java on Truffle 的特殊功能。


注意,当前 Java on Truffle 的性能并不代表它在不远的将来的能力。目前它的峰值性能要比常规 JIT 模式下运行相同的代码慢好几倍。另外,预热也还没有进行优化。在这个初始发布版本中,我们完全专注于功能、兼容性,并让 Java on Truffle 开源,使其能够在更广大的社区中得到应用。


预计在我们即将发布的每个 21.x 版本中,性能(包括预热性能和峰值性能)将会得到迅速提升


现在,我们更加详细地看一下 Java on Truffle 是什么并探索一些它提供帮助的典型用例,尝试将该项目放到更大的 GraalVM 和 Java 生态系统中。

Java on Truffle

Java on Truffle 是一个 JVM 实现,它使用了 Truffle 语言实现框架。它提供了 Java 虚拟机所有的核心组件:


  • 字节码解释器

  • 字节码校验器

  • 单程(Single-pass)的 class 文件解析器

  • 简单的对象模型

  • 使用 Java 语言编写的 Java 原生接口(Java Native Interface,JNI)实现

  • 使用 Java 实现的 Java 虚拟机

  • Java Debug Wire Protocol(JDWP)


这个 JVM 实现有很重要的一点就是它是使用 Java 编写的。Java on Truffle 是基于 Java 的 Java(Java on Java)。自托管是 Java 虚拟机研究和开发领域的圣杯。


它所能做的就是运行 Java 程序。当然,它也可以运行用其他 JVM 语言编写的程序。从上面的列表我们可以看出,它还支持调试协议,所以我们也可以使用它调试 Java 应用。


Java on Truffle 能够用于基于 Java 8 和 Java 11 的 GraalVM 发行版,所以从技术上来讲,你可以使用它来替代自己所选择的 JVM。Java on Truffle 目前是实验性的,速度还不是很快,所以现在不建议将其用于生产环境的工作负载,但是我们可以探索一下使用 Java on Truffle 运行应用程序都能实现哪些特性。

基于 Java 的 Java

正如我们在前文所描述的,Java on Truffle 是使用 Java 实现的。它是一个虚拟机实现,所以为了实际运行 Java 代码,它需要访问类库以及 JDK 提供的本地库和方法。Java on Truffle 重用了 GraalVM 分发版的 JAR 和本地库。



因为它是使用 Java 实现的并且能够运行 Java,这使得 Java on Truffle 具有了非常有意思的特性:它可以运行自己!事实上, Java on Truffle 是一个元循环(metacircular)的虚拟机,它可以嵌套运行自己好几层(不过每次都会越来越慢)。


作为一个 Java 程序,它有很多优势。其中之一就是能够使用原生镜像编译成原生的可执行文件,在后面的章节中我们将会讨论一个很有意思的用例。


另外一个优势就是,对于 Java 开发人员来说,代码非常友好和熟悉,易于理解。读者可以考虑去 GitHub 仓库查看它的源码。你的日常工具适用于它,你的 IDE 支持它,你可以像探索其他 Java 依赖那样去探索它的代码。这种透明度和熟悉度能够让 Java on Truffle 更加高效地应对变化。

将 Java 11 嵌入到 Java 8 中


Java on Truffle 实际就是一个 JVM,但它也是一个 Java 程序,这意味着你可以在其他 Java 程序中运行它。这就为将应用程序中的不同组件进行分割开辟了一个很有趣的途径。举例来说,如果你将 Java on Truffle 指向一个 JDK 11,那么它就能运行 Java 11。如果访问 Java 8,那么它就会成为 Java 8。如果你同时拥有这两个发行版的话,那么你就可以在 Java 8 的环境中运行 Java on Truffle,并使用它来运行 Java 11 字节码,反之亦然。如果有个库只能用于 Java 8,那么你可以迁移至更新的基础 JDK,并且通过一些编程方面的努力让这个特定的库依然能够运行,这需要建立一种互操作性,在相同的 Java 进程中建立兼容的 JDK 8 环境。

混合 AOT 和 JIT


因为 Java on Truffle、Truffle、GraalVM 编译器和运行 Java on Truffle 的所有其他必要的组件都是使用 Java 编写的,所以我们能够构建一个包含运行 Java on Truffle 基础设施的原生镜像可执行文件。


这意味着,我们可以基于 Java 应用,将一个 JVM 构建到它的里面,然后要么在 JVM 上运行该应用,要么以原生镜像的方式运行该应用。需要注意,在后面的情况中,Java on Truffle 实际上可以执行任意的 Java 代码,这些代码不一定需要在构建的时候就得知道。


没错,Java on Truffle 可以将 JIT 编译器和动态 Java 运行时用到一个提前编译的二进制文件中。


Java on Truffle 允许为使用原生镜像构建的应用添加动态语言的特性


我们准备了一个样例应用来阐述这个理念。这是一个 JShell 实现的样例,它接受一个常规的 JShell 应用,该应用包含两个组成部分:前端的 CLI 应用和后端的计算引擎,我们将后者替换成了 Java on Truffle 实现。


实际上,它非常整洁地重用了原来实现中的所有类,只需加载它们即可。因此,示例应用程序的原始部分是连接托管 Java 部分和 Java on Truffle 部分的“胶水”代码。


这个示例可以被编译成原生可执行文件,以得到一个二进制文件,由于原生可执行文件的性能特征,它的启动速度比一般的 JShell 要快,而且仍然可以执行我们扔给它的 Java 代码。


下面是 Java on Truffle 实现的 JShell 加载并启动俄罗斯方块游戏的截图。



混合 AOT 和 JIT 对于那些不能利用原生镜像性能改进的应用程序来说是一个非常棒的可选方案,因为这些应用的功能依赖于动态代码,而动态代码不容易与原生镜像一起工作。

高级的类重定义


Java on Truffle 有另外一项很酷的特性,比 HotSpot 更强大,这就是增强的热替换(Hot Swap)能力:在调试会话中,运行时改变类。


GraalVM 21.0 支持如下的变化:


  1. 添加和移除方法

  2. 添加和移除构造器

  3. 从接口中添加和移除方法

  4. 改变方法的访问修饰符

  5. 改变构造器的访问修饰符

  6. Lambda 的变化

  7. 添加新的匿名内部类

  8. 移除匿名内部类


未来将会使热替换更强大的是支持对类字段的变化。该特性正在进行中,会在未来的释放版本中添加进来。


在 IntelliJ IDEA 调试器中重新加载修改的类


这个搭建过程与 HotSpot 相同:启动调试器、修改代码、重新编译类、在 IDE 调试器中点击“Reload the classes”并使用新代码恢复程序运行,下一次变更的代码就会生效。

GraalVM 生态系统的支持


对于 GraalVM 语言从 Truffle 框架中获取的开发人员工具支持来说,Java on Truffle 会使它们从中收益。


例如,你可以在运行应用的时候,使用某些java -truffle --cpusampler,这样的话就能让采样剖析器(profiler)在代码上运行。我们还可以启用跟踪剖析器或内存跟踪器,从而告诉我们代码的哪个部分产生了更大的内存压力。


生态系统的另一个方面是支持的语言。Java on Truffle 允许我们创建多语言程序,不同的组件用不同的语言编写。关于如何加载用其他语言编写的代码、在不同语言之间导出和导入对象等细节,超出了本文的范围,但细节可以从文档中找到

下一步的计划


GraalVM 21.0 是 Java on Truffle 的初始版本。现在它是一个实验性的组件,在接下来的版本中我们计划对它进行重大改善。


它有很多需要改进的地方,从支持 javaagents,到与其他语言的互操作协议方面提供更好的实现,重大的性能改进等等。


我们将致力于这些和其他方面的改进,并且会非常乐意听到任何反馈、特性请求、潜在的用例、发现的问题和当前版本的不足之处。你可以通过SlackGitHubTwitter分享你的反馈。要想开始学习它,请前往 graalvm.org/java-on-truffle


Java on Truffle 是一种全新的、非常令人兴奋的运行 Java 代码的方式。请了解并考虑一下它所带来的可能性。

2021-02-10 12:138163
用户头像
蔡芳芳 InfoQ主编

发布了 710 篇内容, 共 392.3 次阅读, 收获喜欢 2551 次。

关注

评论 1 条评论

发布
用户头像
Enable the Java on Truffle execution mode. From the main menu select Run -> Run… -> Edit Configurations > Environment. Put the -truffle -XX:+IgnoreUnrecognizedVMOptions command in the VM options field and press Apply.
It is necessary to specify -XX:+IgnoreUnrecognizedVMOptions because Intellij automatically adds a -javaagent argument which is not supported yet.
2021-02-22 11:50
回复
没有更多了
发现更多内容

Vue进阶(幺零八):npm run build 错误 (node:7852) UnhandledPromiseRejectionWarning: CssSyntaxError:xxxx. 解决分析

No Silver Bullet

Vue 9月日更

Parted 创建 GPT 分区

耳东@Erdong

Linux 9月日更 parted 磁盘分区

手撸二叉树之二叉搜索树中的众数

HelloWorld杰少

9月日更

数据结构和算法应用

Albert

算法 9月日更

为何数据类大项目都会先做盘点??

奔向架构师

数据仓库 数据治理 9月日更

双指针算法之同向双指针

泽睿

Java 数据结构 面试 双指针算法

【VueRouter 源码学习】第九篇 - router-view 组件的实现

Brave

源码 vue-router 9月日更

全方位解读服务网格(Service Mesh)的背景和概念

xcbeyond

Service Mesh 服务网格 引航计划

HTML进阶(三)

Augus

html 9月日更

分享 4 个前端开发必备的 Chrome 扩展

devpoint

SVG chrome扩展 9月日更

【LeetCode】有效的括号字符串Java题解

Albert

算法 LeetCode 9月日更

通过编程训练题来讲讲链表操作

Regan Yue

算法 链表 9月日更

【网络安全】Spring框架漏洞总结(二)

网络安全学海

黑客 网络安全 信息安全 WEB安全 漏洞挖掘

【Flutter 专题】49 图解 Flutter 与 Android 原生交互

阿策小和尚

Flutter 小菜 0 基础学习 Flutter Android 小菜鸟 9月日更

Redis核心原理与实践--列表实现原理之ziplist结构

binecy

redis 源码分析

服务注册与发现的原理和实现

万俊峰Kevin

微服务 服务注册与发现 microservice 服务发现 Go 语言

科技的进步会造福人类吗--闲聊科幻

姬翔

9月日更

模块七作业

seawolflin

架构实战营

翻转未来!钢铁之城重添色彩

白洞计划

网络攻防学习笔记 Day133

穿过生命散发芬芳

网络基础 9月日更

常用特殊符号大全

入门小站

工具

Golang 中的好代码 VS 烂代码

baiyutang

编码 Go 语言 9月日更

Context 和 struct

Rayjun

struct Context Go 语言

写给互联网工程师的5G书 | 0. 前言

俞凡

架构 5G

将JSON中对于集合的数据,如何解析成对象集合

卢卡多多

集合 Stream<T> 9月日更

灯塔之上:vivo X70背后的影像进化史

脑极体

linux之chsh命令

入门小站

Linux

一名优秀的技术Leader是如何炼成的?

架构精进之路

管理 技术管理 引航计划 内容合集

模块8

gevin

架构实战营

写给互联网工程师的5G书 | 1. 简介

俞凡

架构 5G

Python——函数正确调用

在即

9月日更

Java on Truffle:实现真正的元循环_编程语言_Oleg Šelajev_InfoQ精选文章