JRuby
From JVMLanguages
JRuby is an interpreter for the Ruby programming language written in Java. Although the semantics of Ruby and Java are very different, JRuby is quite good for integrating the two languages.
| Table of contents |
JRuby in the News
- September 7, 2006: Sun "acquires" JRuby and hires two key JRuby developers, Charles Nutter (http://headius.blogspot.com) and Thomas Enebo (http://bloglines.com/blog/ThomasEEnebo).
How to use JRuby
Invoking JRuby
JRuby includes a main class org.jruby.Main which can read a script off of the command-line arguments and invoke it. If no script is provided, JRuby will read the entire stream from standard input and then execute it. Unlike most other command-line interpreters, it does not evaluate it statement-by-statement.
$ java org.jruby.Main print "the answer is: " a = 2 + 2 print a.to_s, "\n" ^D the answer is: 4
If you provide a script, any arguments that follow the script will be appended to ARGV.
$ cat print_sum.rb
sum = 0
ARGV.each { |x| sum += x }
print sum.to_s, "\n"
$ java org.jruby.Main print_sum.rb 2 2
4
JRuby assumes the several Java system properties are set. This includes:
- jruby.base
- jruby.home
- jruby.lib
- jruby.shell
- jruby.script
You can also invoke Ruby programmatically by obtaining an instance of org.jruby.Ruby.
import org.jruby.*;
public long doMath ()
{
Ruby ruby = Ruby.getDefaultInstance();
ruby.defineReadonlyVariable("a", new RubyFixnum(ruby, 2));
RubyFixnum out = (RubyFixnum)ruby.evalScript("a + 2");
return out.getLongValue();
}
Using Existing Ruby Libraries
JRuby is only distributed with its own Ruby libraries, which are used for integration with Java. The core Ruby libraries such as XXXX are not included and must be downloaded separately from a typical Ruby installation.
Interacting with Java Objects from Ruby
Java objects are represented inside of Ruby as an instance of the JavaObject class, which has methods that can be used to locate its Java class (JavaClass) and look up methods and fields via a reflection-like API.
However, in most cases there is no need to interact with JavaObjects directly -- JRuby can also create proxies around these JavaObjects that make them look like ordinary Ruby objects. This means that you can call methods on them directly. Calling a method on a Ruby proxy that returns another Java object will also automatically wrap that object in a proxy.
public class MyJavaClass {
public MyOtherJavaCLass a () {
return new MyOtherJavaClass();
}
}
public class MyOtherJavaClass {
public int b () {
return 42;
}
}
class MyRubyClass
def myMethod (myJavaObject)
print "a.b = ", myJavaObject.a.b.to_s, "\n"
end
end
Ruby also supports proxies for Java classes, which expose static methods and constructors as if they were normal operations in Ruby. This is usually done through the include_package statement in Ruby, which creates proxies for all Java classes within that package.
The JavaBean standard dictates that nearly all Java objects have private fields and public accessor and mutator methods which named get* and set*, respectively. Ruby's coding style, on the other hand, generally leaves off the prefixes and instead uses the presence of a = suffix to indicate a mutator method. This convention is enforced by the language itself, which has syntactic sugar that makes a.b = 42; equal to a.b=(42);. Similarly, boolean accessor methods in Java are often prefixed with the word is, where boolean accessors in Ruby are conventionally suffixed with a question mark (?).
To ease the integration between Ruby and Java code, JRuby added support for mapping between these conventions and creating aliases on the Ruby proxies that follow the Ruby codingconventions. Thus the Java method Foo.getBar() can be called from Ruby either by foo.getBar() or by foo.bar. 2.4. Interacting with Ruby Objects from Java
Ruby has support for generating Java proxies from Ruby objects, however it is up to the caller to define the mapping between Java interfaces and Ruby classes.
BSF Support
The JRuby distribution contains a BSFEngine implementation called org.jruby.javasupport.bsf.JRubyEngine. However, the Languages.properties file included with BSF has this engine registered, so you will not need to register it explicitly. Simply use the language name ruby and the extension .rb.
Ruby's BSFEngine is responsible for converting all data types between Ruby's data types (RubyFixnum, RubyString, etc.) to Java's data types (Integer, Long, String, etc.). It does this conversion in both directions, for input parameters as well as return values.
Limitations
In the case of JRuby, we have a milestone against which we can measure its functionality. In fact, Ruby has a general conformance test called Rubicon that is designed to test all of the functionality that Ruby supports. According to the JRuby web site, 651 of the 933 (70%) Rubicon tests pass for 0.7.0. Is this still the most recent?
Articles
- alt.lang.jre: Take a shine to JRuby (http://www.ibm.com/developerworks/library-combined/j-alj09084/)

