三行まとめ
- JRuby 1.7.24 (Ruby 1.9.3相当) はAndroidから普通に使える
- JRuby 9.1.0.0 (Ruby 2.3相当) はOracle JDK固有のクラスを使っていてAndroidでは使えない
- JRuby on Androidに興味のある開発チームはいるようなので、しばらくすると使えるようにはなるかもしれない
解説
Re:VIEW のソースを直接レンダリングするAndroidアプリがあったら面白いかなと思い、かといってRe:VIEWをJavaで再実装するのも面倒なのでまずJRubyをAndroidで動かせるかどうか試してみました。といっても、すでにJRubyを処理系として使うRubotoというAndroid用フレームワークがあるので、ある程度は使えることが分かっていました。
このJRubyを試しているリポジトリは https://github.com/gfx/HelloJRuby にあります。
依存関係
まず依存は次のように指定するだけです。ただし、JRubyは9000系と1.7系があり、相当するRubyのバージョンが違います。
// JRuby 9000 (Ruby 2.x相当) dependencies { compile 'org.jruby:jruby:9.1.0.0' } // JRuby 1.7 (Ruby 1.9相当) dependencies { compile 'org.jruby:jruby:1.7.24' }
実行
JRuby wiki に簡単な使い方が書いてありるので、それにしたがってRubyスクリプトを評価するコードを書きます。JITを無効化するのを忘れないように。
from MainActivity.java:
Log.d(TAG, "Ruby starting"); // Rubyランタイムの設定 RubyInstanceConfig rubyInstanceConfig = new RubyInstanceConfig(); // JITはOFFにする rubyInstanceConfig.setCompileMode(RubyInstanceConfig.CompileMode.OFF); // Rubyラインタイムを生成する Ruby runtime = Ruby.newInstance(rubyInstanceConfig); Log.d(TAG, "Ruby instantiated (" + (System.currentTimeMillis() - t0) + "ms)"); // Rubyスクリプト。android.util.Log.d()を呼んだあと、BuildConfig.APPLICATION_IDを返す String script = "require 'java'\n"+ "Java::AndroidUtil::Log.d %Q{Ruby}, %Q{This is JRuby (Ruby #{RUBY_VERSION})}\n"+ "Java::ComGithubGfxAndroidHellojruby::BuildConfig::APPLICATION_ID"; // Rubyスクリプトを実行する IRubyObject result = runtime.evalScriptlet(script); Log.d(TAG, "Ruby evaluated (" + (System.currentTimeMillis() - t0) + "ms)"); TextView textView = (TextView) findViewById(R.id.text); assert textView != null; // RubyオブジェクトのもつJavaオブジェクトを取り出す textView.setText(result.toJava(String.class).toString());
さて、これをJRuby 9.1.0.0で動かすと、java.lang.invoke.SwitchPoint
が存在しないという実行時例外で落ちてしまいました。これはAndrodには実装されていないようです。そこで一旦JRubyのバージョンを1.7.24に落としてみると、無事に実行できました。
Re:VIEWの最小サポートバージョンがRuby 2.0 なので Ruby 2.2に相当するJRuby 9.1.0.0を使いたいところです。現在は実行できない以上、当初の目的であったRe:VIEWの実行はできませんね。残念…。