JRuby JRuby 到底是不是直接编译成 Java 字节码的?

zsdz · 2014年08月21日 · 最后由 douxiance 回复于 2015年08月20日 · 9750 次阅读

翻了翻 jruby 的代码,本来以为是将 ruby 代码翻译成 java 字节码的,但好像他是用 java 写了 个解释器来解释 ruby 代码,相当于 jruby 只是一种 java 的嵌入语言。生成的 java 文件是把 ruby 源代码当成字符串读取,再用这个解释器去执行

相当于没有直接用 java 虚拟机来作为底层,只是用 java 写了个解释器

比如用 jrubyc 生成的 class,反编译结果如下:

import org.jruby.Ruby;
import org.jruby.RubyObject;
import org.jruby.javasupport.util.RuntimeHelpers;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.javasupport.JavaUtil;
import org.jruby.RubyClass;


public class Foo extends RubyObject  {
    private static final Ruby __ruby__ = Ruby.getGlobalRuntime();
    private static final RubyClass __metaclass__;

    static {
        String source = new StringBuilder("class Foo\n" +
            "   def bar(a, b)\n" +
            "     puts a + b\n" +
            "   end\n" +
            "\n" +
            "a=Foo.new\n" +
            "a.bar(1,2)\n" +
            "").toString();
        __ruby__.executeScript(source, "a.rb");
        RubyClass metaclass = __ruby__.getClass("Foo");
        metaclass.setRubyStaticAllocator(Foo.class);
        if (metaclass == null) throw new NoClassDefFoundError("Could not load
Ruby class: Foo");
        __metaclass__ = metaclass;
    }

    /**
     * Standard Ruby object constructor, for construction-from-Ruby purposes.
     * Generally not for user consumption.
     *
     * @param ruby The JRuby instance this object will belong to
     * @param metaclass The RubyClass representing the Ruby class of this object
     */
    private Foo(Ruby ruby, RubyClass metaclass) {
        super(ruby, metaclass);

    /**
     * A static method used by JRuby for allocating instances of this object
     * from Ruby. Generally not for user comsumption.
     *
     * @param ruby The JRuby instance this object will belong to
     * @param metaclass The RubyClass representing the Ruby class of this object
     */
    public static IRubyObject __allocate__(Ruby ruby, RubyClass metaClass) {
        return new Foo(ruby, metaClass);
    }

    /**
     * Default constructor. Invokes this(Ruby, RubyClass) with the
classloader-static
     * Ruby and RubyClass instances assocated with this class, and then invokes
the
     * no-argument 'initialize' method in Ruby.
     *
     * @param ruby The JRuby instance this object will belong to
     * @param metaclass The RubyClass representing the Ruby class of this object
    public Foo() {
        this(__ruby__, __metaclass__);
        RuntimeHelpers.invoke(__ruby__.getCurrentContext(), this, "initialize");
    }


    public Object bar(Object a, Object b) {
        IRubyObject ruby_a = JavaUtil.convertJavaToRuby(__ruby__, a);
        IRubyObject ruby_b = JavaUtil.convertJavaToRuby(__ruby__, b);
        IRubyObject ruby_result =
RuntimeHelpers.invoke(__ruby__.getCurrentContext(), this, "bar", ruby_a, ruby_b)
;
        return (Object)ruby_result.toJava(Object.class);

    }

}

到 java 字节码还是有难度的

2 楼 已删除

__ruby__.executeScript() 里面解释执行最顶层的代码, 顺带编译 def 的内容 (其实和 java 的执行很相似, main 顶层是解释执行的, 再下去才是编译执行).

ruby 的 wire format 是源代码, 而 java 的 wire format 是 class 文件, jrubyc 的作用是把 .rb 包装成 .class 而已

#3 楼 @luikore 那就是还是能把 rb 代码真正的编译成 java 字节码?我咋觉得不能呢

#4 楼 @zsdz

jruby 还创造了一套写 jvm 字节码的 dsl (https://github.com/headius/bitescript), 用 jruby 直接写 class 比好多工具例如 asm 都好使...

很多比较静态的 ruby 代码都是一一对应翻译成 jvm 字节码的, 看代码就知道了, 例如这里:

https://github.com/jruby/jruby/blob/master/core/src/main/java/org/jruby/compiler/impl/MethodBodyCompiler.java

优势呢?

需要 登录 后方可回复, 如果你还没有账号请 注册新账号