Upgrade to Pro — share decks privately, control downloads, hide ads and more …

JRuby - The Synergy of Ruby and the JVM

JRuby - The Synergy of Ruby and the JVM

All about why JRuby offers so much to the Ruby and Java worlds, and how to use it.



August 28, 2012


  1. JRuby -- Java/Ruby Synergy Keith Bennett keithrbennett --at-- gmail.com @keithrbennett

    1 Tuesday, August 28, 2012
  2. What is JRuby? An implementation of the Ruby language on

    the Java Virtual Machine: • Open Source • Main site at http://jruby.org/ • Source Code at https://github.com/jruby/jruby • Just as Matz writes C so we don't have to, the JRuby team writes Java so we don't have to. • Both 1.8 and 1.9 compatible. • JRuby's lead developers are Charles Nutter, Thomas Enebo, Ola Bini and Nick Sieger. 2 Tuesday, August 28, 2012
  3. Non-Java Languages on the JVM "The Java virtual machine knows

    nothing of the Java programming language, only of a particular binary format, the class file format." - from http://java.sun.com/developer/technicalArticles/DynTypeLang/ • Groovy • JRuby • Scala • Clojure • JavaScript 3 Tuesday, August 28, 2012
  4. Technical Benefits of Running Ruby on the JVM • mature

    and stable platform • excellent performance, garbage collection, and multithreading • performance tuning and profiling tools (e.g. jvisualvm) • access to a huge number of libraries, e.g. Hadoop, XML, SOAP • great for driving Java API's • excellent I18N (internationalization) support • highly scalable • adds to the pool of systems on which Ruby can run (e.g. mainframes with JVM’s) 4 Tuesday, August 28, 2012
  5. Benefits of JRuby for Enterprise Java Shops • can use

    Ruby software such as rspec, rake, Active Record (esp. useful for migrations), DBI, etc. • can introduce development staff to scripting languages in general, and Ruby in particular • can automate one-off tasks that were previously too cost prohibitive to automate • can grow Ruby expertise that can be applied to various kinds of tasks (e.g. testing, scripting, web development) • can introduce it in a way that will not be distributed with production code • can use it for saner and more rapid development of Swing or SWT client-side GUI apps (see JRuby as a Better Language for the JVM - http://krbtech.wordpress.com/2009/02/26/jruby-a- better-language-for-the-javavirtual-machine/ 5 Tuesday, August 28, 2012
  6. JRuby Lowers the Cost of Using Ruby in Java Shops

    • virtually no new infrastructure, means lower sysadmin costs • can still use Java web servers, profiling tools, etc. • can continue to use Java libraries • can decide to implement a hybrid Java-Ruby product where both sides run in the same process (the JVM) • if converting entire product to Ruby, can replace Java code with Ruby code in increments instead of all at once • less learning required In these ways, JRuby lowers the cost of experimenting with Ruby (or switching entirely to it), increasing the probability of adoption and success. 6 Tuesday, August 28, 2012
  7. Business Benefits of Using JRuby for Ruby Developers • enables

    expanding customer base to include Java shops, many of which are very large and well funded. • enables creation of better solutions by increasing the set of parts that can be assembled into a solution -- sometimes Java is better (e.g. XML, SOAP support). 7 Tuesday, August 28, 2012
  8. Calling Java from Ruby require 'java' java.lang.System.properties.sort.each do |key, value|

    printf("%-30s %s\n", key, value) end displays: awt.nativeDoubleBuffering true awt.toolkit apple.awt.CToolkit file.encoding UTF-8 file.encoding.pkg sun.io file.separator / gopherProxySet false java.awt.printerjob apple.awt.CPrinterJob java.class.path java.class.version 50.0 … 8 Tuesday, August 28, 2012
  9. Adding Ruby methods to Java Classes # Add pretty print

    to all Properties instances by # opening the Properties class and defining method 'pp': require 'java' java_import java.util.Properties class Properties def pp s = '' sort.each do |key, value| s << sprintf("%-34s %s\n", key, value) end s end end puts java.lang.System.properties.pp 9 Tuesday, August 28, 2012
  10. JRuby Method Generation JRuby generates snake-case named methods for Java

    camel-case named methods, and conventional reader and writer methods à la attr_accessor: # The java.util.Locale class contains only getDefault and setDefault. # JRuby adds the others: jruby-1.6.5 :003 > puts Locale.methods.sort.grep /[Dd]efault/ default default= getDefault get_default setDefault set_default Also, JRuby makes the Enumerable interface available to some kinds of Java objects, enabling the above, and the following: Locale.iSOCountries.each { |country_code| puts country_code } Locale.iSOLanguages.each { |language_code| puts language_code } 10 Tuesday, August 28, 2012
  11. JRuby to Java Type Conversions jruby- :011 > 'abc'.class =>

    String jruby- :012 > 'abc'.to_java.class => Java::JavaLang::String jruby- :014 > 123.class => Fixnum jruby- :015 > 123.to_java.class => Java::JavaLang::Long jruby- :016 > 3.14.class => Float jruby- :017 > 3.14.to_java.class => Java::JavaLang::Double 11 Tuesday, August 28, 2012
  12. Using IRB in JRuby as an Interactive Shell for Java

    >CLASSPATH=commons-lang.jar irb jruby- :001 > require 'java' => true jruby- :002 > java_import org.apache.commons.lang3.StringUtils => Java::OrgApacheCommonsLang3::StringUtils jruby- :003 > SU = StringUtils => Java::OrgApacheCommonsLang3::StringUtils jruby- :004 > SU.blank? ' ' => true jruby- :005 > SU.blank? 'abc' => false jruby- :006 > SU.center 'abc', 5 => " abc " jruby- :007 > SU.center 'abc', 5, '*' => "*abc*" 12 Tuesday, August 28, 2012
  13. Using RSpec in JRuby to Unit Test Java Code require

    'java' require 'rspec' java_import org.apache.commons.lang3.StringUtils describe 'StringUtils' do subject { StringUtils } it "should consider a 1-space string to be blank" do subject.blank?(' ').should be_true end end # >CLASSPATH=commons-lang.jar rspec string_utils_spec.rb # . # # Finished in 0.039 seconds # 1 example, 0 failures 13 Tuesday, August 28, 2012
  14. Calling JRuby from Java import org.jruby.embed.ScriptingContainer; public class CallingRubyFromJava {

    public static void main(String[] args) { ScriptingContainer container = new ScriptingContainer(); container.put("$greeting", "Hello from JRuby!"); // optional // container.setLoadPaths(aJavaListOfDirectories); // optional container.setCompatVersion(org.jruby.CompatVersion.RUBY1_9); // optional container.runScriptlet("puts $greeting"); } } // >javac -cp ".:$JRUBY_JAR" CallingRubyFromJava.java // >java -cp ".:$JRUBY_JAR" CallingRubyFromJava // Hello from JRuby! 14 Tuesday, August 28, 2012
  15. • java_import - Imports java classes • java_send - for

    specifying which function to call, by signature • java_alias - for creating an alias for a Java function with signature • java_method - for creating a callable reference to a Java function with signature • field_accessor - for accessing Java instance variables, even private ones • add_class_annotation - Adds a class annotation to a Ruby class • become_java! - "promotes" a Ruby class to be a Java class • include - can be used to signal that this class implements a Java interface Special Java Support Calls 15 Tuesday, August 28, 2012
  16. Compiling JRuby The JRuby distribution comes with jrubyc, a compiler

    that can produce either Java class files, or Java source (run jrubyc --help for details). rvm jruby echo "puts 'hello'" > hello.rb jrubyc hello.rb ls -l hello* javap -v hello | less Free code obfuscation: Since only the .class file is need to run your app, you can withhold the source code from your users and provide only the .class file. The .class file can be decompiled, but will be difficult to comprehend, since Java byte code is similar in concept to assembler code. 16 Tuesday, August 28, 2012
  17. Omitting the ‘J’ in JRuby Normally, it is necessary to

    run JRuby commands (jruby, jirb) with their distinctive names beginning with j. rvm eliminates the need for this. rvm jruby which ruby # /Users/kbennett/.rvm/rubies/jruby-1.6.5/bin/ruby which jruby # /Users/kbennett/.rvm/rubies/jruby-1.6.5/bin/jruby ls -l /Users/kbennett/.rvm/rubies/jruby-1.6.5/bin # lrwxr-xr-x 1 kbennett staff 5 Jan 19 13:25 ruby -> jruby 17 Tuesday, August 28, 2012
  18. JRLint Analyzes a code base to identify potential JRuby porting

    issues. Run on current rspec code base: >jrlint JRuby-Lint version 0.3.1 For more on gem compatibility see http:// wiki.jruby.org/C-Extension-Alternatives ./Gemfile:8: [gems, warning] Found gem 'nokogiri' which is reported to have some issues: For best results, use the pure-Java version of Nokogiri (default after v1.5). ./lib/spec/example/example_methods.rb:37: [timeout, warning] Timeout in JRuby does not work in many cases ./lib/spec/extensions/instance_exec.rb:20: [threads, warning] Use of Thread.critical is discouraged. Use a Mutex instead. ... Processed 323 files in 10.25 seconds Found 7 items 18 Tuesday, August 28, 2012
  19. Access Maven Repos >gem install mvn:rhino:js Successfully installed mvn:rhino:js-1.7.r.2-java 1

    gem installed 19 Tuesday, August 28, 2012
  20. Defaulting to 1.9 Most people will want JRuby to run

    in 1.9 mode. To automate this, ensure that the environment variable JRUBY_OPTS will contain --1.9. Most developers will accomplish this by inserting the following line in their shell startup script (e.g. .bashrc, .zshrc): export JRUBY_OPTS=--1.9 This can be overridden by eliminating or replacing that environment variable’s value: JRUBY_OPTS= ruby ... # or export JRUBY_OPTS= 20 Tuesday, August 28, 2012
  21. Nailgun Nailgun is a tool packaged with JRuby that enables

    sharing a single JRuby virtual machine instance by JRuby scripts to eliminate the delay associated with JVM startup. # If $JRUBY_OPTS contains “--1.9” so that JRuby runs # in 1.9 mode by default, then this must be overridden # for the Nailgun server to start. # See bug at http://jira.codehaus.org/browse/JRUBY-5611. # Start up the shared Nailgun server: JRUBY_OPTS=’’ jruby –-ng-server time ruby -e "puts 123" #123 #ruby -e "puts 123" 2.89s user 0.14s system 217% cpu 1.390 total time ruby --ng -e "puts 123" #123 #ruby --ng -e "puts 123" 0.00s user 0.00s system 0% cpu 0.488 total 21 Tuesday, August 28, 2012
  22. JRuby-Rack Ruby Adapter to Java Web Servers • a bridge

    from the Java Servlet API to Ruby’s Rack API. • enables Ruby applications to run on virtually any existing Java web server • regularly tested with Tomcat 6/7, Jetty 6/7, JBoss 5/6, Resin 4, and GlassFish 3 (see http://www.engineyard.com/blog/2011/taking-stock-jruby-web-servers/ for an overview of Ruby adapters to Java web servers) 22 Tuesday, August 28, 2012
  23. Warbler “Warbler is a gem that makes a .war file

    out of a Rails, Merb, or Rack-based application. The intent is to provide a minimal, flexible, ruby-like way to bundle all your application files for deployment to a Java application server.” - http://kenai.com/projects/warbler/pages/Home From the Rails root directory, to create a war file for your Java application server: > warble war Or, to create a file containing the Tomcat web server so that it can be run directly from your command line: # can execute on cmd line like this: java -jar myapp.war > warble executable war 23 Tuesday, August 28, 2012
  24. Trinidad • equally suited for development and production use •

    employs JRuby-Rack and Apache Tomcat as embedded Java libraries • available as a gem 24 Tuesday, August 28, 2012
  25. TorqueBox “TorqueBox is the most powerful deployment environment available to

    any Ruby application.” “Because of its built-in support for features such as clustering, TorqueBox is often distinguished as enterprise-grade software. But it does this without any of the drawbacks we programmers often associate with “enterprisey” things.” - Joe Kutner, “Deploying with JRuby” • supports Rack based applications (e.g. Rails, Sinatra) • built on top of JBoss • clustering - clusters can easily communicate & share session data • messaging (can use Rabbit MQ) • cacheing • scheduling • daemons 25 Tuesday, August 28, 2012
  26. MBeans MBeans (management beans) are objects that can be accessed

    from outside your application in order to access information about, or modify, your running application. • separate from your running application • have their own port, different from app users’ port (offering better security) • can access using management tools such as JConsole (see example, p. 174-5, “Deploying with JRuby”) 26 Tuesday, August 28, 2012
  27. JVisualVM JVisualVM is a monitoring, profiling, and troubleshooting tool packaged

    with the JDK (Java Development Kit). For more info on thread states, see: http://docs.oracle.com/ javase/7/docs/api/java/lang/ Thread.State.html 27 Tuesday, August 28, 2012
  28. Sample Multithreaded Program num_threads = 5 threads = [] (0...num_threads).each

    do |n| threads << Thread.new do loop { puts "#{' ' * (5 * n)}#{n}\n" } end end threads.each { |thread| thread.join } 28 Tuesday, August 28, 2012
  29. Multithreading CPU Usage by Ruby Version rvm 1.8 ruby multithread.rb

    PID COMMAND %CPU TIME #TH #WQ #POR #MREG RPRVT RSHRD RSIZE 367 Terminal 105.8 01:20.36 5/1 1 123- 166+ 267M+ 43M 278M+ 1104 ruby 82.7 00:13.40 1/1 0 18 28 1248K 240K 2108K rvm 1.9 ruby multithread.rb PID COMMAND %CPU TIME #TH #WQ #POR #MREG RPRVT RSHRD RSIZE 1249 ruby 167.6 00:20.85 7/2 0 41 61 2972K+ 240K 4632K+ 367 Terminal 153.0 03:49.55 5/1 1 125 267 716M+ 43M 772M+ # What happened? I thought 1.9 used a GIL (Global Interpreter Lock)? rvm jruby ruby multithread.rb ID COMMAND %CPU TIME #TH #WQ #POR #MREG RPRVT RSHRD RSIZE 1364 java 137.1 00:25.84 23/2 1 201 236 80M 3144K 93M 367 Terminal 120.8 05:05.62 6/1 2 127- 291 813M+ 43M 901M+ 29 Tuesday, August 28, 2012
  30. Life Game Viewer An example of a JRuby application: •

    written in JRuby • uses Java Swing library, so illustrates Java interop • available at: https://github.com/keithrbennett/life-game-viewer 30 Tuesday, August 28, 2012
  31. References • JRuby Main Site: http://jruby.org • JRuby Book: http://pragprog.com/book/jruby/using-jruby

    • Deploying with JRuby Book: http://pragprog.com/book/jkdepj/deploying-with-jruby • Charlie Nutter's JRuby Slide Show: http://www.slideshare.net/CharlesNutter/rubyconf-uruguay-2010-jruby • Replacing Java Incrementally with JRuby: http://www.youtube.com/watch?v=l3jz8OqdBd0 • JRuby Polyglot Heaven by Thomas E Enebo and Charles Oliver Nutter: http://www.youtube.com/ watch?v=ikhmBdQljVI • Check out how LinkedIn uses JRuby on its Front-end: http://www.youtube.com/watch? v=qZcmF3yonjs • JRuby as a Better Language for the JVM - http://krbtech.wordpress.com/2009/02/26/jruby-a- better-language-for-the-javavirtual-machine/ • Life Game Viewer (JRuby Swing app) Github Repo: https://github.com/keithrbennett/life-game-viewer • This slideshow: https://speakerdeck.com/u/keithrbennett/p/jruby-the-synergy-of-ruby-and-the- jvm 31 Tuesday, August 28, 2012