10 Hot Tips for JRuby

DZone 's Guide to

10 Hot Tips for JRuby

· Java Zone ·
Free Resource

Vladimir Sizikov graciously contributed these ten coding tips for JRuby, the JVM implementation of Ruby, to the DZone community.  Sizikov is a core contributor for the JRuby project.  He is a software engineer at Sun Microsystems, with more then 9 years of experience in conformance and compatibility testing for Java SE and Java ME platforms.  Vladimir is also an Engineering Lead for the ME Framework project.  

Here are his tips, which he collected over time.  They're mostly from the point of view of a support engineer while answering user questions and trying to solve their most frequest problems:

1. Command line switch -d is your (biggest) friend. Many, many times, it made it much easier to figure out the problem, when 'require' fails, or when you need to load some Java classes and all you get is a small exception trace.  jRuby -d enables full stack traces, with lots of extra data (java stack traces from jruby internals). Often that shows the root cause of the problem. So, this is the first thing to try when you have require/classloading problems and unclear why. (See also Tip #9, coming up with JRuby 1.5).

2. Platform detection. I've seen this question lots of times. Since in JRuby, RUBY_PLATFORM constant is always "java",  users are unclear how to detect the underlying platform. It is pretty straghtforward with rbconfig module, JRuby fully supports it:
   require 'rbconfig'
   Config::CONFIG['host_os'] # returns mswin32
on Windows, for example

There is plenty of additional info in Config::CONFIG, just print it out to see.

3. Proper OS/platform detection that works in various Ruby implemenations (including JRuby).  This is a very frequent issue, that bites JRuby users often. Typically, in MRI, in order to detect, say, Windows, the following code is used:

   RUBY_PLATFORM =~ /mswin/

That won't work on JRuby (remember, RUBY_PLATFORM in JRuby is always 'java')! The proper way is to use rbconfig module.  Please adjust your code and bring this to attention of authors of the gems/libs you're using. This simple thing plays serious role in reducing incompatibilities and bugs with JRuby (especially on Windows).  For more details, take a look here.

4. Detection if the current code is being run by JRuby. There are multiple ways of doing that.  Please refer to the following post.  I've seen cases #1 and #3 used most often. #1 is not really recommended, since the actual value of RUBY_PLATFORM is not really guaranteed to stay "java".  So #3 is the simplest and recommended approach. If defined, JRUBY_VERSION.  And #2 is the standard, cross-implementation way, since it can be used to perform similar checks against Rubinius, IronRuby, and MRI (albeit, MRI started to support this only from 1.9+).

5. Java Integration. This is probably the most frequent topic of discussions.  JRuby Wiki has a page devoted to it.  Also, for more intricate details, I always recommend looking into JRuby's Java integration specs, you'll get plenty of interesting and new things there.  For, example, you'd like to know how to convert Java array to Ruby.  Take a look in types/array_spec.rb, you'll see, for example:
   [true, false].to_java :boolean

And, if there's something that you'd like to see implemented in JRuby's Java integration layer, consider contributing the specs, that's the most useful way.

Did you know that JRuby now can call into native C functions easily, thanks to FFI?  See examples here.  In JRuby 1.5 things will get even better, we're be fully supporting Win32API library, win32/resolv and win32/registly. They all work on top of JRuby.  And thanks to ruby-ffi project, now there is great possibility to write cross-implementation gems/libraries that call into native layer, and they will work on both MRI and JRuby, and in any other Ruby implementation that is going to support ffi.

7. JRuby and newer rails/activerecord-jdbc. There's no longer a need to tweak database.yml with JRuby-specific info.  The database configuration stays exactly the same for MRI and JRuby.  All the users need to do now is invoke: jruby script/generate jdbc.  For more details, take a look and Nick Sieger's blog about it.  This is a new approach and users need to know about it and adjust their habits. 

*The final three tips are some hints for the upcoming JRuby 1.5 version*

8. [JRuby 1.5 level feature] Want to see how fast/slow JRuby loads gems/libs?  Try this:

jruby -b -J-Djruby.debug.loadService.timing=true -e "require 'rubygems'"

  You'll get the output like this:

#>jruby -b -J-Djruby.debug.loadService.timing=true script\server
-> builtin/core_ext/symbol
<- builtin/core_ext/symbol - 35ms
-> enumerator
<- enumerator - 6ms
-> D:/work/jruby-dev/rails/xxx/config/boot
-> rubygems
-> rubygems/defaults
<- rubygems/defaults - 5ms
-> thread
<- thread - 7ms
-> etc
<- etc - 5ms
-> rbconfig
<- rbconfig - 7ms
-> rubygems/exceptions
<- rubygems/exceptions - 5ms
-> rubygems/version
-> rubygems/requirement
<- rubygems/requirement - 6ms

9. [JRuby 1.5 level feature] Want to see what/where JRuby loads/requires the libraries, try out:

jruby -J-Djruby.debug.loadService=true -e "require 'yaml'"

You'll get the output like this:

jruby -J-Djruby.debug.loadService=true -e "require 'yaml'"

LoadService: trying builtinLib: builtin/core_ext/symbol.class
LoadService: trying builtinLib: builtin/core_ext/symbol.rb
LoadService: trying resourceFromLoadPath: D:/work/jruby-dev/jruby/lib/ruby/site_ruby/1.8/builtin/core_ext/symbol.class
LoadService: trying resourceFromLoadPath: D:/work/jruby-dev/jruby/lib/ruby/site_ruby/1.8/builtin/core_ext/symbol.rb
LoadService: trying resourceFromLoadPath: D:/work/jruby-dev/jruby/lib/ruby/site_ruby/shared/builtin/core_ext/symbol.class
LoadService: trying resourceFromLoadPath: D:/work/jruby-dev/jruby/lib/ruby/site_ruby/shared/builtin/core_ext/symbol.rb
LoadService: found: file:/D:/work/jruby-dev/jruby/lib/ruby/site_ruby/shared/builtin/core_ext/symbol.rb
LoadService: trying builtinLib: enumerator.class
LoadService: trying builtinLib: enumerator.rb
LoadService: trying resourceFromLoadPath: D:/work/jruby-dev/jruby/lib/ruby/site_ruby/1.8/enumerator.class
LoadService: trying resourceFromLoadPath: D:/work/jruby-dev/jruby/lib/ruby/site_ruby/1.8/enumerator.rb

10. [JRuby 1.5 level feature] Having any issues when launching JRuby on Windows? Try to run jruby.exe -Xtrace output.log.  And take a look at the extensive log output in output.log file.

And last, but not least, if you have any more questions, asking them over JRuby's mailing list
and/or over IRC is the fastest way to get the answers.  Filing JRuby bugs is also an important part of the process.

These tips were authored by Vladimir Sizikov.


Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}