Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

• 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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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