在 2025 收官前,看清 Data + AI 的真实走向,点击查看 BUILD 大会精华版 了解详情
写点什么

XRuby:享用 JVM 上的 Ruby

  • 2007-10-11
  • 本文字数:4739 字

    阅读完需:约 16 分钟

XRuby 是什么?它是一个开源编译器。与其它编译器一样,它完成的工作是将一种格式的语言转换成另一种。与大多数编译器不同的是,它是将 Ruby 的代码(.rb)转换成 Java 的字节码(.class)。

图 1:将 Ruby 编译为字节码

又一个 Ruby 实现?

Ruby 编译器?那岂不又是一个 Ruby 的实现。自从 Ruby 越来越受到人们的关注,各种 Ruby 实现也逐渐出现在人们的视野之中。除了 Ruby 之父松本行弘(Matz)开发的版本(Matz Reference Implementation,简称 MRI)之外,JRuby、Rubinius、IronRuby、Ruby.NET、Cardinal 等不同 Ruby 实现的名头也是一天比一天响亮。同为 Ruby 实现,XRuby 有哪些不同之处呢?

XRuby 是一个将 Ruby 代码编译为 Java 字节码的编译器,这说明

  • XRuby 的目标平台是 Java 虚拟机(Java Virtual Machine,简称 JVM)
  • XRuby 是一个编译器

运行在 JVM 上让 XRuby 有别于用 C 完成的 MRI,.NET 平台上的 IronRuby 和 Ruby.NET 和 Parrot 上的 Cardinal,而编译器的特点又让 XRuby 和 JRuby 有所差别。

JVM 上的 Ruby

无可否认,经过多年发展,Java 已经成为软件开发世界的主流语言之一,选择 Java 平台还因为:

  • Java 是一个经过验证的平台
  • Java 在许多领域内都有了成熟的解决方案
  • Java 已经有了大量稳定的基础结构
  • 有众多熟悉 Java 的人才
  • Java 社区非常开放

从程序设计语言的发展来看,一种新兴的程序设计语言都会存在与主流程序设计语言的接口,比如 C/C++ 对汇编语言的接口,比如 Java 语言对于 C/C++ 的接口。通过这样的接口,利用主流语言已有的资源,帮助新语言得到更好的接受。用 C 开发的 MRI 让 Ruby 已经拥有了和 C/C++ 的接口,XRuby 为 Ruby 提供了一种通往 Java 世界的选择。拥有 Ruby 和 Java 的接口,意味着我们可以将 Ruby 的开发效率和 Java 的丰富资源结合起来:在 Ruby 的代码中使用 Java 的类库;将 Ruby 应用部署到 Java EE 的服务器上……

为什么要将 Ruby 应用部署到 Java EE 服务器上呢?Java EE 技术经过多年的发展已经走向成熟,并在业界得到了广泛的应用,Java EE 的服务器逐渐稳定,在很多领域中都有了成熟的解决方案。更重要的是,将 Ruby 应用部署到 Java EE 服务器上,意味着之前众多企业在 Java EE 服务器方面的投资将会得到重用,这会极大的减少基础设施建设方面的浪费。

解释和编译

如果我们想将程序设计语言编写的源代码运行起来,通常情况下,我们有两条路可以走:解释和编译,这也是我们让 Ruby 运行于 JVM 平台的两种选择。

解释,这是 MRI 最初的选择。因为有 MRI 作为参考,所以,这也是一种相对来说比较容易移植的选择。这种做法需要有一种专门的执行引擎。如下图所示,源码经过 MRI 解析之后,产生了一棵抽象语法树(Abstract Syntax Tree,简称 AST)。利用这棵树产生我们需要的结果,这是执行引擎的工作。这种做法的好处就是可以把执行逻辑独立处理,无须为每个平台编写不同的代码,所以,这种做法的可移植性很好,它也就成了不少程序设计语言最初的选择。不过,随之而来的问题就是这会降低执行速度,毕竟,这个软件执行引擎的性能无法与硬件相比。所以,“编译”会让程序拥有更佳的性能。

图 2:解释

采用编译的方式,我们可以将代码编译成可以由硬件直接执行的二进制代码。对于 JVM 这个“虚拟”的机器而言,它的二进制代码就是字节码。因为不同硬件和不同操作系统的二进制格式是不同的,所以,如果希望语言得到广泛应用,那便需要针对不同平台实现平台相关的编译器后端,理论上说,这不是一件不能完成的任务,但实际上,这意味着巨大的工作量。JVM 的存在降低了这个难度,因为主流软硬件平台上基本都有自己的 JVM 实现,所以,代码可以运行在 JVM 上便意味可以运行在大多数平台上。当然,因为 JVM 本身是虚拟机,也是一种软件实现,所以,性能上也会有一些损失。不过,随着 JVM 技术上的不断进步,性能损失越来越小。另外,从 Java 平台的广泛应用也证明了,这样的损失在实践中是可以接受的。不过,相对于解释的方式有 MRI 这种成熟实现作为参考,编译显然需要更多的探索。

图 3:编译

除了执行性能之外,将 Ruby 代码编译为 Java 的字节码还可以为我们带来另外的好处,那就是保护源代码。解释的方式让很多人不放心的一点就在于,产品发布意味着将源代码也发布出去。对于需要保护知识产权的公司和个人而言,这是他们所不愿意看到的。通过编译的方式,我们将源代码转成了字节码,这样,源代码可以得到有效保护。破解字节码理论上也是有可能的,不过,这是另外的故事了。

XRuby 从起步开始走的就是编译的道路,而 JVM 上的另外一种 Ruby 实现——JRuby 则是从解释起步的。相比于解释,编译方式在性能方面有着很大的优势,所以,从解释方式起步的 JRuby 最终也走上编译的道路。

初涉 XRuby

让我们从一段简单的 Ruby 代码出发,更具体了解一下 XRuby。

class MyClass
def say_hello_three_times
3.times { puts “hello”}
end
end MyClass.new.say_hello_three_times

(simple.rb)

这里,我们定义了名为 MyClass 的类,其中有一个 say_hello_three_times,它的工作就是输出三次“hello”。即便你并不了解 Ruby 语言,相信这段代码看上去,也不是那么难以理解,只是语法上不尽相同而已。稍微需要解释一下的就是:

3.times { puts “hello”}

同许多面向对象程序设计语言相比,在 Ruby 中,面向对象做得更加彻底,所以,即便像“3”这样的数字也是一个对象,所以,我们可以调用它的方法。再有,就是后面括号里的东西。在 Ruby 中,这是一种语法结构,称为 block。从这段代码来说,block 中的代码会在执行 3.times 的过程中调用。当然,这里展现的只是非常简单的用法,事实上,block 的存在使得 Ruby 代码具有了更强的表现力。这不是一篇 Ruby 语言的介绍,如果你对 Ruby 语言更感兴趣,那本著名的《Programming Ruby》是个不错的选择。

将这段代码保存在一个名为 simple.rb,然后,用 XRuby 对它进行编译。

java -jar xruby-0.3.1.jar -c simple.rb

编译之后,会得到一个名为 simple.jar 的文件,运行这个 JAR 文件,就可以得到运行的结果

java -jar simple.jar

屏幕输出为:

hello
hello
hello

当然,我们也可以像使用其它 Ruby 实现一样,直接运行这段代码,而无需生成中间的 JAR 文件。

java -jar xruby-0.3.1.jar simple.rb

我们会得到同样的结果:

hello
hello
hello

作为一个 Ruby 用户,如果你对 XRuby 有兴趣,你所需要做的只是把 XRuby 安装到你的系统,像其它 Ruby 实现一样去使用,因为从用户的角度而言,XRuby 和它们没有区别。如果你对 Ruby 语言的实现感兴趣,也许你需要了解 XRuby 的一些内部实现。

XRuby 的架构

图 4:XRuby 架构图

上图展示了 XRuby 的架构,主要包括两个部分:编译器和运行时。编译器部分将 Ruby 代码编译生成字节码,运行时部分则实现了对 Ruby 语言的支持。下面具体看一下各个部分。

图 5:编译器

Ruby 代码经过 Parser 的解析,会形成一棵抽象语法树,Tree Parser 处理这棵树,形成 Code DOM。Code Generator 部分利用 Code DOM 生成对应的字节码。这里的 Code DOM 是对 XRuby 内部对 Ruby 语言建立的一个模型,通过这个模型进行代码生成。这个模型将 XRuby 的编译器前端很好的独立出来,这样,在保持前端不变的情况下,我们可以用它为不同的平台去做代码生成,这也 XRuby 之所以为“X”的一个原因。

图 6:运行时

从这张架构图中,我们可以看到,XRuby 的运行时包括动态语言的支持、内建库(Builtin)和 Java 支持几个部分。

Ruby 是一种动态语言,而 JVM 本身是为 Java 这样的静态语言提供的平台,很难直接在二者之间做直接的映射。动态语言支持的部分就是为了在 JVM 平台上支持动态语言特性而存在的。也是因为这个部分的存在,我们即便采用编译的方式,依然使用 Ruby 的动态语言特性,比如,在程序运行期间为类增加或删除方法等等。

我们知道,除了语言本身外,程序库是一种程序设计语言可以成功的另一种强大的推动力。同样,Ruby 的优秀,除了它优雅的语法外,与它有强大的内建库密不可分。所以,XRuby 当然也少不了对于内建库的支持。

正如前面提到的,XRuby 为 Ruby 提供了一条通往 Java 的道路,Java 支持部分就是完成这样的工作。有了这个部分,你就可以在 Ruby 脚本使用 Java 的类库,这样,丰富的 Java 资源可以在 Ruby 世界中得到重用。

如果这里的讨论引起你对 XRuby 更多的兴趣,或许你希望更多的了解 XRuby,那最好的方式是参与到 XRuby 的开发中来。

管窥 XRuby

进入 XRuby 开发最好的起点莫过于内建库,下面是一个简单的内建库中 Array#length 实现的例子:

@RubyLevelClass(name=“Array”)
public class RubyArray … {

@RubyLevelMethod(name=“length”)
public RubyFixnum length() {
return ObjectFactory.createFixnum(this.array_.size());
}

}

XRuby 提供了一个名为 @RubyLevelClass 的 Annotation,它将 Java 层次的类绑定到 Ruby 层次的类上。这里可以看到, RubyArray 是一个定义在 Java 层次的类,通过 @RubyLevelClass,它被绑定为 Ruby 层次的 Array 这个类上。同样, @RubyLevelMethod 完成的是将 Java 层次的方法绑定到 Ruby 层次上的工作。在上面的例子中,我们用这个 Annotation 将 Java 的 length 方法绑定到了 Ruby 的 length 方法上。这样,在 Ruby 代码中调用 Array 类的 length 方法最终会调用到 RubyArray 的 length 方法上来。

当然,这是一个极为简单的例子,不过,它至少可以说明,XRuby 的开发并不像许多人想象的那么复杂。实际上,大多数 XRuby 的参与者都是从内建库起步的,随着对 XRuby 了解的增多,再逐渐的参与到其它部分的开发之中,比如动态语言支持和编译器部分等等。

参与 XRuby

事实上,XRuby 欢迎任何形式的贡献,也鼓励大家进行任何尝试,这也是 XRuby 不断前进的动力。在这里,大家总会有冒出一些新的想法把事情做得更好。你可以选择不同的方式参与 XRuby:

  • 使用 XRuby
  • 报告 Bug
  • 提交补丁
  • 加入邮件列表分享你的想法
  • 成为 XRuby 的项目一员
  • ……

参与 XRuby 这样一个开源编译器项目会有很多乐趣:

  • XRuby 是一个编译器,对于那些不满于工作在黑盒上的程序员来说,编译器和操作系统等底层知识具有难以抗拒的吸引力,了解这些知识本身可以为我们带来更好的理解代码如何运行,写起代码来也会更加的得心应手。 编译器技术背后的思想不仅限于编译器技术本身,了解这些技术之后,你会发现它会在许多的问题上为你带来新的思路。
  • XRuby 是一个 Ruby 语言的实现,这意味着我们可以更多的了解 Ruby 这种优雅的程序设计语言。了解得越多,我们便可以越多的发现它的优点,这会让我们更加喜欢这种程序设计语言。
  • 不仅仅是运用 Ruby,我们更要了解 Ruby 语言的实现,甚至是更为通用的是动态语言实现机制。对于语言实现的了解,将有助于我们写出更为高效的程序,对于动态语言尤其如此,不少看上去功能类似的做法,实际上却存在很大的差异。
  • XRuby 的目标运行平台是 JVM,所以,我们会得到与 JVM 打交道的机会,了解 JVM 可以帮助我们更好的理解 Java 代码的运行机制,写出更好的 Java 代码。
  • XRuby 是一个开源项目,所以,参与 XRuby 让我们有机会为开源做出自己的贡献,与天南海北的人协同开发,体会开源开发模式为我们带来的种种乐趣。
  • 最重要的是,XRuby 还是一个年轻的项目,这意味着参与其中的人将会获得更多的机会,和它共同成长。

Ruby 之父松本行弘经常将乐趣挂在嘴边,因为编程本来就该是一件充满乐趣的事。如果你对 XRuby 有兴趣,那不妨加入我们,和我们一起体验这份开发的乐趣,共同享用 JVM 上的 Ruby!

参考信息

作者简介

郑晔,ThoughtWorks 中国公司咨询师,开源项目 XRuby 核心成员,目前正致力于让 Ruby 更好地运行于 JVM 平台。他的 Blog 为: http://dreamhead.blogbus.com/

2007-10-11 03:162360
用户头像

发布了 22 篇内容, 共 14.9 次阅读, 收获喜欢 49 次。

关注

评论

发布
暂无评论
发现更多内容

业界首个!快手提出亿级别多模态短视频百科体系——快知Kuaipedia

Geek老T

短视频 快手 泛知识

云上创新!观测云携手阿里云日志服务 SLS,全面升级云上应用可观测性体验

观测云

docker-compose下的java应用启动顺序两部曲之一:问题分析

程序员欣宸

Java Docker Docker-compose 11月月更

万字详解JVM,让你一文吃透

华为云开发者联盟

开发 华为云 企业号十月 PK 榜

AI 模型编译器 MegCC 开源,解决推理引擎体积问题

MegEngineBot

深度学习 开源 MegEngine MegCC AI 模型编译器

2022年中国汽车OTA行业发展洞察

易观分析

汽车 OTA

SAP 电商云的 Spartacus Storefront 如何配置多个 JavaScript Application

汪子熙

angular SAP commerce 电商云 11月月更

React源码分析6-hooks源码

goClient1992

React

认证升级 | 秒云再次获评软件企业认证

MIAOYUN

双软认证 软件企业认证 软件产品认证

React面试:谈谈虚拟DOM,Diff算法与Key机制

beifeng1996

React

python中私有成员和公有成员

乔乔

11月月更

软件测试面试真题 |你用过哪些用例设计方法?

测试人

软件测试 面试题 测试用例

EMQ荣获“2022中国移动创客马拉松OneOS物联网专题赛”三等奖

EMQ映云科技

物联网 IoT emqx 云边协同 车路协同

京东云开发者|软件架构可视化及C4模型:架构设计不仅仅是UML

京东科技开发者

软件架构 架构设计 架构可视化 图形化编排 C4模型

react的jsx和React.createElement是什么关系?面试常问

beifeng1996

React

云栖大会,未来万物皆是计算机?

阿里云CloudImagine

阿里云 云栖大会

DevUI开源经验分享:从0到1开始运营你的开源项目

华为云开发者联盟

开源 华为云 企业号十月 PK 榜

react相关面试知识点总结

beifeng1996

React

京东云开发者|深入JDK中的Optional

京东科技开发者

jdk java8 NPE 空指针 Optional

高效数据通道支撑生产情况实时分析与可视化|工业4.0智慧工厂

EMQ映云科技

物联网 IoT 数据可视化 11月月更 云边协同

京东云开发者|深入JDK中的Optional

京东科技开发者

jdk java8 NPE 空指针 Optional

在Dubbo中,模板方法模式 用得真6

小小怪下士

Java 程序员 dubbo 阿里

专业移动办公解决方案!远程控制软件RayLink内测火热进行中!

RayLink远程工具

远程控制软件 远程办公软件 远控软件 远程桌面连接 RayLink

React源码分析7-state计算流程和优先级

goClient1992

React

HDC 2022精彩继续,多重亮点进来看!

HarmonyOS开发者

HarmonyOS

我把分布式音乐播放器适配了Stage模型

OpenHarmony开发者

OpenHarmony

谈谈企业级前端应用中客户端渲染和服务器端渲染的区别

汪子熙

前端开发 SSR SAP Spartacus 11月月更

代码质量与安全 | 想在发布竞赛中胜出?Sonar来帮你

龙智—DevSecOps解决方案

代码质量 代码安全

Databend 集群部署 | 新手篇(2)

Databend

开源

面试官最喜欢问的几个react相关问题

beifeng1996

React

云原生系列四:Yelp 如何在 Kubernetes 上运行 Kafka

叶秋学长

kafka Kubernetes 11月月更 Yelp

XRuby:享用JVM上的Ruby_Ruby_郑晔_InfoQ精选文章