So recently at work we finally decided (after some prodding from me) to go with JRuby for a new production system.
I had no real experience with JRuby other than looking at some documentation and playing with it for five minutes, so here’s some JRuby-related topics I bumped into and I’ve been wanting to write about.
start-up time during development
Since the system hasn’t yet been deployed, I don’t have deployment stories to share, but for development I have some tips:
Do define the magic
--devdefault option in your local development environment!
With this flag active, JRuby optimizes for startup time, so your fast
pryusage stops being painful.
(Of course, do note that steady-state performance will drop, so don’t use this for long-running code.)
Use binaries directly (or with
jruby -S) rather than with
bundle execwhenever possible. On my machine running
jruby -S rspecinstead of
bundle exec rspecslices start-up time in about half.
These tips are documented in the JRuby wiki but I can’t stress enough the difference they make between JRuby being painful and a pleasure to use during development.
easy interop with java code
Don’t abuse it, but I must say it’s really easy to call Java code:
 pry(main)> require 'java' => false  pry(main)> l = java.util.ArrayList.new() => #<Java::JavaUtil::ArrayList:0x7c24b813>  pry(main)> l.add(:foo) => true  pry(main)> l.add(:bar) => true  pry(main)> l.to_string => "[foo, bar]"
bonus: warbler and the magical jar
While you can use
bundler and many of the same techniques and platforms you are used to with mri (such as the puma webserver), an interesting tool I’ve recently discovered that is also developed by the JRuby team is
Warbler allows you to package a ruby application as a single jar or war file, that can be executed like any other java code standalone or (if applicable) on an application server. If needed, it can even bundle in a Java webserver that will call your ruby code.
Turning a simple ruby script into an inconspicuous jar is as simple as:
$ gem install warbler Fetching: jruby-jars-126.96.36.199.gem (100%) Successfully installed jruby-jars-188.8.131.52 Fetching: jruby-rack-1.1.20.gem (100%) Successfully installed jruby-rack-1.1.20 Fetching: rubyzip-1.2.0.gem (100%) Successfully installed rubyzip-1.2.0 Fetching: warbler-2.0.3.gem (100%) Successfully installed warbler-2.0.3 Parsing documentation for jruby-jars-184.108.40.206 Installing ri documentation for jruby-jars-220.127.116.11 Parsing documentation for jruby-rack-1.1.20 Installing ri documentation for jruby-rack-1.1.20 Parsing documentation for rubyzip-1.2.0 Installing ri documentation for rubyzip-1.2.0 Parsing documentation for warbler-2.0.3 Installing ri documentation for warbler-2.0.3 Done installing documentation for jruby-jars, jruby-rack, rubyzip, warbler after 1 seconds 4 gems installed $ cat bin/test.rb puts "hello, world!" $ cat config/warble.rb Warbler::Config.new do |config| config.features = %w(executable) config.jar_name = "test" end $ warble jar rm -f test.jar Creating test.jar $ java -jar test.jar hello, world!
And that’s all there is to it, and you now have a single jar that anyone will be able to easily run on their local machine.
Big kudos to the JRuby team for this one!
dealing with java jar dependencies
So one of my colleagues asked: what about jars? Do you have to break out
maven? How does that work?
The answer turns out to be no, you can just use
jbundler to do that work for you. It looks and feels like bundler, and you feed it with a
Jarfile and magic happens.
Of course, approach this with care, as when you start depending on Java code you cannot go back to MRI or other ruby implementations.
a shout out to jruby+truffle
I’m really looking forward to what I believe is the next big thing in the ruby implementation arena: JRuby+Truffle.
Its name can be somewhat misleading, as it’s a very different beast from vanilla JRuby. JRuby+Truffle instead uses a self-optimizing AST interpreter that basically teaches the JVM (via the truffle api and the graal compiler) how ruby works and how to optimize its execution.
The resulting benchmarks are looking very good, although a few sharp edges still stand before it can really be rolled out to production.
Chris Seaton, its creator, gave an awesome talk about it recently at VMSS16, which I really recommend watching:
P.s.: There are a lot of other great talks from that event, such as Cliff Click’s.
crystal, I am disappoint
As a shared-memory concurrency junkie, it really seems weird to have a new language being created that doesn’t properly consider concurrency. Hopefully in the future this will be fixed, but until then, it seems like JRuby and Elixir are where the parallel party’s at!