$30 off During Our Annual Pro Sale. View Details »

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.

keithrbennett

August 28, 2012
Tweet

More Decks by keithrbennett

Other Decks in Technology

Transcript

  1. JRuby -- Java/Ruby Synergy
    Keith Bennett
    keithrbennett --at-- gmail.com
    @keithrbennett
    1
    Tuesday, August 28, 2012

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  11. JRuby to Java Type Conversions
    jruby-1.6.7.2 :011 > 'abc'.class
    => String
    jruby-1.6.7.2 :012 > 'abc'.to_java.class
    => Java::JavaLang::String
    jruby-1.6.7.2 :014 > 123.class
    => Fixnum
    jruby-1.6.7.2 :015 > 123.to_java.class
    => Java::JavaLang::Long
    jruby-1.6.7.2 :016 > 3.14.class
    => Float
    jruby-1.6.7.2 :017 > 3.14.to_java.class
    => Java::JavaLang::Double
    11
    Tuesday, August 28, 2012

    View Slide

  12. Using IRB in JRuby as an Interactive Shell
    for Java
    >CLASSPATH=commons-lang.jar irb
    jruby-1.6.7.2 :001 > require 'java'
    => true
    jruby-1.6.7.2 :002 > java_import org.apache.commons.lang3.StringUtils
    => Java::OrgApacheCommonsLang3::StringUtils
    jruby-1.6.7.2 :003 > SU = StringUtils
    => Java::OrgApacheCommonsLang3::StringUtils
    jruby-1.6.7.2 :004 > SU.blank? ' '
    => true
    jruby-1.6.7.2 :005 > SU.blank? 'abc'
    => false
    jruby-1.6.7.2 :006 > SU.center 'abc', 5
    => " abc "
    jruby-1.6.7.2 :007 > SU.center 'abc', 5, '*'
    => "*abc*"
    12
    Tuesday, August 28, 2012

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide