Getting Started With JRuby
Preface
I'm trying to do some integrations with jruby and java. I encountered some problems, and found that there were only a few information about jruby. So I write down my experience and share it.
Install JRuby
Environment: Mac, rvm
rvm get head
rvm install jruby-9.0.4.0
in your project folder, run
rvm use jruby-9.0.4.0
or create a .ruby-version
file
echo 'jruby-9.0.4.0' > .ruby-version
Calling Java
create a folder named getting-started-with-jruby
, you can find the code in Github
quick start
create a Hello.java
public class Hello {
public static void world(){
System.out.println("Hello JRuby!");
}
}
compile it with javac Hello.java
require 'java'
will give you access to any bundled Java libraries (classes within your java class path)
then we create a calling-class-in-root.rb
require 'java'
Java::Hello.world()
run ruby calling-class-in-root.rb
in termial, and you will see the output. Hello JRuby!
classpath
Everything in the Ruby load path is considered to be a classpath entry, so .class files under load path hierarchies are automatically available to be referenced from code.
The classpath is typically set up through the CLASSPATH environment variable or passed to the java command using -cp or -classpath with a delimited list of filesystem locations.
We can add classpath
$CLASSPATH << "classes"
# or $CLASSPATH << "file:///#{File.expand_path('classes')}/"
we create a java file java/src/main/java/SubHello.java
, and compile the java file.
create calling-class-in-sub-folder.rb
in project root.
require 'java'
$CLASSPATH << "java/src/main/java"
Java::SubHello.world()
run ruby calling-class-in-sub-folder.rb
in termial, and you will see the output. Hello jruby in sub folder!
import jar file
require 'path/to/mycode.jar'
create a pom.xml
in java
folder, run mvn package
and we get demo-1.0.jar
create calling-jar.rb
in project root,
require 'java'
require './java/target/demo-1.0.jar'
Java::SubHello.world()
run ruby calling-jar.rb
in termial, and you will see the output. Hello jruby in sub folder!
jbundler
install JBundler with
gem install jbundler
create a Jarfile, something like:
jar 'commons-io:commons-io', '2.4'
run jbundle install
in terminal
require 'jbundler'
will give you access to Java libraries announced in Jarfile
create calling-jar-with-jbundler.rb
require 'java'
require 'jbundler'
file = java.io.File.new('./Jarfile')
lines = org.apache.commons.io.FileUtils.readLines(file, "UTF-8")
puts lines
we will see the output [jar 'commons-io:commons-io', '2.4']
we can also calling java in caml style, and get the same result
require 'java'
require 'jbundler'
file = Java::JavaIo::File.new('./Jarfile')
lines = Java::OrgApacheCommonsIo::FileUtils.readLines(file, "UTF-8")
puts lines
Speedup initialization
JRuby initialization is much more slower than MRI Ruby, and we will speedup it.
–dev flag
Use the "–dev" flag, this enables the following settings:
- client mode where applicable (generally older 32-bit JVMs). The client mode is designed to start up quickly and not optimize as much.
- TieredCompilation and TieredStopAtLevel=1, equivalent to client mode on newer Hotspot-based JVMs
- compile.mode=OFF to disable JRuby's JVM bytecode compiler
- jruby.compile.invokedynamic=false to disable the slow-to-warmup invokedynamic features of JRuby
If you don't need code to be fast but you want the application to start up quickly, this option may be good for you.
use –dev flag with rvm
RVM supports PROJECTJRUBYOPTS with two provided hook files (currently, afterusejruby and afterusejrubyopts). If enabled by making them executable, the hooks use the script library functions jrubyoptionsappend and jrubyoptionsremove to append/remove the options in PROJECTJRUBYOPTS to/from JRUBYOPTS.
chmod +x $rvm_path/hooks/after_use_jruby_opts
echo 'PROJECT_JRUBY_OPTS=(--dev)' > ~/.rvmrc
tools
rails/spring MRI Ruby only, they use fork
which doesn't work on JRuby
spork, not work. start with error TypeError: no implicit conversion of Fixnum into String
theine Rails pre-loader designed to work on JRuby
gem install thenine
theine_server
time thenine rake test
4.882s
time theine runner "puts Rails.env"
4.464s
drip Fast JVM launching not working with rails runner
benchmark
create two project.
1 2 3 4 5 6 7 8 9 10 11 |
|
| | ruby | jruby | jruby –dev | theine| |————|——–|———|————-|——-| | rake test | 3.841s | 13.547s | 7.451s |4.882s | | rails s | 4.796s | 20.914s | 11.833s |5.084s | |rails runner| 2.128s | 17.116s | 9.718s |4.464s |
Using --dev
flag, we can roughly cut 45% time when initialization. And theine
is a good option.
Reference
- https://github.com/jruby/jruby/wiki/ClasspathAndLoadPath
- https://github.com/jruby/jruby/wiki/Improving-startup-time
- http://stackoverflow.com/questions/8283300/how-do-i-use-jruby-opts-with-rvm
- http://blog.headius.com/2009/05/jruby-nailgun-support-in-130.html
- https://github.com/mrbrdo/theine
- http://stackoverflow.com/questions/2224178/how-to-improve-jruby-load-time
- https://github.com/ninjudd/drip
- https://gist.github.com/rwjblue/4582914