Posted on February 1st, 2010 by
Matt Fletcher
One of the great things about the JRuby project is that it’s easy to run Ruby programs without installing Ruby. In fact, you don’t even need to install JRuby. All you need is a JVM runtime and jruby-complete.

Rationale
Check out this other post for a discussion of my reasons for locking down your JRuby runtime. In summary, embedding jruby-complete gives you complete control of your Ruby runtime. That’s a good thing. The downside is that discovering and executing commands through jruby-complete can be a pain. The rest of this post describes how to ameliorate the pain.
Running jruby-complete
The base jruby-complete command is:
|
java -jar jruby-complete-1.4.0.jar |
This gives you the same behavior as typing
ruby or
jruby.
|
java -jar jruby-complete-1.4.0.jar -e "puts 'Hello'" |
prints “Hello.” (Of course, this depends on what your jruby-complete jar is named. I usually put the version number in there so I know what it is. I expect anyone reading this to be able to figure out what their jar is named and fill it in appropriately. If this is a hurdle, then too bad for you.)
I lied.
1 To get the same
JVM heap and stack sizes as typing
jruby, you need to pass a couple of
JVM options:
|
java -Xmx500m -Xss1024k -jar jruby-complete-1.4.0.jar -e "puts 'Hello'" |
Want to run irb? Try this:
|
java -Xmx500m -Xss1024k -jar jruby-complete-1.4.0.jar -e 'load "META-INF/jruby.home/bin/jirb"' |
1
2
3
4
|
irb(main):001:0> puts "Hello"
Hello
=> nil
irb(main):002:0> % |
As you can see, the
java command is getting to be a pain. It’s time to introduce some rake tasks to help us out.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
JRUBY_COMPLETE = "jruby-complete-1.4.0.jar"
JRUBY = "java -Xmx500m -Xss1024k -jar #{JRUBY_COMPLETE}"
namespace :jruby do
desc "Run JRuby help"
task :help do
sh %+#{JRUBY} --help+
end
desc "Run any command with JRuby"
task :run do
sh %+#{JRUBY} -e '#{ENV["cmd"]}'+
end
end |
Now I can type rake jruby:run cmd='puts "Hello"'. Shell escaping is becoming a real annoyance at this point. Thankfully, I’m usually not using jruby-complete to run silly little commands. By the time I’ve introduced a Rakefile I’ve got a real application with tasks oriented around testing and running it, so it’s rare that I’m using a task like jruby:run very often.
Running my application may introduce a task that looks something like this:
1
2
3
|
task :run do
sh "#{JRUBY} lib/application_bootstrap.rb"
end |
Running it:
1
2
3
4
|
fletcher-git/github/jruby-complete-example(master) rake run
(in /Users/fletcher/git/github/jruby-complete-example)
java -Xmx500m -Xss1024k -jar jruby-complete-1.4.0.jar lib/application_bootstrap.rb
Hello from application_bootstrap |
Of course, my application comes with RSpec specs. The standard jruby-complete distribution comes with RSpec built in. How can I use it? The
-S parameter runs files in JRuby’s bin directory:
1
2
3
4
5
6
7
|
namespace :spec do
desc "Run RSpec against a specific file"
task :run do
raise "You need to specify a spec with spec=" if not ENV["spec"]
sh %+#{JRUBY} -S spec -f specdoc #{ENV["spec"]}+
end
end |
Here’s a spec:
1
2
3
4
5
|
describe "John Galt" do
it "does not tolerate logical fallacies" do
"A".should == "A"
end
end |
Running it:
1
2
3
4
5
6
7
8
9
10
|
fletcher-git/github/jruby-complete-example(master) rake spec:run spec=spec/unit/objectivism_spec.rb
(in /Users/fletcher/git/github/jruby-complete-example)
java -Xmx500m -Xss1024k -jar jruby-complete-1.4.0.jar -S spec -f specdoc spec/unit/objectivism_spec.rb
John Galt
- does not tolerate logical fallacies
Finished in 0.123 seconds
1 example, 0 failures |
Is this more typing than the usual
spec spec/unit/objectivism_spec.rb? Yes. Do I care? No. I know how to use my shell.
1
2
3
4
5
6
7
|
fletcher-git/github/jruby-complete-example(master) which sp
sp () {
rake spec:run spec=$@
}
fletcher-git/github/jruby-complete-example(master) sp spec/unit/objectivism_spec.rb
(in /Users/fletcher/git/github/jruby-complete-example)
java -Xmx500m -Xss1024k -jar jruby-complete-1.4.0.jar -S spec -f specdoc spec/unit/objectivism_spec.rb |
Alright, so now that my application has been built up, I might want to start compiling the .rb files into .class files. Here comes jrubyc:
1
2
3
4
5
6
7
8
9
10
11
12
|
require "rake/clean"
namespace :jruby do
output_directory = "classes"
directory output_directory
CLEAN.include output_directory
desc "Compile Ruby files in lib"
task :compile => output_directory do
sh %+#{JRUBY} -S jrubyc -p com/atomicobject -t #{output_directory} lib+
end
end |
1
2
3
4
5
6
7
8
9
10
11
|
fletcher-git/github/jruby-complete-example(master) rake jruby:compile
(in /Users/fletcher/git/github/jruby-complete-example)
mkdir -p classes
java -Xmx500m -Xss1024k -jar jruby-complete-1.4.0.jar -S jrubyc -p com/atomicobject -t classes lib
Compiling all in '/Users/fletcher/git/github/jruby-complete-example/lib'...
Compiling lib/application_bootstrap.rb to class com/atomicobject/lib/application_bootstrap
fletcher-git/github/jruby-complete-example(master) rake jruby:run cmd='require "classes/com/atomicobject/lib/application_bootstrap"'
(in /Users/fletcher/git/github/jruby-complete-example)
java -Xmx500m -Xss1024k -jar jruby-complete-1.4.0.jar -e 'require "classes/com/atomicobject/lib/application_bootstrap"'
Hello from application_bootstrap |
Remember that since we’re executing a
java command, we can pass any typical
JVM parameters before the
-jar parameter. We’ve done this for things like:
- enabling antialiasing in Apple’s JVM via a Java property.
- tweaking Substance’s widget behavior via a Java property.
- enabling Yourkit Java Profiler via the
-agentlib parameter.
- including libraries and directories in the JVM’s classpath via the
-cp parameter.
Since these parameters need to be passed before the -jar parameter, a more sophisticated method for setting up the JRuby command is needed than the constant I’ve used. A method like that is specific for your application and beyond the scope of this post, but is not be difficult to create.
Conclusion
There are an uncountable number of good things about JRuby and jruby-complete is one of them. A little help from scripts and your shell means you can build and run your application with a controlled Ruby runtime.
Additional resources
- The Rakefile, jruby-complete, and other files used in this post are available in this GitHub project.
- JarJar Links is an ant library that is useful for combining multiple jar files together.
- I wrote a post a while ago about using JarJar to combine jruby-complete and other application dependences into a single file.
- The AGI Production Simulator is built using the jruby-complete commands described in this post as well as the above jar-rolling technique.
-
Replicating the true
jruby behavior is way, way beyond the scope of this post. Check out the jruby script if you really care. Most of the time the JVM heap and stack sizes are the most important things to worry about.
↩
Edit 2/6/2010: Reduced -e ‘load…’ parameters to -S
Luke Says:
February 3rd, 2010 at 03:01 PMJRuby is great! I use jruby-complete.jar to pckage a war to deploy in JBoss. Very good post btw.
Chris Says:
February 10th, 2010 at 04:06 PMVery good post.
Anyway, can anybody help me understand why “jruby” standalone and using jruby-complete-1.4.9.jar below behave different in this example: hi java -Xmx500m -Xss1024k -jar /home/cg/Downloads/firefox/jruby-complete-1.4.0.jar -e “require ‘rubygems’; require ‘eventmachine’; puts ‘hi’” file:/home/cg/Downloads/firefox/jruby-complete-1.4.0.jar!/META-INF/jruby.home/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require’: no such file to load—eventmachine (LoadError) from file:/home/cg/Downloads/firefox/jruby-complete-1.4.0.jar!/META-INF/jruby.home/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require’ from -e:1
It seems to me that using jruby-complete.jar the installed rubygems are not picked up !?
Any help is very much appreciated.
cg Says:
February 11th, 2010 at 12:03 AMIs there an easy way to use installed (j)rubygems in a script run launched via jruby-complete?
In other ways i’d like to do something like this:
java -Xmx500m -Xss1024k -jar jruby-complete.jar -e “require ‘eventmachine’; puts ‘eventmachine required’ “
so that the installed ‘eventmachine’ gem is picked up from my gem repository.
Babar Says:
April 8th, 2010 at 04:49 AMOn Windows, this line doesn’t work : java -Xmx500m -Xss1024k -jar jruby-complete-1.4.0.jar -e ‘load “META-INF/jruby.home/bin/jirb”’
You must inverse double quotes with single quotes, like this : java -jar jruby-complete-1.4.0.jar -e “load ‘META-INF/jruby.home/bin/jirb’”
Eric Kramer Says:
April 20th, 2010 at 08:17 AMI’m also interested in the subject of accessing gems using JRuby-complete. I just stumbled upon this blog posting from Nick Sieger that appears quite relevant. Note that this is 1.1.6 so perhaps things have changed.
David Says:
July 9th, 2010 at 07:30 AMI use jruby-complete for testing with RSpec. Now I’m trying to use RCov with it, but no luck right now because RCov is using binary that can’t be installed in the jar package.
How could I do that? I mean, to use RCov with jruby-complete? Did anyone try?
mk Says:
July 20th, 2010 at 08:53 AMI try to start jirb_swing with JSR 223 script and jruby-complete but it does not show the commmand prompt. How can I do this?