- 浏览: 939886 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
hw7777777:
非常感谢作者提供这么好的工具,在使用的过程中遇到一些问题?1、 ...
基于java nio的memcached客户端——xmemcached -
SINCE1978:
多久过去了时间能抹平一切
无路用的人 -
fangruanyjq:
[img][/img]引用
用osworkflow写一个请假例子(提供代码下载) -
thinkingmysky:
楼主,你确定,java memached client能处理并 ...
memcached java client性能测试的几点疑问和说明 -
hellostory:
aaa5131421 写道07年2月hibernate已经出来 ...
dozer与BeanUtils
XRuby是什么?它是一个编译器。与其它编译器一样,它完成的工作是将一种格式的语言转换成另一种。与大多数编译器不同的是,它是将Ruby的代码(.rb)转换成Java的bytecode(.class)。
Xruby是一群中国开发者维护的项目,它的目的如上所述。它的主页是http://code.google.com/p/xruby/。与JRuby不同,JRuby一开始是想使用java写ruby解析器,性能上是个大问题,当然现在也走上了编译这条路。而XRuby是第一个实现这种想法的人。
我翻译下了《XRuby Hacking Guide》,这篇文章是XRuby的入门指南。
介绍
这篇文章是为了帮助用户/开发者理解xruby的内部结构而写的。
如何编译ruby?
怎么将ruby编译成java字节码呢?首先,你不必成为一名字节码方面的专家来考虑这个问题,Java的字节码是对原生机器语言的较高层次的抽象,非常类似于java源代码。你可以简化这个问题为:如何用java表示一段ruby程序?
这两门语言有很多的相同之处:ruby是一门OO语言,它有类、方法、变量等,java也是如此。这是否意味着我们可以将一个ruby类类比为java类,ruby方法作为java方法?可是,除了这些相同之处外,它们之间有足够的不同点让你打消这个主意:首先,ruby是一门动态类型语言,因此一个方法可以接受不同类型的参数,而在java中,参数类型是方法签名(signature)的一部分。其次,在ruby中,方法可以从一个类中动态地添加和移除;但是目前的JVM并不支持这样的行为。值的注意的上述的这些问题也许会在将来的JVM版本中解决,请参考Gilad Bracha's work at JSR 292.
第一个办法是我们自己维护一个类型系统,这正是xruby目前采用的办法(Ruby.net好像也是如此)。从JVM的角度看,一个ruby类只是一个Object,这个Object中包含着代表方法等的其他object。我们将在后面更多讨论这点。
另一个办法是动态地编译(ruby)源代码,在运行时获得类型信息,将源代码编译成高效的代码(字节码?)是可能的。(一些方法由于duct typeing的特性将被编译成好几个版本)
我们将比较这两个办法,
实例
通过一个例子来了解xruby:将上面的代码存为test.rb,使用xruby编译(下载的xruby解压后运行build.bat或者build.sh生成xruby-0.1.3.jar):<!---->def say_hello_three_times
3.times {puts 'hello'}
end
say_hello_three_times
可以看到生成了一个test.jar文件,执行下面的命令来运行这个程序:<!---->java -jar xruby-0.1.3.jar -c test.rb
<!---->java -jar test.jar
当然,你将看到下面的输出:
hello如果你查看test.jar文件,你将看到以下3个class文件:
hello
hello
这些class文件等价于下面这段java程序:
<!---->//test/main.class
public class main
implements RubyProgram
{
public main()
{
}
public static void main(String args[])
{
RubyRuntime.init(args);
(new main()).run();
RubyRuntime.fini();
}
public RubyValue run()
{
RubyRuntime.ObjectClass.defineMethod("say_hello_three_times", new say_hello_three_times._cls0());
return RubyRuntime.callMethod(ObjectFactory.topLevelSelfValue, null, null, "say_hello_three_times");
}
}
//say_hello_three_times$0.class
class say_hello_three_times$0 extends RubyMethod
{
protected RubyValue run(RubyValue rubyvalue, RubyArray arrayvalue, RubyBlock rubyblock)
{
return RubyRuntime.callPublicMethod(ObjectFactory.createFixnum(3), null, new BLOCK._cls1(), "times");
}
public say_hello_three_times$0()
{
super(0, false);
}
}
//test/BLOCK$1.class
class BLOCK$1 extends RubyBlock
{
protected RubyValue run(RubyValue rubyvalue, RubyArray arrayvalue)
{
RubyArray arrayvalue1 = new RubyArray(1);
arrayvalue1.add(ObjectFactory.createString("hello"));
return RubyRuntime.callMethod(rubyvalue, arrayvalue1, null, "puts");
}
public BLOCK$1()
{
super(0, false);
}
}
在main类中:首先在"Object"类中定义了一个私有的方法"say_hello_three_times",然后通过no parameter, no block和一个top level "self"作为接收者的方式调用这个方法。
"say_hello_three_times$0"类表示say_hello_three_times方法的实现(参考command模式)。在代码中,我们可以看到Fixnum"3"(接收者)调用了"timer"这个方法,仍然没有parameter,但是有一个block被传进去(方法)。
BLOCK$1类则表示传进"3.times"方法中的block,代码中是"puts 'hello'"的实现。
源码结构
- com.xruby.compiler.parser 提供了一个compiler前端(parser and tree parser)。 Parser转换ruby脚本成AST (Abstract Syntax Tree),然后 tree parser将AST转换为内部结构(internal structure)。
编译器前端使用 Antlr 作为语法分析器的生成器.实践证明,将这个前端分为两部分可以带来好处:parser 和 tree parser;其中 parser 解析脚本,而tree parser生成内部结构(internal structure)。 - com.xruby.compiler.codedom 定义了描述ruby脚本结构的内部结构(internal structure)。内部结构作为前端和后端的接口,对于xruby是非常重要的。
- com.xruby.compiler.codegen 实现了编译器的后端(代码生成)。后端将前端生成的内部结构转换为java字节码。代码生成是通过ASM实现的,ASM简化了对字节码的操作。
- com.xruby.runtime 实现了xruby运行时(runtime),它维护着运行ruby脚本必需的类型系统, com.xruby.runtime.lang 描述了ruby类型的运行时结构,一些ruby内建标准库实现在 com.xruby.runtime.builtin.
内建库
通往xuby hacking之路最简便的办法就是学习 'com.xruby.runtime.builtin'包的源代码。
下面是来自Fixnum::+方法实现的代码片段:
<!---->class Fixnum_operator_plus extends RubyMethod {
public Fixnum_operator_plus() {
super(1);
}
protected RubyValue run(RubyValue receiver, RubyArray args, RubyBlock block) {
RubyFixnum value1 = (RubyFixnum)receiver.getValue();
RubyFixnum value2 = (RubyFixnum)args.get(0).getValue();
return ObjectFactory.createFixnum(value1.intValue() + value2.intValue());
}
}
RubyClass c = RubyRuntime.GlobalScope.defineNewClass("Fixnum", RubyRuntime.IntegerClass);
c.defineMethod("+", new Fixnum_operator_plus());
XRuby的语法解析器
Xruby的解析器使用 Antlr 作为解析器的生成器。 这是目前相比于c ruby唯一另类的ruby语法。
对于大部分编程语言来说,词法分析(lexing)和语法解析是两个不同的步骤:首先词法分析器将输入的字符组织成单词(token),然后解析器将单词组织成句法单元。但是在ruby(和perl语言)中,词法分析器和语法解析器是紧紧地耦合在一起的:有时候词法分析器需要从语法分析器中获取上下文信息。
疑难解决
作为Xruby的开发者,我们的任何改变都可能导致编译器出错并且生成有问题的字节码。当这种情况发生时,我们可以依赖3样工具:javap,ASM和你所喜欢的java反编译器(比如jad)
如果生成的class文件格式正确但是运行结果不是预期的,我们可以简单地使用反编译工具将字节码转换成可读的java源代码,以便查找错误。
如果你遇到是一个verifier error,大部分的反编译器都不能正常工作(jad在这种情况也许会crash掉)。我们不得不使用javap来研读字节码。多数情况下,JVM class验证器(verifier)给出的信息没什么用处,但是我们可以通过ASM更快地找到错误发生点。(see ASM FAQ: Why do I get the [xxx] verifier error?).
发表评论
-
使用Ruby amb解决说谎者谜题
2008-11-15 18:50 1602说谎者谜题是sicp4.3.2小节的一道题目,题目本身 ... -
swfheader 0.10 Released
2008-10-11 23:41 1520swfheader是一个处理swf文件的工具脚本,可用 ... -
Ruby 1.9概要(1)新的语法和语义
2008-10-01 13:37 1805一、新的语法和语义 1、新的Hash定义语法: 例如{a:2 ... -
Ruby 1.9概要(2)Kernel和Object
2008-10-01 13:48 1398二、Kernel 和 Object 1、引 ... -
Ruby 1.9概要(3)类和模块
2008-10-01 13:52 1404三、类和模块 1、Module#instance_method ... -
Ruby 1.9概要(4) Block和Proc
2008-10-02 13:54 13441、Proc加了新方法Proc#yield ,这只是Proc# ... -
Ruby 1.9概要(5) 异常
2008-10-03 13:26 13301、异常的相等性 ,如果两个异常的class、message和 ... -
Ruby Tip——读文件
2008-10-07 09:38 1834Ruby如何简洁地读整个文件,你可以这样做: f = Fil ... -
Ruby写Servlet的小例子
2008-07-23 12:05 2397Ruby也能写servlet?是的,没开玩笑,而且挺 ... -
JRuby中调用java带可变参数的方法
2008-06-14 22:41 1281今天同事遇到的问题,用JRuby调用一个java方 ... -
Ruby中实现stream
2008-05-08 22:36 1316流是通过延时求值实现的,Ruby中实现stream也 ... -
lua 5.0的实现(翻译)1,2,3部分
2008-04-07 17:28 3945三个多月前翻译的,今天又找出来看看,后面的整理再发。 原文: ... -
Ruby代码调整性能优化的几个Tip
2008-03-27 09:49 2184数据都是在我的 ... -
使用JProfiler监控JRuby脚本的运行
2008-03-24 15:32 1581jruby本质上也是启动一个jvm,然后去读Ru ... -
发布swf-util 0.01
2008-03-11 14:49 1812swf-util是一个使用Ruby读取swf头信息(高度、宽度 ... -
用Ruby写个NFA
2008-02-25 17:49 2881今天有点空闲,想想用Ruby写个NFA试试。从正则表达 ... -
Ruby小技巧:处理方法调用中的nil
2008-02-19 13:41 3727读blog看到的一个小技巧,原文在这里。 我们 ... -
expectations——轻量级的单元测试框架
2008-02-16 10:05 1706项目主页:http://expectations.rubyfo ... -
JRuby中使用接口和抽象类
2008-02-15 14:36 1704要在JRuby中实现java接口,接口include进 ... -
google translator 0.2
2008-02-14 11:17 1905过去写的那个利用google在线翻译的小脚本工具一 直 ...
相关推荐
标题“5xruby”可能指的是一个与Ruby编程语言相关的项目或者教程,可能是为了介绍或教授如何使用Ruby进行五倍速(高效)的编程。描述中同样提到“5xruby”,但没有提供具体的信息,可能是因为它是项目的简短命名,...
开发指南 软件依赖项 (OS X) $ brew install postgres redis imagemagick pkg-config 设置 $ bundle install $ cp config/application.yml.example config/application.yml $ cp config/database.yml.example ...
本地安装要求Linux,Unix,Windows或Mac OS XRuby在Unix上安装ruby: yum install ruby (或sudo apt-get install ruby1.9.1 )在Mac OS X上安装ruby: curl -L https://get.rvm.io | bash -s stable --ruby 请访问...
dotjs 是一个谷歌扩展,它可根据文件名 ~/.js 来执行 JavaScript ... 而这将会使你很方便地使用 JavaScript 去改进你所喜爱的页面要求OS XRuby 1.8rake (gem install rake)Google Chrome/usr/local/bin in your $PATH
做电影Curso Ruby on Rails 5.x-执行本操作安比恩特RVMListar todas无React,无争议$ rvm list known列表$ rvm get headLista作为本地安装人员$ rvm listInstala umaversãoescolhida $ rvm install x.x.x.xRuby,...
要求Ruby 2.6.3 导轨5.2.3 PostgreSQL 9.4.4安装 $ git clone git@github.com:5xruby/daikichi.git$ cd daikichi# generate key with rake secret$ cp config/secrets.yml.sample config/secrets.yml$ cp config/...