Two weeks ago, JRuby 1.7.0 was officially released. Here are a few reasons why you might want to upgrade:
JRuby 1.7.0 fixes many compatibility issues with ruby 1.9. Also, JRuby 1.6.8 is no longer being maintained so fixes from 1.7.0 are not getting backported.
Support for invokedynamic
JRuby 1.7.0 supports the invokedynamic instruction, a new feature in Java 7 which allows the compiler to use duck typing. This means dynamic languages on the JVM will be compiled to faster code.
JRuby 1.7.0’s exec function is now a true system exec that replaces the current process, while previously it spawned a new process and waited until the process exited.
I just upgraded my project from 1.6.8 to 1.7.0. It was fairly easy – I took about a day to upgrade our project.
- Install JRuby 1.7.0
It’s as simple as:
$ rbenv install jruby-1.7.0
If ruby-build complains that definition not found, you’ll need to upgrade ruby-build.
Note that if you’re using ruby 1.8.7, you’ll need to install that separately since JRuby 1.7.0 by default uses ruby 1.9.3.
Drop the new version into your project .rbenv-version file.
Some gems may fail to install because JRuby 1.7.0 by default doesn’t enable C extensions since they are deprecating this feature. You can turn it back on with the command line option
-Xcext.enabled=true– add this to your .rbenv-vars file.
$ rake spec
If you’re lucky, everything will pass and you can skip straight to step 4.
Otherwise, here’s a list of the changes I made to port our project over. This is by no means an exhaustive list, so please feel free to comment below.
An interesting change in JRuby 1.7.0 is that Java exceptions no longer inherit from ruby Exception. This means that they will not be caught by a standard global rescue. I.e., executing the code below will print ‘Rescued’ under 1.6.8 but will blow up under 1.7.0.
begin java.lang.Integer.parse_int("asdf") rescue puts "Rescued" end
If you’re doing a global rescue from Java code, you’ll need to change your code to specifically catch a Java exception class or explicitly rescue Exception (at your own risk).
- Another change is the behavior of Kernel#exec, which unexpectedly broke one of our dependencies with an unhelpful error message
Error: Unable to access jarfile start.jar. In our case, the fix was to change the
Once we finished tweaking it, our application loaded and behaved normally.
You may want to experiment with enabling invokedynamic. It’s turned off by default because some versions of the JDK 7.0 are not fully compatible. To enable it, add
-Xcompile.invokedynamic=true into your .rbenv-vars file.
Unfortunately, on my project, we’re sticking with Java 6 due to our dependencies, so no invokedynamic for us – but let me know how that works out if you try it.