Blog

5 Things to Look for in JRuby 1.4

By | September 21st, 2009 at 10:09AM

The team has finally wrapped up the long summer of JRuby-related travel, and it’s time to set our sights on a new version of JRuby for the community to lovingly embrace.

The release itself is tentatively planned to enter a round of release candidates at the end of September. Please prepare yourselves, try the release candidates when they are available, and most importantly, report bugs!

So what can you expect in the next release, other than the usual array of bug, performance, and compatibility fixes? Here are the five areas where we’ve been focusing efforts.

1. 1.8.7 is the New Baseline

When Ruby 1.8.7 was first released, we had a false start where we eagerly started to add some of the new additions, only to find that Rails (version 2.0 at the time) was rendered useless by the changes. Now, finally, three minor releases of Rails 2.x later, Rails on Ruby 1.8.7 has finally stabilized, and is now the recommended version of Ruby to use with Rails. Additionally, 1.8.7 is showing up as the default version of Ruby in many operating systems, and we began to see more bug reports about missing 1.8.7 features.

So, in JRuby 1.4, we’ll finally report compatibility with Ruby 1.8.7p174:

$ jruby -v
jruby 1.4.0dev (ruby 1.8.7p174) (2009-09-14 b09f382) (Java HotSpot(TM) Client VM 1.5.0_19) [i386-java]

The patch-level (p174) is based on the version of Ruby where we pulled the updated standard library. We always maintain that patch-level is a “best effort” number, and as such, we cannot promise full feature-for-feature (or bug-for-bug!) compatibility. However, as the RubySpec project has matured, it’s gotten much easier for us to feel confident about this claim. As always, if you spot an area where we differ from Ruby 1.8.7, please do file a bug on the discrepancy, or even better, make sure that RubySpec covers the issue by submitting a patch to RubySpec.

2. Improving 1.9 Compatibility

Even though Ruby 1.9 is still a moving target, the RubySpec project has recently begun to cover many of the new 1.9 features, which gives JRuby an easier, more robust mechanism for tracking how far along the path to 1.9 we are.

We’ve also been following our tried-and-true approach of just trying to get stuff working. In particular, IRB, RubyGems, Rake, and even some simple Rails applications are working with JRuby in 1.9 mode.

Other than a couple of major new features remaining (Multilingualization/encoding, IO transcoding, Fibers), JRuby 1.9 mode should just work. To try out JRuby in 1.9 mode, just pass --1.9 as a leading argument on the command-line:

$ jruby --1.9 -v
jruby 1.4.0dev (ruby 1.9.1p0) (2009-09-14 b09f382) (Java HotSpot(TM) Client VM 1.5.0_19) [i386-java]

If you’ve been writing 1.9 code, we’d love to hear if you can get it working on JRuby: do comment!

3. New YAML Parser

Ok, so a new YAML parser is something you’d probably have to give more than a cursory glance to notice. But our good friend Ola Bini has gone and done it again with Yecht, a new YAML engine. Ola re-implemented YAML support in JRuby to be much closer to the idiosyncracies of Syck, the C YAML parser that MRI uses. With this change, a number of long-standing YAML compatibility issues are fixed. Hopefully this is the last YAML engine that JRuby will ever need!

4. Java Method Selection and Coercion API

For a long time, JRuby Java integration features have been something of a black box, especially the way Java methods are selected and invoked and arguments are coerced. This black box has hindered understanding of how JRuby calls Java, and in the case of overloaded methods, has made some Java methods unreachable. Consider this Java class:

public class Overloaded {
    public static void use(int i) { /* ... */ }
    public static void use(long l) { /* ... */ }
}

And this JRuby code:

Java::Overloaded.use 10

Which Overloaded method is called? It turns out it’s use(long). JRuby behavior is to coerce Ruby Fixnums into Java longs. Thus, with current versions of JRuby, it’s impossible to call the version that takes an int.

We’d like to make this part of the Java integration layer more transparent and accessible. Here are a few APIs we’re considering:

a. Object#java_send(name, signature, *args)

Like Object#send except it would allow you to identify and invoke a specific Java method by its name and signature. A signature for these purposes is an array of classes, where the first element in the array specifies the return type.

b. Object#java_method(name, signature)

Like Object#method, except it would take an array of Java classes representing a method signature as an additional argument and return a Method object that can be #call‘ed.

c. #coerce_to?(type)

Method convention to allow an object to decide whether it can be coerced to a Java type. JRuby will call this method if it’s available to get hints to aid in choosing a method in the presence of several overloaded methods.

d. #to_java(type)

Method convention to allow arbitrary Ruby objects to control how they are coerced to Java. If a Ruby object responds to #to_java, JRuby will use it to convert the argument before passing to a Java method invocation.

e. #to_ruby(type)

Like #to_java except to be applied to return types and Java objects coming back to Ruby.

All of these APIs are still yet to be implemented, and we could use some good real-world examples of where JRuby falls down to help ensure that we solve those issues.

5. Generate Real Java Classes from Ruby

Since we started writing Ruby2java as an add-on library, we’ve been looking for a way to expose the functionality of creating a real Java class from Ruby in the JRuby core. JRuby 1.4 will have some new experimental APIs for doing this. The example below explains it in code:

require 'java'
require 'jruby/core_ext'

class SimpleTest
  def equals
    raise "not equal" unless 1.0 == 1
  end
end

SimpleTest.add_method_signature("equals", [java.lang.Void::TYPE])
SimpleTest.add_method_annotation("equals", org.junit.Test => {})
SimpleTest.become_java!

The effect of this code is the same as writing the following Java code:

package ruby;
import org.junit.Test;
public class SimpleTest {
    @Test
    public void equals() {
        // dispatch back to Ruby code here
    }
}

We are also providing #add_class_annotation and #add_parameter_annotation methods as well, rounding out the ability to shape a real Java class.

These APIs are admittedly verbose and low-level, but they do allow you to easily build higher level constructs using Ruby metaprogramming techniques.

Here’s a more realistic example of implementing a JAX-RS/Jersey resource using Ruby (full source available):

class Hello < RubyJersey::Resource
  GET()
  Produces("text/plain")
  Returns(java.lang.String)
  def hello
    "Hello Ruby Jersey!"
  end
end

Feedback

The release is still a couple of weeks away, so none of this is by any means final. Please send us feedback by commenting here or use the JRuby mailing list for longer discussions, and let us know how the 1.4 release candidates work for you!

  • kevwil

    Is there a time frame for getting the 1.9 support up to the current patch level, in the same way the 1.8.7 spec is coming into line with that latest patch level? I see 1.9.1p0 and I'm pretty sure that's already out of date.

    Thanks for the great work on JRuby – we might FINALLY be allowed to code in Ruby at work due to JRuby's awesomeness.

  • AkitaOnRails

    I know that you're always striving to achieve better performance in every new release. Any new optimizations in this release? Would be great to hear some comparisons between jRuby 1.3 and 1.4. And congrats, as usual a great work.

  • http://intensedebate.com/people/nicksieger nicksieger

    You're right, patch level 0 doesn't say much about the level of JRuby's 1.9 support. This is complicated by 2 reasons: 1) JRuby's own support is still missing a couple major features as mentioned; 2) 1.9 itself isn't fully baked.

    Regarding 2), the RubySpec project has been targeting 1.9.2, and JRuby follows that as a result. Since 1.9.2 is still in preview releases, there is no publicly-known patch level to use anyway. If you think we should display something other than "0", please let us know.

  • http://intensedebate.com/people/nicksieger nicksieger

    While performance was not a major theme for this release, there's a smorgasbord of lower-level things that may help certain applications. Things like numeric operations in the interpreter, some improvements to Fixnum math operations, and reducing the bytecode limit for JIT'ted methods so that we won't attempt to compile methods that are too big, thus wasting less time during compilation.

    Thanks for the suggestion for a comparison between 1.3 and 1.4. We'll try to have some numbers to show closer to release time.

  • http://thinkincode.net David Calavera

    Some days ago I wrote a little script to help me to run ruby specs to check ruby 1.9 compatibility. I know it's not perfect but it's useful for me and perhaps for you as well, you can take a look at here:

    http://gist.github.com/190948
    http://thinkincode.net/2009/9/22/improving-jruby-…

  • Knodi

    Is fork support in 1.4?

  • http://intensedebate.com/people/nicksieger nicksieger

    No, we haven't done anything new with fork. We still have the experimental support by setting -J-Djruby.fork.enabled=true, but I've only seen it work in simple cases.

  • Knodi

    Thx for the quick reply.
    I tried experimental support for it in 1.3.1 but hasn't worked out to well for me.

    Thx again.

  • http://presidentbeef.com Justin

    How easy/difficult would it be to get gdbm working? Would using the JRuby FFI be the way to go?

  • http://intensedebate.com/people/nicksieger nicksieger

    Yeah, looks like FFI would be your best bet. The C gdbm extension is mostly just wiring the underlying APIs into Ruby, and it's only 1300 lines of C code :). Sounds like a nice side project. If you decide to port it, let us know so we can consider including it in JRuby core (since gdbm is usually distributed with Ruby).

  • http://presidentbeef.com Justin

    I think that's just what I will do. Thanks.

  • Jason

    Does anyone know if we jRuby allows you upload rails apps as bytecode?

  • Chisa

    I've just translate in Japanese!
    http://blog.chaaasan.com/archives/51267492.html

  • http://presidentbeef.com Justin

    Alright, it is available at http://github.com/presidentbeef/ffi-gdbm