The JRuby Blog

The Ruby Programming Language on the JVM

  • JRuby 10, Part 1: What's New

    Published by Charles Oliver Nutter on April 09, 2025

    I am very excited to introduce you to JRuby 10, our biggest leap forward since “JRuby 9000” was released almost a decade ago.

    With up-to-date Ruby compatibility, support for modern JVM features, and a big cleanup of internal code and external APIs, we believe this is our most important release ever. This article will provide a first look at these improvements and help you get started on your JRuby 10 journey.

    Moving Forward

    With such a long time since our last major release, we decided JRuby 10 had to make some big moves. As a result, this is the most up-to-date and powerful JRuby release we’ve ever put together. Here’s a few of the major upgrades you’ll see when you move to JRuby 10.

    Compatibility jump to Ruby 3.4

    It’s been over three years since we released JRuby 9.4 with Ruby 3.1 compatibility, so naturally a version update was in order. Last year we decided it made the most sense for us to target Ruby 3.4, since it would be released late in 2024 around the time we hoped to wrap up JRuby 10.

    That meant implementing Ruby 3.2, 3.3, and 3.4 features, and getting literally thousands of new tests and specs passing.

    CRuby core class test results

    JRuby 9.4 running Ruby 3.1 tests:
    
    4888 tests, 1859373 assertions, 0 failures, 0 errors, 22 skips
    
    JRuby 10 running Ruby 3.4 tests:
    
    5461 tests, 1903359 assertions, 0 failures, 0 errors, 43 skips
    

    Over the past month, we merged our JRuby 10 development branch back to main, and just this week we finally went “green” in CI after hundreds of hours of work. We’re confident this is the most compatible a JRuby “dot zero” release has ever been, and being current on Ruby compatibility means we’ve got more time to work on aggressive optimization plans.

    Java up to 21

    Like many projects in the Java world, we chose to maintain support for Java 8 for over a decade after it was released, due to challenging issues involving Java 9+ and the new restrictions of the Java Platform Module System. Even though we made sure JRuby supported the latest Java releases, we could only depend upon Java 8-level features. Meanwhile the JDK added powerful enhancements like native function calls (Project Panama) and lightweight threads (Project Loom).

    For JRuby 10, we’re finally updating our minimum Java version… to the most recent “long term support” version 21. Many of the JRuby features described in this post are possible because of that move.

    We’ve already started to integrate the features that Java 21 provides, and we’re looking forward to bringing ten years of JVM enhancements to Ruby users.

    Full optimization by default

    Starting with Java 7, JRuby has supported optimizing Ruby code using a feature called “invokedynamic”, which allows us to teach the JVM how Ruby code works. “Indy” is absolutely critical for Ruby performance on JRuby, but it has also taken time to evolve at the JVM level. Because of the extra startup and warmup time required to use indy on older JVMs, JRuby ran by default in a “middle tier” of optimization, using indy only for simple Ruby operations and using slower inline caching techniques for heavier ones. Users had to enable indy with the JRuby flag -Xcompile.invokedyamic.

    But no longer!

    JRuby 10 runs with full invokedynamic optimization by default. That means you’ll get the best available performance for your JRuby scripts and applications without passing any additional flags.

    JRuby default red/black performance, 9.4 vs 10

    $ jruby9.4 -v bench/bench_red_black.rb 5
    jruby 9.4.12.0 (3.1.4) 2025-02-11 f4ab75096a OpenJDK 64-Bit Server VM 21.0.5+11-LTS on 21.0.5+11-LTS +jit [arm64-darwin]
    1.0899240000000001
    0.632956
    0.604672
    0.612468
    0.5976049999999999
    $ jruby -v bench/bench_red_black.rb 5
    jruby 10.0.0.0-SNAPSHOT (3.4.2) 2025-04-09 e2909f9baf OpenJDK 64-Bit Server VM 21.0.5+11-LTS on 21.0.5+11-LTS +indy +jit [arm64-darwin]
    1.651375
    0.46118200000000004
    0.363622
    0.23990799999999998
    0.177958
    

    For development and testing environments, where aggressive optimizations are usually not helpful and just slow down command-line use, we provide other options…

    Startup time improvements

    The number one complaint from JRuby users has always been startup time (and to a lesser extent, warmup time of large apps). With the leap to Java 21, we’ve started to leverage a few new JVM features to get JRuby apps starting up more quickly:

    • OpenJDK’s “Application Class Data Store” (AppCDS) allows pre-caching code and metadata during startup to reduce the cost of future commands. JRuby’s main executable will automatically use the right AppCDS flags on Java 21+ to optimize and cache as much as possible. This has halved the startup time of a typical JRuby command, and there’s a lot more we can do to utilize this feature.
    • Project CRaC (Coordinated Restore at Checkpoint) is an experimental JVM feature that allows users to “checkpoint” a running process and launch multiple future processes by restoring that checkpoint. There’s limitations, such as only being able to restore a single process at a time, but when CRaC works for you it can reduce startup time of even large apps to just a few milliseconds. The JRuby launcher supports CRaC with a few flags described in my first “JRuby on CRaC” blog post.
    • Project Leyden is the next-generation “AppCDS”, also storing data like JIT-compiled native code and optimization profiles from previous runs. The goal of Leyden is to eventually save off everything needed to start right up with optimized code, skipping the slow early stages of execution. The JRuby Team will incorporate Leyden flags into our launcher as they become available (with preview support already in Java 24)… and JRuby users will just have to upgrade their JDK to take advantage.

    These features combined with our reduced-overhead --dev flag mean JRuby starts up faster than ever before… fast enough to take most of the pain out of command-line development.

    JRuby “hello world” startup time, 9.4 vs 10

    [] jruby $ time jruby9.4 --dev -e 'puts "Hello, world!"'
    Hello, world!
            0.99 real         1.13 user         0.10 sys
    [] jruby $ time jruby --dev -e 'puts "Hello, world!"'
    Hello, world!
            0.81 real         0.91 user         0.08 sys
    

    Getting Started

    Trying JRuby has never been easier! Here’s a quick walkthrough on getting JRuby into your development toolbox.

    Install a JDK

    The only requirement for JRuby 10 is a Java 21 or higher JDK installation. I personally like the OpenJDK “Zulu” builds from Azul, but there’s excellent and well-supported free binaries from the Eclipse project, Amazon, Microsoft, and Oracle.

    Install the JDK in whatever way is most appropriate for your platform… usually that will mean a system-level package on Linux/BSD or an installer on MacOS and Windows. Then just point your JAVA_HOME environment variable at the JDK and JRuby’s launcher will figure out the rest.

    Install JRuby

    Most Rubyists will be familiar with Ruby managers and switchers like rbenv, rvm, or chruby. JRuby 10 preview snapshots can be usually be installed as “jruby-head” or “jruby-dev”, and after our release as “jruby-10” or just “jruby”.

    JRuby is also a JVM-based project (“write once, run anywhere”, remember?), so installing it yourself is as easy as unpacking a tarball or zip and putting the bin dir in your PATH. There’s no build step and no build tools needed to start using JRuby today.

    Users of chruby can unpack this tarball into ~/.rubies since it does not support “head” installs.

    Try it out

    JRuby supports the standard irb REPL, as well as other modern alternatives like pry. Once you have jruby -v working, you can gem install your favorite tools and test them out on JRuby. It’s really that easy.

    $ irb
    irb(main):001> JRUBY_VERSION
    => "10.0.0.0-SNAPSHOT"
    irb(main):002> RUBY_VERSION
    => "3.4.2"
    irb(main):003> java.lang.System.get_property("java.version")
    => "21.0.5"
    

    Riding the Rails

    Ruby without Rails would be like… well I guess it would still be Ruby, but there’s no doubt Rails is still the most popular use case for Ruby. JRuby has supported Rails since the 1.x era, and we’ve worked with the Rails and JRuby community to keep up with new releases and features. JRuby represents the best way to achieve single-process multicore scaling of Rails applications, and thousands of Rails users around the world rely on it to better utilize precious computing resources.

    We’ll publish a post soon that describes how to get started with JRuby on Rails, all the way from generating an app to deploying on Puma or inside a Java application server.

    Rails compatibility

    Keeping up with Rails is no small feat, and with only a handful of contributors we have tended to lag a bit behind. JRuby currently has database support for ActiveRecord up to 7.1, and work is ongoing to support Rails 8. If you have an interest in helping the JRuby team update our ActiveRecord adapter (ActiveRecord-JDBC, which uses the pure-JVM Java DataBase Connectivity API), please let us know! We’re hoping to have full support for Rails 8 by this summer.

    Generating an app

    The typical Rails commands should all work on JRuby exactly the same as on standard CRuby, and with our startup time improvements and the –dev flag, we’re able to run those commands faster than any past JRuby version.

    Config changes

    Only minor configuration changes are required to run a Rails app on JRuby:

    • Switch to the appropriate ActiveRecord-JDBC adapter for your database, in database.yml and in your Gemfile.
    • Configure the Puma server for a number of threads based on the CPU cores available, using “2n+1” as a good rule of thumb.
    • Make sure there’s enough database connections in the pool for the number of Puma threads you configure.

    Once you’ve generated a new app or made config changes to your existing app, just bundle and fire it up! JRuby is a true Ruby implementation, and we work very hard to ensure Ruby libraries and applications like Rails work the same as on CRuby.

    Integrating with JVM Languages

    Half the fun of JRuby comes from taking advantage of the Java platform. Here’s just a few examples of things you can’t do as easily or quickly on any other Ruby implementation.

    Ruby on the JVM

    We’ve always had a goal of keeping JRuby a standard “JVM language”, runnable on any Java build compatible with our minimum requirement. This means you can deploy JRuby on Linux, MacOS, and Windows, of course, but also unusual and exotic platforms like the BSDs, Solaris, and more. We also can run on any hardware supported by the JVM, which basically means any system with enough memory and at least 32 bit registers is fair game.

    This also means JRuby can be deployed anywhere Java applications can be deployed, alongside enterprise Java apps using Spring or Jakarta EE. Ruby and Rails developers can expand their target market to any shop that hosts JVM-based apps… which dwarfs the number of shops that would be comfortable installing the libraries and development tools necessary to run CRuby. JRuby brings the Ruby world into the enterprise, and brings enterprise opportunities to every Rubyist.

    JRuby versus Ruby running threaded “tarai” benchmark

    $ jruby bench_ractors_tarai.rb 
                          user     system      total        real
    serial           21.580000   0.070000  21.650000 ( 21.395228)
    threaded         32.690000   0.100000  32.790000 (  4.260730)
    
    $ ruby3.4 --yjit bench_ractors_tarai.rb
                          user     system      total        real
    serial           25.037682   0.060370  25.098052 ( 25.257134)
    threaded         24.998077   0.055508  25.053585 ( 25.058869)
    

    Calling into Java

    Part of running on the JVM is being able to integrate other languages and their libraries into your JRuby apps. With JRuby, you can call Java, Scala, Clojure, Kotlin, and any other JVM language from Ruby with ease. Imagine bring the entire world of JVM languages and libraries to your Ruby app… what could you do when that kind of power?

    Using Java’s Swing GUI API from Ruby

    java_import javax.swing.JFrame
    
    frame = JFrame.new("Hello Swing")
    button = javax.swing.JButton.new("Klick Me!")
    button.add_action_listener do |evt|
      javax.swing.JOptionPane.showMessageDialog(nil, <<~EOS)
        <html>Hello from <b><u>JRuby</u></b>.<br>
        Button '#{evt.getActionCommand()}' clicked.
      EOS
    end
    
    # Add the button to the frame
    frame.get_content_pane.add(button)
    
    # Show frame
    frame.set_default_close_operation(JFrame::EXIT_ON_CLOSE)
    frame.pack
    frame.visible = true
    

    Using JVM libraries

    Of course in order to use more than just the standard JDK libraries, you need to be able to download and load them into your app. JRuby provides tools like jar-dependencies to let your JRuby gems use libraries published to Maven Central, Warbler to bundle your app and libraries into a single executable jar or war file (“Web ARchive”), and an enhanced require that loads Java JAR files right into your app. It’s the easiest and most fun way to explore all that the JVM has to offer.

    Want to build a cross-platform desktop UI? The JVM has a half-dozen different frameworks for building GUI applications, and with JRuby-supported libraries like Glimmer and JRubyFX, you don’t have to give up Ruby to get there.

    Hello World in Glimmer

    include Glimmer
    
    shell {
      text "Glimmer"
    
      label {
        text "Hello, World!"
      }
    }.open
    

    Hello World in Glimmer

    Interested in building Android apps for mobile or embedded applications? JRuby provides the Ruboto framework for building Android apps in Ruby without having to write a single line of Java or Kotlin.

    This also puts you on the leading edge of emerging technologies. As the JVM platform evolves and new features like Leyden, CRaC, SIMD vector operations, GPU integration and native function support in Panama move from experimental to standard, your apps can start using them with a simple JDK upgrade.

    You’ve even got a leg up on adding AI capabilities to your app; Ruby APIs for ChatGPT, Claude, Copilot and others are just starting to appear, but there’s dozens of existing JVM libraries for these LLMs and other bleeding edge AI technologies. You can start using AI in your Ruby apps today with JRuby!

    What’s Next?

    Over the coming weeks, I’ll publish more detailed posts on each of these areas to help you get started as a new JRuby user or to upgrade your existing JRuby applications. We are very proud of the work we’ve done to bring JRuby 10 to life, and I guarantee every Ruby shop can be faster and more scalable by taking advantage of JRuby and the JVM.

    Ruby’s future depends on projects like JRuby and creative developers like you. Let’s show them what we can do!

    Join the discussion on Reddit!

    JRuby Support and Sponsorship

    This is a call to action!

    JRuby development is funded entirely through your generous sponsorships and the sale of commercial support contracts for JRuby developers and enterprises around the world. If you find my work exciting or believe it is important your company or your projects, please consider partnering with me to keep JRuby strong and moving forward!

    Sponsor Charles Oliver Nutter on GitHub!

    Sign up for expert JRuby support from Headius Enterprises!

  • Independence Day

    Published by Charles Oliver Nutter on July 03, 2024

    All Good Things…

    Hello Ruby and JRuby friends! I have some exciting news!

    As they say, all good things must come to an end, and so it is with our sponsorship from Red Hat. We recently received notice that after 12 years of support, JRuby funding at Red Hat would conclude. Recent reorganization has changed priorities, and unfortunately there’s no place for ongoing sponsorship of projects like JRuby. As of July 4, 2024, my employment at Red Hat will end, and by the end of this month there will be no salaried employees dedicated to JRuby.

    JRuby’s Independence Day

    I’m not giving up without a fight. It is still my goal to build the most scalable, most stable, best-possible Ruby runtime for the JVM.

    JRuby’s independence couldn’t come at a more exciting time!

    Since we learned about our employment change, we’ve released two updates to JRuby: 9.3.15.0 (a special release of 9.3 for a major commercial user) and 9.4.8.0 (our standard update release with over 50 issues and pull requests).

    Meanwhile we have been pushing toward JRuby 10, our most ambitious release to date. JRuby 10 will feature:

    • Full support for Ruby 3.4, right in time for the official release
    • Support for Rails 7.1 and beyond, with updated support for Java app server deployment
    • Dozens of major optimizations we’ve backburnered for years in favor of compatibility and stability work
    • Improved tooling for debuggers, profiling, and monitoring
    • Update support for mobile and embedded applications using Ruboto

    After twenty years of development on JRuby – two-thirds of my professional career – I’m going to need your help to keep building the most widely-deployed alternative Ruby in the world. I am offering multiple ways you can support the JRuby project and my continued contributions to the JRuby and Ruby communities.

    Many of you have asked how you can support JRuby directly… this is your chance!

    Sponsorship

    Friends of the project and past users who have benefited from our tireless, free support can sponsor me directly via my GitHub Sponsor page.

    I’m very proud to announce that Shopify is my first major sponsor!

    Demonstrate your appreciation for the hard work that has gone into JRuby by contributing directly. Follow your heart and choose a monthly or one-time sponsorship level that reflects the benefit you and your projects have received from JRuby. Your sponsor contributions will go directly toward “keeping the lights on”, allowing me to continue the work we started back in 2004. In return, you or your organization will be presented to the JRuby and Ruby world through our talks, social media, and public outreach.

    Commercial Support

    For the first time ever, we are offering commercial support for JRuby users around the world!

    JRuby Support by Headius will give your company a direct line to the most knowledgeable JRuby developers in the world, the folks who have built this platform into the powerhouse it is today.

    JRuby Pro Support provides the basic tier, giving you priority email support from me and pre-release announcements for you and your organization.

    JRuby Enterprise Support takes that support to the next level, with priority bug and feature work across all supported platforms. Pricing scales with your needs: a tiered pricing structure that guarantees support for your production, off-the-shelf, embedded, and mobile JRuby applications.

    We’re still rolling out pricing and payment, but you can tell us of your interest and requirements today at the Contact Us page!

    JRuby Needs You!

    While we are deeply saddened by Red Hat’s decision, we recognize that their sponsorship and the sponsorship of other companies like Engine Yard and Sun Microsystems have made JRuby possible. Now it’s your turn, as JRuby friends and users, to help us write the next chapter in the JRuby story.

    Sign up for a sponsorship or contact us about commercial support today!

  • JRuby Prism - A new parser for a new era

    Published by Thomas E. Enebo on February 23, 2024

    Introduction

    JRuby has added support for the new backend parser Prism via the gem: jruby-prism-parser. Installing this gem will give you access to enable Prism (export JRUBY_OPTS="-Xparser.prism"). At this stage jruby-prism-parser is at the technology preview stage but capable of running pretty much everything: Rake, RSpec, RubyGems, Bundler, etc… We plan on this being the default parser when we release our next major JRuby release (10) which will be targeting Ruby 3.3 support.

    We encourage all JRuby users to give it a try and help us work out any kinks. Both in our integration with Prism and for Prism itself as it is still under heavy development.

    For those who do not want to read this whole article:

    1. gem install jruby-prism-parser and export JRUBY_OPTS=-Xparser.prism
    2. All implementations of Ruby will be sharing the same parser
    3. Prism is faster than JRuby’s current parser
    4. Prism gives us some cool future improvements

    The rest of this post will explain the background and why you should care. For those who want more details about Prism specifically then I recommend reading: https://kddnewton.com/2024/01/23/prism.html. This mentions a lot of additional information not covered here like the syntax tooling/APIs it enables.

    Why another parser?

    Community Effort

    As a compatibility project JRuby is always chasing what is happening with C Ruby. When a new release of C Ruby comes out it includes a big set of changes to the parser. JRuby must translate those changes to our fork of the parser and it is not trivial work. This is extra work that was just an accepted cost of developing JRuby.

    Prism changes this. It allows one set of developers to change the language and all implementations can use that without any parser porting activity. This is obviously less work but it also separates parsing into a more focused repository. Syntactic changes and fixes are easier to see and it gives the alternate implementations more access to the evolution of Ruby.

    One fascinating development I did not expect to see is so many different projects buying into Prism. Besides the more obvious ones like JRuby and TruffleRuby there has been support for Sorbet, js/webasm(Garnet), Rust, parser gem emulation, ripper emulation, and so much more (https://github.com/ruby/prism?tab=readme-ov-file#examples). I firmly believe this is because the parser has been externalized to its own project.

    Speed

    JRuby’s existing parser can eventually parse quickly but it is subject to the JVM warming up and optimizing the Java code in the parser. So if you parse enough files then JRuby parses as fast or faster than C Ruby. You will not ever see this in practice however. This is because by the time you parse the code of a typical application you will not have reached that warmup point where the JVM shines. This is a conundrum. We have tried different things and we still have unfinished ideas but this has been one of JRuby’s bigger unsolved problems.

    Prism mitigates this warmup issue because it is implemented in C. It has no warmup. JRuby will load a shared library and through a single foreign function call pass source code to be parsed. Prism will then parse, generate a syntax tree, and finally serialize that tree into a stream of bytes. JRuby will deserialize those bytes into a Java version of the syntax tree and then build that into JRuby’s own internal virtual machine instructions (referred to as IR from this point forward).

    Why serialize? There are some neat features possible because of serialization that I will mention in the Futures section of this post, but from a performance perspective the less foreign calls the better performance is. If this API had been performing potentially multiple foreign calls into C per syntax node the performance would slow down to a crawl.

    Let’s look at some current numbers. Here is JRuby loading all the bootstrapped files of Ruby and loading internal default gems (like rubygems) using our default parser (and with –dev to help improve startup time even more):

    time JRUBY_OPTS='--dev -Xparser.summary' jruby -e 1
    ----------------------------------------------------------------------
    Parser Statistics:
      Generic:
        parser type: Legacy
        bytes processed: 490245
        files parsed: 71
        evals parsed: 69
        time spent parsing(s): 0.115545746
        time spend parsing + building: 0.174647871
      IRBuild:
        build time: 0.059102125
    
    real	0m0.785s
    user	0m1.379s
    sys	0m0.150s
    

    We parsed 140 files/evals and we spent 0.115s parsing. Now let’s look at Prism:

    time JRUBY_OPTS='--dev -Xparser.summary -Xparser.prism' jruby -e 1
    ----------------------------------------------------------------------
    Parser Statistics:
      Generic:
        parser type: Prism(C)
        bytes processed: 681698
        files parsed: 71
        evals parsed: 69
        time spent parsing(s): 0.036817425
        time spend parsing + building: 0.093962833
      Prism:
        time C parse+serialize: 0.013102905
        time deserializing: 0.020535794
        serialized bytes: 381808
        serialized to source ratio: x0.5600838
      IRBuild:
        build time: 0.057145408
    
    real	0m0.700s
    user	0m1.224s
    sys	0m0.131s
    

    Same 140 files/evals but we did that parsing in 0.037s. So Prism is a little over 3x faster.

    Let’s try something larger like entering into a Rails console in a single model scaffolded app.

    Again using current parser:

    time echo exit | JRUBY_OPTS='--dev -Xparser.summary' jruby -S rails c
    Loading development environment (Rails 7.1.3.1)
    Switch to inspect mode.
    exit
    ----------------------------------------------------------------------
    Parser Statistics:
      Generic:
        parser type: Legacy
        bytes processed: 11250799
        files parsed: 1742
        evals parsed: 1672
        time spent parsing(s): 0.645997881
        time spend parsing + building: 0.9063163169999999
      IRBuild:
        build time: 0.260318436
    

    Now with Prism:

    time echo exit | JRUBY_OPTS='--dev -Xparser.summary -Xparser.prism' jruby -S rails c
    Loading development environment (Rails 7.1.3.1)
    Switch to inspect mode.
    exit
    ----------------------------------------------------------------------
    Parser Statistics:
      Generic:
        parser type: Prism(C)
        bytes processed: 11941034
        files parsed: 1742
        evals parsed: 1672
        time spent parsing(s): 0.36850959
        time spend parsing + building: 0.612780287
      Prism:
        time C parse+serialize: 0.211684276
        time deserializing: 0.145067202
        serialized bytes: 8044568
        serialized to source ratio: x0.6736911
      IRBuild:
        build time: 0.244270697
    

    Parsing goes from 0.645s to 0.369s. We can see that we have greatly reduced our parser overhead. I have not talked about our building of IR (see IRBuild time above) but we are doing some extra work to re-scan some text in Prism which will be going away (working around a bug). It will not make a huge difference but it will speed up even more.

    Speaking of bugs…

    Current State of JRuby and Prism

    I mentioned above that we can run many things out of the gate with where JRuby and Prism stand today. There are still unresolved issues. The only significant one is that some regular expressions with multiple byte characters are not properly decoding to be valid regexps. For example, in the Rails console example in the previous section I had to comment out part of a single regexp in reline to run to completion. This will be fixed very soon but it shows both how far Prism is (only a single thing commented out) and also that is not quite done yet.

    Two sanity CI Rake tasks we run are spec:ruby:fast and test:mri:core. These two suites hit enough tests to give us confidence that language and Ruby core libraries are working. Here are the results using Prism (with our current parser both of these would be 0F/0E):

    % rake spec:ruby:fast:prism
    
    # output removed
    
    3394 files, 29743 examples, 138683 expectations, 5 failures, 3 errors, 1109 tagged
    

    Not bad. Almost all of the errors are relatively unimportant things:

    • Mismatched error strings
    The rescue keyword raises SyntaxError when else is used without rescue and ensure ERROR
    Expected SyntaxError ((?-mix:else without rescue is useless))
    but got: SyntaxError ((eval):3: unexpected `else` in `begin` block; a `rescue` clause must precede `else`)
    
    • Missing warnings
    The defined? keyword when called with a method name in a void context warns about the void context when parsing it FAILED
    Expected warning to match: /warning: possibly useless use of defined\? in void context/
    but got: ""
    
    • Invalid syntax not getting marked as invalid
    The next statement in a method is invalid and raises a SyntaxError FAILED
    Expected SyntaxError but no exception was raised (:m was returned)
    

    In all three cases these are unlikely to break working code.

    Here is running subset of C Ruby’s test suite:

    % rake test:mri:core:int:prism
    
    # output removed
    
    4632 tests, 1863532 assertions, 41 failures, 3 errors, 18 skips
    

    The failing tests here are more of the same but mostly syntax which should fail but doesn’t. On JRuby’s side, there is still a single failing test involving keyword arguments but otherwise we are looking really good.

    I cannot underscore how quickly Prism is being developed. The problems shown here will probably be gone in another couple of weeks. Since JRuby is bundling Prism support as a gem you will be able to quickly update to a version of jruby-prism-parser as Prism updates come out.

    Futures

    Lazy method improvements

    JRuby will only build IR (JRuby’s internal representation) for methods if the method is actually called. For larger frameworks and libraries a majority methods will never be called. Using Prism, JRuby support laziness already but there are some larger potential for savings.

    In the current parsers, both will generate an entire syntax tree and only generate IR for the method portions if they are called. This means from a memory perspective we have a live sub-tree for the method sitting around in case we need to build it. From a time perspective it means generating sub-trees we may not use.

    Prism support also currently requires us to keep a copy of the original source to decode numbers (which has just gotten fixed in the last day but not released yet). Besides requiring us to keep more in memory this is holding back from “ultimate laziness (tm)”.

    So what is “ultimate laziness (tm)”? Remember I said when we call prism we get back a serialized representation of the syntax tree? The design of prism allows us to skip method sections of the serialized blob. That in turn means we can eliminate building up a syntax tree for the method unless it is ever called. We will instead just keep a reference to that section of the serialized blob.

    In this new scheme the serialized section is much smaller than the live tree presentation AND we eliminate the time spent to build that tree. This will shave off even more time from parsing and building.

    Serialization as pre-compilation format

    The serialized blob has had extra thought put into for saving it to disk. It is versioned. It saves all potential warnings in case you are running with warnings enabled. So we can just pre-compile all the base distribution files as serialized files and skip parsing altogether. We would only deserialize.

    We could also provide a tool for people to precompile their projects for faster loading. This could even be expanded to an endorsed format so that all Ruby implementations could ship serialized code to make everyone save parsing time.

    Web Assembly (Chicory)

    I mentioned how many projects have contributed to Prism and one cool option which happened as a result is that Prism is compiled to web assembly (wasm). The Java world has a project called Chicory which can run wasm in Pure-Java. JRuby and Chicory have worked together to demonstrate us being able to run using a wasm build of Prism. That works today (albeit as a WIP on a branch).

    Chicory is still only running as a simple interpreter and is ~6-7x slower than C (or if you look at the previous examples above ~3x slower than our current parser) but once they can JIT/AOT compile wasm then I expect this will be much closer to the C speed.

    This will give us an escape from maintaining a second parser so platforms which cannot call into a C library (or compile Prism) will continue to work. Luckily, for JRuby users, JRuby 10 will still ship with our old parser and Prism.

    Soon we will add this integration in so you can -Xjruby.parser.prism.wasm in our next major release of JRuby.

    Precompiled libraries

    For the common platforms we would like to precompile the shared library to reduce the need for people to have compilers in order to install the gem. Windows will likely be the first shipped binary as compilation on Windows is not as simple as MacOS or Linux (hint: install Mingw if you are a windows user). For now, compiler is a requirement to install the gem.

    Conclusion

    Prism is a big step forward for the Ruby community. It has been a lot of work to initially support this new parser in JRuby but it will make development going forward much simpler. The performance gains and other potential (like pre-compilation) will give us some new tricks to improve startup time even more.

    There have been many contributions to Prism and everyone who has worked on the project needs to be thanked. As I said earlier the broad range of interest is fascinating and a good indication that this was a project filling needs. Kevin Newton gets a special call-out because he has been so focused and positive in welcoming contributions that without him this project would not be so far along and moving at a break-neck speed.

  • Jruby Class Extension 9.3

    Published by on June 24, 2022

    = Generating Java Classes at Runtime with JRuby 9.3.4 Patrick Plenefisch :doctype: article :encoding: utf-8 :lang: en :toc: left :numbered: == Background There are many reasons people use the JRuby implementation of Ruby over MRI/CRuby: increased long-run performance, lock-free multi-threading, the ability to deliver code as a war file, and to integrate with Java libraries. I often find my use of JRuby via integrating with Java, and that's the topic of this post. First, what types of basic Java integration does JRuby currently provide? 1. Embedding JRuby in Java code (JSR-223) 2. Memory/GC integration 3. Marshaling values from Ruby to Java 4. Ruby code calling into Java 5. Marshaling values from Java to Ruby 6. Implementing interfaces so Java can call Ruby 7. Extending a Java class with a Ruby class (concrete extension) 8. Lowering a Ruby class into a JVM class at runtime (reification, `become_java!`) 9. The `jrubyc` class compiler that can generate (ahead of time) Java classes This post will principally investigate #7 and #8, and some of their recent changes in the JRuby 9.3.4 series. I shall assume a basic knowledge of how the JVM works, and a familiarity with Ruby. First, why would one want to do either #7 or #8? Number 7, henceforth referred to as concrete extension, should hopefully be more obvious, as lots of frameworks and libraries require extending a class, and doing so from Ruby code is simply more convenient when using JRuby than having to bundle an extra jar. Number 8, henceforth referred to as reification, is needed whenever a full JVM class is required, either for multi-interface support, or as a token. As a quick example, lets look at using Logback, a common Java logging framework. Logback (slf4j, really) requires a class as a token to get a logger. The Ruby version uses using concrete extension and reification together. NOTE: All examples in here use the `maven-require` gem to load maven dependencies interactively. Install it via `gem install maven-require` and then in each `irb` session or file, `require 'maven_require'` at the top. Note the differing gem name and require line. .Classic Java Usage of Logback [source,java] ---- import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class JavaPiList extends java.util.AbstractList { static Logger logger = LoggerFactory.getLogger(JavaPiList.class); int[] pi = {3,1,4,1,5,9}; public Integer get(int index) { logger.info("Getting index {}", index); return pi[index]; } public int size() { return pi.length; } public static void main(String[] args) { new JavaPiList().get(3); // => 12:34:56.789 [main] INFO JavaPiList - Getting index 3 } } ---- .Ported JRuby Usage of Logback [source,ruby] ---- require 'jruby/core_ext' # required for become_java! to do anything useful require 'maven_require' # load latest version of logback into this Ruby session maven_require "ch.qos.logback:logback-classic:RELEASE" class RubyPiList < java.util.AbstractList def initialize @pi = [3,1,4,1,5,9] end def get(index) Logger.info("Getting index {}", index) return @pi[index] end def size() @pi.length end # Ensure this class is reified become_java! Logger = org.slf4j.LoggerFactory.get_logger(RubyPiList.java_class) end RubyPiList.new.get(3) # => 12:34:56.789 [main] INFO rubyobj.RubyPiList - Getting index 3 ---- Neat! How is this implemented under the hood in JRuby? We can take a look at the generated classes to find out. But first, we must save the classes generated to a disk somewhere. Luckily, this is easy to do selectively by passing a directory to `become_java!`, and the generated class will be saved under it: .Saving class files [source,ruby] ---- become_java!("/tmp/jruby-dump-folder") ---- NOTE: For some of the examples here I've taken the JVM bytecode generated, and run it through the https://github.com/JetBrains/intellij-community/tree/master/plugins/java-decompiler/engine[FernFlower] decompiler. The code you see may not compile, and those seeking a deeper understanding are encouraged to explore the disassembled JVM bytecode directly. I recommend https://bytecodeviewer.com/[Bytecode Viewer] as it's what I used to develop these improvements to JRuby. Now, we can look at the decompiled MyRubyClass that JRuby generated for us: .Generated MyRubyClass (decompiled) [source,java] ---- public class RubyPiList extends AbstractList implements ReifiedJavaProxy { private synthetic final ConcreteJavaProxy this$rubyObject; // ...bookkeeping fields snipped... // ...constructors snipped... public int size() { this.this$rubyObject.ensureThis(this); return ((Number)this.this$rubyObject.callMethod("size", IRubyObject.NULL_ARRAY).toJava(Integer.TYPE)).intValue(); } public Object get(int var1) { this.this$rubyObject.ensureThis(this); return (Object)this.this$rubyObject.callMethod("get", new IRubyObject[]{ JavaUtil.convertJavaToRuby(ruby, var1) }).toJava(Object.class); } // ...bookkeeping methods snipped... } ---- Here we can see several important facts. First, this is just a proxy for a Ruby class. As the Java class just delegate everything to the Ruby object, all the logic can still be swapped around via monkey patching and it is still dynamic under the hood. The Java class is merely an interface to the Ruby class. Second, there is lots of internal JRuby bookkeeping present, so performance may be lower. Third, all instance variables are not lowered to fields and are still Ruby-private. And fourth, the method signatures were picked up from the superclass. For most JRuby Java integrations this is fine, but sometimes you need to add some more flair to your generated classes. Let us investigate three separate ways to upgrade our integration game with JRuby 9.3.4 improvements to concrete reification: 1. Java-callable constructors 2. Fields 3. Annotations == Constructors The first issue I ever filed against JRuby was about the lack of java-callable constructors for java-extending classes (concrete extension), in 2012. One anagram and 8½ years later, it was finally closed in 2021, as my implementation was merged into JRuby 9.3.0. What caused me to file the issue, and still want it done in 2021? JavaFX, or more specifically, the JRuby bindings of JavaFX, JRubyFX. JavaFX is a cross-platform GUI toolkit, and my usual go-to for GUI work when I'm writing Ruby. One of the features that drew me to JavaFX is SceneBuilder, a drag-and-drop GUI designer that produces a runtime-loadable XML (cleverly called FXML) description of the GUI layout. While it's possible to use JavaFX/JRubyFX without FXML (and indeed most of the people using JRubyFX seem to not use it), FXML is very useful. Supporting FXML in JRubyFX was tricky, as the JavaFX `FXMLLoader` reads the FXML to build classes and set fields. It does this by using reflection to call the no-arg constructor of the named class in the FXML. This is where I ran into trouble in 2012, but is now fixed, as of JRuby 9.3.1 (and utilized in JRubyFX 2.0). If you want to be able to call a constructor from Java for a Ruby class extending a Java class, now you can do so, and it's configurable: .Simple Construction Example [source,ruby] ---- require 'jruby/core_ext' # required for become_java! to do anything useful class ChaosParrot < java.io.InputStream def initialize() puts "ChaosParrot was initialized" @percent = 0.1 end java_signature 'void setPercent(float)' def setPercent(pct) puts "Got percent: #{pct}" @percent = pct end java_signature 'void setStream(java.io.InputStream)' def setStream(underlying) puts "Got new stream" @underlying = underlying end # no java_signature necessary here, as it uses the inherited signatures def read(*args) # for other signatures, use parent return super.read(*args) unless args.empty? # corrupt bytes randomly, as configured return rand(256) ^ @underlying.read if rand <= @percent @underlying.read end new # if you directly `new` the class, become_java! # is called if necessary for concrete-extension classes # but you can always ensure it by calling become_java! directly end # call the constructor via Java Reflection API's us = ChaosParrot.java_class.constructor().newInstance # => ChaosParrot was initialized us # => # ---- This means that you can now use any Java object-construction libraries. Here is a contrived continuation of this example using Spring to construct Ruby objects: NOTE: We use `ChaosParrot.java_class.name` to get the full name, as the `rubyobj` package is not considered stable release-to-release. CAUTION: We also must pass in an appropriate classloader. See below for issues related to classloading reified classes (both concrete and normal) from java. .Instantiating Ruby Objects from Java via Spring [source,ruby] ---- # ChaosParrot code from above continues here maven_require 'org.springframework', 'spring-context','5.3.16' require 'tempfile' Tempfile.open("beans.xml") do |beanxml| File.write(beanxml.path, %Q| |) ctx = org.springframework.context.support.FileSystemXmlApplicationContext.new ctx.config_location = "file:#{beanxml.path}" ctx.class_loader = ChaosParrot.java_class.class_loader # See below about classloaders ctx.refresh # load the beans! # => ChaosParrot was initialized # => Got percent: 0.25 # ...do stuff with ctx end ---- TIP: Getting type conversion errors about IRubyObject? Ensure you required `require 'jruby/core_ext'` as it is a no-op by default for `jrubyc` compatibility. Dumping the generated class shows us the method that JRuby generates: .Generated ChaosParrot Structure (disassembled with javap) [source,java] ---- public class rubyobj.ChaosParrot extends InputStream implements ReifiedJavaProxy { // Java-reflection constructor public ChaosParrot(); // Internal JRuby constructors (::new) public ChaosParrot(Ruby, RubyClass); public synthetic ChaosParrot(ConcreteJavaProxy, IRubyObject[], Block, Ruby, RubyClass); protected synthetic ChaosParrot(ConcreteJavaProxy, boolean, IRubyObject[], Block, Ruby, RubyClass); public static {}; // Our new methods public void setStream(InputStream); public void setPercent(float); // Overrides for read (all overloads always added) public int read(); public int read(byte...); public int read(byte[], int, int); // bridge methods so super works (Internal JRuby implementation details) // Note only 2 here, as read() is abstract in the parent public bridge synthetic int __super$\=rubyobj\,ChaosParrot$read(byte[]); public bridge synthetic int __super$\=rubyobj\,ChaosParrot$read(byte[], int, int); // internal JRuby API (ReifiedJavaProxy) public synthetic IRubyObject ___jruby$rubyObject(); public synthetic JavaProxyClass ___jruby$proxyClass(); } ---- CAUTION: Because internally JRuby has the proxy Java class, as well as the Ruby class, and it needs to initialize both of them no matter if initialized from Ruby code via `::new` or Java code via `newInstance`, a limitation currently applies to `super(...)` calls in the configured constructor method (typically `initialize`, see below): there can be at most one `super(...)`, with no conditionals over it. TIP: If you are curious how these two halves are initialized together, https://github.com/jruby/jruby/pull/6422#issuecomment-748414730[this initialization diagram] is a good place to start One potentially tricky thing, is that of which method to call in initialization. This is particularly acute for JavaFX as the "fxml is loaded" method is called `initialize`, shadowing the Ruby constructor of the same name. Luckily, the new constructor support in 9.3 allows reconfiguring many aspects of this interaction, owing to the fact that it is merely a proxy generator for Java. In the example below, the method defined as `#initialize` is never used, as `::new` has been redefined (via `configure_java_class`) to call `#java_ctor`, and calling `.initialize` from Java is re-routed to `#normal_method`. By default JRuby, excludes `#initialize` from generation, so we must explicitly include it here. CAUTION: Class configuration using `configure_java_class` is only fully enabled for concrete extension (aka Ruby-subclassing-Java) as of 9.3.4. Non-concrete extension (no Java superclasses) is not fully enabled. There is a bug about this https://github.com/jruby/jruby/issues/7122[issue #7122]. .Configuring Java Proxy Class Generation Parameters [source,ruby] ---- require 'jruby/core_ext' # required for become_java! to do anything useful # configuring classes only works for concrete classes right now (JRuby 9.3.4) # so we extends java.lang.Object to force this to be a concrete-extended class class ConfiguredProxy < java.lang.Object def initialize puts "I shouldn't be called" end def java_ctor puts "The ctor was called" end def standard_method puts "The non-ctor was called" end configure_java_class(ctor_name: "java_ctor") do dispatch :initialize, :standard_method # java initialize will call standard_method include :initialize # excluded by default end become_java! end ConfiguredProxy.new # => The ctor was called inst = ConfiguredProxy.java_class.constructor().newInstance # => The ctor was called ConfiguredProxy.java_class.get_method("initialize").invoke(inst) # => The non-ctor was called # you can stil call standard_method directly too, since # it wasn't excluded or redefined ConfiguredProxy.java_class.get_method("standard_method").invoke(inst) # => The non-ctor was called ---- Decompiling the result shows that some of our changes (`dispatch`, `include`) are baked into the class file itself, while others (`ctor_name`) can still be edited after class generation: .Generated ConfiguredProxy (decompiled) [source,java] ---- public class ConfiguredProxy implements ReifiedJavaProxy { // ...bookkeeping fields snipped... (see end for full listing) // ...some constructors snipped... // Java no-arg constructor public ConfiguredProxy() { this(new ConcreteJavaProxy(ruby, rubyClass), false, IRubyObject.NULL_ARRAY, Block.NULL_BLOCK, ruby, rubyClass); } protected synthetic ConfiguredProxy(ConcreteJavaProxy var1, boolean var2, IRubyObject[] var3, Block var4, Ruby var5, RubyClass var6) { this.this$rubyObject = var1; // the splitInitialized & finishInitialize calls here will invoke whichever // ruby method is configured as :ctor_name in configure_java_class SplitCtorData state = var1.splitInitialized(var2 ? rubyClass : var6, var3, var4, this$rubyCtorCache); // snipped bookkeeping... super(); var1.setObject(this); var1.finishInitialize(state); // snipped bookkeeping... } // Since we didn't specify the signature, it returns // Ruby objects as the default public IRubyObject standard_method() { this.this$rubyObject.ensureThis(this); return this.this$rubyObject.callMethod("standard_method"); } // the configured dispatch is seen here, dispatching // to a differently-named method public IRubyObject initialize() { this.this$rubyObject.ensureThis(this); return this.this$rubyObject.callMethod("standard_method"); } // No dispatch configuration, uses same name public IRubyObject java_ctor() { this.this$rubyObject.ensureThis(this); return this.this$rubyObject.callMethod("java_ctor"); } // ...bookkeeping methods snipped... } ---- == Fields Java/JVM fields and Ruby instance variables are different: fields are fixed, and can be public, protected, or private, while instance variables are only protected, but are dynamic. Nonetheless, when porting Java code to Ruby, or vice-versa, they are typically replaced with each other. JRuby, however, exposes fields differently than instance variables. Fields are accessed by named getters and setters on self, and not related to instance variables (you can set a field and an instance variable of the same name to different values!). If you are accessing existing Java objects this is one thing, but how do you create a Java field on a reified Ruby object, whether concrete-extended or not? With `java_field`. Here is a contrived example using Jackson, a JSON serializer for Java (Please use one of the ruby serializers in real code, this is just an example of a java library reading fields): .Serializing Reified Ruby Classes with Jackson [source,ruby] ---- require 'jruby/core_ext' # required for become_java! to do anything useful maven_require 'com.fasterxml.jackson.core:jackson-databind' # If we are a pure ruby class, internal JRuby fields will be present. # To avoid unnecessary methods and fields on the resulting Java Class, # we decend from Java Object, not Ruby Object class FieldedClass < java.lang.Object java_field 'java.lang.String mystr' def initialize(mystr = nil) super() # j.l.Object requires no args self.mystr = mystr if mystr != nil end become_java! end om = com.fasterxml.jackson.databind.ObjectMapper.new str = om.write_value_as_string(FieldedClass.new("foo")) # => "{\"mystr\": \"foo\"} om.read_value(str, FieldedClass.java_class).mystr # => "foo" ---- This isn't very idiomatic Ruby. If we are willing to sacrifice some of the expected semantics of ruby instance variables, we can, as of JRuby 9.3.4, tie the instance variables and the fields together. Instead of being able to store two different values in `@name` and `self.name`, they are aliases .Serializing Reified Ruby Classes with Jackson, using Instance Variables [source,ruby] ---- class InstancedClass < java.lang.Object java_field 'java.lang.String mystr', instance_variable: true def initialize(mystr = nil) super() @mystr = mystr if mystr != nil end become_java! end str = om.write_value_as_string(InstancedClass.new("foo")) # => "{\"mystr\": \"foo\"} om.read_value(str, InstancedClass.java_class).mystr # => "foo" ---- CAUTION: `@name.equals?(@name)` may be false in some cases when using this configuration CAUTION: A frozen object can have all instance variables using this configuration modified. Instance variables using this configuration do not respect if an object is frozen or not. CAUTION: JVM semantics, not Ruby Semantics, apply when using this configuration Disassembling, we see this has no affect on the generated proxy class: .Generated InstancedClass & FieldedClass Structure (disassembled with javap) [source,java] ---- public class FieldedClass implements ReifiedJavaProxy { public java.lang.String mystr; public FieldedClass(); // snipped internal ctors and internal JRuby API methods } public class InstancedClass implements ReifiedJavaProxy { public java.lang.String mystr; public InstancedClass(); // snipped internal ctors and internal JRuby API methods } ---- == Annotations JRuby 9.3 partly unified the annotation API between `become_java!` on a pure-ruby class, a concrete-extension Ruby class, and using `jrubyc` (class-methods only, package and class annotations are not mutually supported). Now the class methods work equally well and with the same syntax: [source, ruby] ---- class MyClass java_field 'full.Type name' java_field '@full.Annotation() full.Type name' java_signature 'full.Type myMethod(primitive, full.Type)' java_signature '@full.Annotation() full.Type myMethod(primitive, full.Type)' def myMethod(*args) #... end end ---- We can extend the example from the previous section to have annotations that affect the behavior of Java libraries: .Annotations on Generated Java Classes with Jackson [source, ruby] ---- maven_require 'com.fasterxml.jackson.core', 'jackson-databind' # we extend the Java Object for the same reasons as the previuos example class AnnotatedClass < java.lang.Object # Note we can't use java_annotation ouside of the class, that is jrubyc only add_class_annotations com.fasterxml.jackson.annotation.JsonRootName => {"value" => "user"} java_field '@com.fasterxml.jackson.annotation.JsonIgnore java.lang.String mystr' java_field 'int myint' java_signature '@com.fasterxml.jackson.annotation.JsonSetter(value="phantom") void printItOut(boolean)' def printItOut(p) puts "Phantom set to: #{p}" end become_java! end om = com.fasterxml.jackson.databind.ObjectMapper.new om.enable(com.fasterxml.jackson.databind.SerializationFeature::WRAP_ROOT_VALUE) om.write_value_as_string(AnnotatedClass.new.tap{|x|x.myint=9}) # => "{\"user\":{\"myint\":9}}" ac = om.read_value('{"myint":314,"phantom":true}', AnnotatedClass.java_class) # Phantom set to: true ac.myint # => 314 ---- TIP: Can I avoid typing the package name of the class? Not as of JRuby 9.3. It is https://github.com/jruby/jruby/issues/5486[issue #5486] Examining the generated class, we can see it did annotate as we requested: .Generated AnnotatedClass Structure (decompiled) [source,java] ---- @JsonRootName("user") public class AnnotatedClass implements ReifiedJavaProxy { // snipped private implementation fields @JsonIgnore public String mystr; public int myint; @JsonSetter("phantom") public void printItOut(boolean var1) { // ... } // snipped internal JRuby API parts } ---- == JRubyFX 2.0 After all of these changes in JRuby 9.3.4, the JRubyFX gem can finally dump its FXML hacks and use the existing FXMLLoader by taking advantage of these new features. So, how does JRubyFX use these features for loading FXML? Every request for loading FXML starts by us loading the file and pulling out all the expected field names from the `fx:id` attributes, and the `onEvent` expected event handlers For each of these names, we call java_field with the FXML annotation, field name, and request that the instance variables are mapped to the fields. This makes the API seem more Ruby-like while two copies of variables. Additionally, most of the pitfalls are likely avoided as these instance variables are typically read, not written, once the FXML file has been loaded. For each of the event handlers, we define an appropriate event handler method using `java_method` with the fxml annotation and event handler name We configure the class for a Java-accessible constructor We call `become_java!` and pass the concrete-extended reified class off to the JavaFX FXMLLoader As such, users can experience a straightforward integration experience. For example, while the JVM class is a static and unchangeable interface, by defining all the expected methods and fields, user Ruby code can muck with the class as long as those methods stay defined. Here are some snippets of the above features when integrated into JRubyFX use. Plus, some of the interesting bits of the JRubyFX implementation. See the full working example these were taken from under https://github.com/jruby/jrubyfx/tree/master/samples/contrib/fxmltableview[samples/contrib/fxmltableview]. TIP: I recommend using Zulu+FX JDK builds for JRubyFX as it is pre-packaged with JavaFX, but any JDK with JavaFX should work (Java 8 and later) .Fragments of fxmlloader JRubyFX example & JRubyFX implementation [source, ruby] ---- # user usage class FormattedTableCellFactory include Java::javafx.util.Callback include JRubyFX # see below for fxml_raw_accessor definition fxml_raw_accessor :alignment, Java::javafx.scene.text.TextAlignment fxml_raw_accessor :format, java.text.Format def call(param) cell = FormattedTableCellFactory_TableCell.new(@format) cell.setTextAlignment(@alignment) # ... end # ... end # library definition module JRubyFX # ... def fxml_raw_accessor(symbol_name, type=java::lang::String) # ... # fieldNameGetType() is an extention to standard bean style # getters/setters in JavaFX java_signature "java.lang.Class " + symbol_name.id2name + "GetType()" send(:define_method, symbol_name.id2name + "GetType") do return type.java_class end # define the field as fxml-capable java_field "@javafx.fxml.FXML #{type.java_class.name} #{symbol_name}", instance_variable: true end end # user usage class FXMLTableViewController include JRubyFX::Controller # this method call defines all the methods and fields in the provided file fxml "fxml_tableview.fxml" # event handler from the fxml def addPerson # the tableview and the fields are # accessable as instance variables data = @tableView.items data.add(Person.new(@firstNameField.text, ...)) @firstNameField.text = "" # ... end # ... end # library definition module JRubyFX::FxmlHelper # ... def self.transform(clazz, ...) # called by fxml in the user code above # ... while xmlStreamReader.hasNext # lots of xml processing ... # if it is an id, save the id and annotate it as injectable by JavaFX. Default to object since the FXMLLoader doesn't care... if localName == "id" and prefix == FXMLLoader::FX_NAMESPACE_PREFIX clazz.instance_eval do # Note: we could detect the type, but Ruby doesn't care, and neither does JavaFX's FXMLLoader java_field "@javafx.fxml.FXML java.lang.Object #{value}", instance_variable: true end # otherwise, if it is an event, add a forwarding call elsif localName.start_with? "on" and value.start_with? "#" name = value[1..-1] # strip hash clazz.instance_eval do # add the fxml signature and correct param count java_signature "@javafx.fxml.FXML void #{name}(javafx.event.Event)" end end # ... end # ... clazz.become_java! end end ---- .fxmltableview sample FXML selection (fxml_tableview.fxml) [source, xml] ----
  • Performance Improvements in JRuby 9.0.3.0

    Published by Charles Oliver Nutter on October 21, 2015

    With the release of JRuby 9000, we promised you’d see our new runtime start to shine in update releases. Now, it’s starting to happen.

    JRuby 9.0.3.0 has been released with three key performance improvements we’re very excited about.

    Lightweight Postfix Rescues

    One of the most convenient anti-patterns in Ruby is the ability to add a rescue to any expression, capturing all StandardError descendants and instead returning another expression. You see this pattern a lot in code where any exception raised has a trivial fallback.

    Unfortunately, exceptions can be very expensive on the JVM. For various reasons, when the JVM generates a stack trace, it has to do much more work than a runtime like CRuby: combining interpreted calls and compiled calls, breaking apart inlined code, omitting or reformatting internal calls. Generating a 1000-deep stack trace on the JVM can cost in the neighborhood of a few milliseconds.

    This doesn’t sound like a lot until you start raising thousands of exceptions every second.

    Here’s an example from csv.rb, Ruby’s standard library for CSV parsing.

      Converters  = { integer:   lambda { |f|
                        Integer(f.encode(ConverterEncoding)) rescue f
                      },
                      float:     lambda { |f|
                        Float(f.encode(ConverterEncoding)) rescue f
                      },
    ...
    

    Ruby’s CSV library can automatically convert values to Ruby types as they are read. It does this by cascading attempts from one converter to the next using trivial rescues to capture any errors. Each converter executes in turn until one of them is able to convert the incoming data successfully.

    Unfortunately, before 9.0.3.0, this had a tremendous impact on performance. Every exception raised here had to generate a very expensive stack trace…ultimately causing CSV value conversions to spend all their time in the guts of the JVM processing stack trace frames.

    We received a bug report showing JRuby processing and converting CSV almost 30x slower than CRuby, and we knew we had to do something.

    Luckily, with our new runtime, it was easy for to make improvements. Credit goes to Tom Enebo for this excellent work:

    • Inspect the expression provided for a rescue to see if it is trivial (local variable, constant value, etc).
    • If trivial, entering the rescued code sets a thread-local flag indicating no stack trace will be needed.
    • When raising exceptions, we can now omit stack traces we know will never be used.

    The result? Trivial rescues are now over 40x faster than before and JRuby handles CSV with conversions considerably faster than CRuby.

    Note that this optimization only works when the lightweight rescue is directly upstream from the exception it captures. If there are intevening heavyweight rescues, we can’t optimize the stack trace away.

    Independently Jitting Blocks

    You can see from the CSV code snippit above that the converters are held in a hash mapping symbols to lambda expressions. This was another case that needed fixing.

    JRuby’s JIT has always occurred at method boundaries. If a method is called enough times, we compile it to JVM bytecode. However, there are libraries like CSV where the hot code is not contained within a method…it is a free-standing lambda or proc defined in a script or class body. Because of the limitations of our old JIT, this code would only run in the interpreter, which is generally many times slower than compiled JVM bytecode.

    This is frequently compounded by the metaprogramming method Module#define_method, which allows you to define a new method using only a Ruby block. These definitions usually don’t occur within a method (or at least not within a method we JIT), so they too would never JIT.

    In JRuby 9.0.3.0, I finally fixed this by modifying blocks to have their own independent call counters and JIT cycle. If a block is called enough times (currently the same 50-call threshold as methods), they will JIT into JVM bytecode even if the surrounding scope does not. We’ve promised this for years, but it wasn’t until our new runtime that we were able to make it possible.

    This improvement makes formerly unjittable blocks anywhere from 5x to 20x faster than they were before.

    And speaking of define_method…

    define_method Methods

    For years we’ve wanted to be able to optimize define_method methods just like regular methods. The block JIT changes above certainly help that, but it is well known that blocks still have a more overhead (lexical context, heap-based local variables) than regular method bodies.

    Once again our new runtime comes to the rescue. Thanks to additional work by Tom, JRuby 9.0.3.0 will now optimize non-capturing define_method methods (i.e. those that do not access variables from their lexical enclosure) as if they were normal methods. No extra context must be managed, no variables need to go on the heap, and all optimizations that apply to methods work just fine.

    For cases where this optimization applies, you’ll see almost no difference in performance between a define_method method and one defined with the def keyword.

    We don’t plan to stop here, either. For future releases, we plan to make capturing define_method methods also optimize like regular methods, modulo any context we can’t optimize away. Ideally, these methods should have only a small amount of overhead (or none at all) compared to their regular non-metaprogrammed siblings.

    More to Come

    We’re very happy with how JRuby 9000 has been received (our most stable, most compatible, and fastest JRuby ever) and we’ll continue to push the limits of what Ruby can do on the JVM (and what Ruby can do in general).

    We’d love to hear what you’re doing with Ruby and JRuby and encourage you to join our community!

  • JRuby 9000

    Published by The JRuby Team on July 22, 2015

    After years of work, we’re proud to announce the release of JRuby 9000!

    JRuby is an implementation of the Ruby programming language atop the Java virtual machine, bringing true parallelism, increased performance, and top-notch garbage collectors to the Ruby world. You can call into other JVM languages, deploy on Java servers, and take advantage of the massive Java tooling ecosystem. At the same time, “It’s Just Ruby”… we pride ourselves on compatibility and on being a Ruby implementation first, and a JVM language second.

    We’ve put an enormous amount of effort into this release, and we wanted to share with you why we’re so excited.

    Compatibility

    During JRuby 1.7.x we had the brilliant idea to support multiple compatibility levels of Ruby from the same runtime. If you passed ‘–1.8’ you would be running JRuby in 1.8.7 compatibility mode. Passing ‘–1.9’ would be running in1.9.3 compatibility mode.

    As it turned out this ended up being extremely messy internally. We were forced to start versioning method names (e.g. inspect or inspect19). We would get bug reports where we had a 1.9 method calling a 1.8 method which did the wrong thing. We confused people making native extensions – “which method do I call?” In hindsight, this idea was too difficult to maintain.

    For JRuby 9000 we only support a single version of Ruby. For 9.0.0.0 we will support Ruby 2.2, the current version of Ruby. As new versions of Ruby come out you should expect to see a version of JRuby come out that supports the same features.

    Versioning

    JRuby 9000 is the ninth major release of JRuby. We opted to go with 9000 as a code name and 9.0.0.0 as a version number to separate it from Ruby’s version numbers (1.8, 1.9, 2.0 etc). We frequently ran into confusion about our version numbers versus Ruby’s, and neither “1.8” nor “2.0” would do anything but make that worse.

    Going forward, expect to see maintenance releases versioned as 9.0.x and Ruby compatibility updates numbered as 9.x.

    New Runtime

    More than five years ago Subramanya Sastry (subbu) expressed an interest in helping us work on a new runtime for JRuby. It was based, in part, on his PhD experience designing a static optimizing compiler for Java. From this beginning, we have worked with subbu to build a new runtime (called IR) which will look pretty familiar to anyone who has ever taken a compiler course in college.

    For JRuby 9000, this new runtime runs things about as fast as JRuby 1.7 but we have years worth of plans for improving performance. At this point, we are only executing conservative static optimizations. Over the next several months we will start enabling profiled optimizations and things will start to get exciting. The ability to perform more aggressive optimizations like unboxed math and inlining methods and the blocks they call will open up an entire new dimension for JRuby’s performance.

    IR is the beginning of a new road for performance for JRuby. We hope to ship continual performance improvements during our point releases.

    Native Process and IO

    During the JRuby 9000 dev cycle, we decided it was time to improve the POSIX behavior of our Process and IO subsystems. In C Ruby, IO and Process are implemented directly atop the standard C library functions. As a result, they reflect behaviors often hidden when running Java applications, where those APIs are wrapped in many layers of abstraction. For example, a subprocess launched from Java can’t be read from in a nonblocking way, can’t be signaled, can’t inherit open files and from the parent process, and many other limitations. In short, we realized we’d need to go native to be truly compatible.

    JRuby 9000 now uses native operations for much of IO and almost all of Process. This makes us the first POSIX-friendly JVM language, with full support for spawning processes, inheriting open streams, perfoming nonblocking operations on all types of IO, and generally fitting well into a POSIX environment.

    Years of Work

    We first started talking about the next JRuby a few years ago, and the IR work started years before that. JRuby 9000 represents the largest (by far!) release we’ve ever done.

    • Just counting the time since we branched, there have been over 5500 commits by 104 contributors. That’s a rate of 7 commits per day for two years.
    • We fixed 468 issues during our preview and release candidate cycle. Your bug reports were crucial to delivering a high quality release.

    With all the work that has gone into JRuby 9000, we’re very proud of what we’ve achieved.

    Installing JRuby

    JRuby 9000 can be installed in the same ways as previous versions. If you are using Windows, we recommend the Windows Executable installer. If you are using Linux or Mac OS X, we recommend using RVM by running the command rvm install jruby-9.0.0.0.

    You can also install the JRuby 9000 binaries by downloading the latest TAR or ZIP file from the JRuby Downloads page, and putting the bin directory on your PATH. For more information on installing JRuby, see the Getting Started with JRuby guide on the Wiki.

    Your Turn

    We’re a very friendly community and we welcome all users to our mailing list, our IRC channel (#jruby on Freenode), and our team Twitter account. File bugs against our Github project and check out our community page for more information.

    Welcome to the future…JRuby 9000 is here!

  • A Truffle/Graal High Performance Backend for JRuby

    Published by Chris Seaton on January 06, 2014

    For the past year Oracle Labs have been working on an implementation of Ruby built upon two new JVM technologies - the Truffle AST interpreter framework and the Graal JVM compiler. We believe that the new approach will lead to a faster and simpler Ruby implementation.

    We’ve been talking to Charles Nutter and Thomas Enebo for several months and have given them early access to our code. We’ve also been talking to other Ruby implementors such as Alex Gaynor of Topaz, and presenting our results to the JVM language community at the JVM language summit. Today we are open sourcing our implementation and, with the consent of Charles and Thomas, pushing a patch that begins the integration as an optional backend in JRuby.

    This blog post describes some of the background to this project. The original code is available in the Graal Mercurial repository and the patch to JRuby is available in a new truffle branch in the JRuby Git repository. There is documentation of how to use the code and an FAQ in the JRuby wiki, as well as pointers to more in-depth technical information such as peer-reviewed research publications.

    What does this new implementation do differently?

    The new backend is an AST interpreter. We call it the Truffle backend because it’s written using the Truffle framework for writing AST interpreters from Oracle Labs.

    Truffle is different to other AST interpreters in that it creates ASTs that specialize as they execute. The AST interpretation methods that are currently in JRuby are megamorphic, which means that they must handle all possible types and other dynamic conditions such as branches taken. In Truffle, AST nodes ideally handle a minimal set of conditions, allowing them to be simpler and more statically typed, which can lead to more efficient code. In the less common case that the node’s conditions aren’t met the node is replaced with another node that can handle them.

    AST interpreters are generally thought of as being slow. This is because every operation becomes something such as a virtual method call. MRI 1.8 used a simple AST interpreter, and JRuby still uses an AST interpreter by default for the first run of methods. To improve performance many language implementations convert the AST to bytecode. Python, Ruby 1.9 and above (via YARV) and PHP all do this. Normally the bytecode is still interpreted, but it’s often faster as the data structure is more compactly represented in memory. In the case of many JVM languages like JRuby and other Ruby implementations such as Topaz and Rubinius, this bytecode is eventually compiled into machine code by the JIT compiler.

    Again, Truffle takes a different approach here. When running on JVM with the Graal JIT compiler, Truffle will take all of the methods involved in interpreting your AST and will combine them into a single method. The powerful optimisations that the JVM usually applies to single methods are applied across the combined AST methods and a single machine code function per Ruby method is emitted by Graal.

    For more information about what Truffle and Graal do see the JRuby wiki page, the a recent project summary slide deck.

    Is this going to change with how I use JRuby today?

    The Truffle backend, Truffle itself, and Graal are research projects and are certainly not ready for general use today. It is very unlikely that your application or gem will run right now, but if you are interested in the JRuby internals, or the JVM or compiler technology in general we’d encourage you to take a look at what we’re doing. The JRuby wiki page will give you a starting point.

    For the foreseeable future this work is going to live on a separate truffle branch in the main JRuby Git repository. It is possible that this branch will be considered for merging into the master branch before the next major release, JRuby 9000, but this a decision for the wider JRuby community and its leadership.

    We believe that in the further future the Truffle backend could be good enough to become the default backend for JRuby, but again this is a decision for the JRuby community.

    What are we going to do next?

    We are going to continue to integrate Truffle into JRuby at the same time as continuing to implement more of the Ruby language. We already have very encouraging results with our initial implementation and with the excellent work already done by the JRuby community we think we can fill in the gaps to be a complete implementation.

  • JRuby Stickers now available

    Published by Hiro Asari on January 05, 2014

    JRuby stickers are now ready for shipping!

    JRuby Stickers

    If you want one, fill out the form and send $2 for each sticker via Square Cash to [email protected].

    Additionally, we will be handing them out when some of the core members attend the upcoming conferences.

  • A Last Hurrah For JRuby 1.6

    Published by Charles Oliver Nutter on August 27, 2012

    Summer is wrapping up and the JRuby team is busy putting the finishing touches on JRuby 1.7, our next major release. How major? It has taken us almost 1.5 years to get to this point. That’s major.

    Of course, we weren’t sitting on our hands that whole time. For about 8 months after the release of JRuby 1.6 last year, we continued putting out point releases to catch bugs, improve Ruby 1.9 support, and fix performance and concurrency issues you faithful JRuby users reported. Even as late as the waning days of 2011, we were putting out security-fix releases like JRuby 1.6.7.2.

    But as of today, it has been eight months since a proper JRuby release. That’s too long.

    JRuby 1.7 has had two preview releases, the most recent a couple weeks ago. And JRuby 1.7 final is scheduled to come out toward the end of September. There are already users with 1.7 in production, and we’re confident it’s going to be an amazing release. But we also recognize that many users are still on JRuby 1.6 and may not be able to migrate for some time.

    So, by popular demand, we’re going to release JRuby 1.6.8!

    This release will be a bit of an experiment in that the core JRuby team will not directly contribute to it. We’re looking to community members like you to backport interesting fixes from JRuby 1.7 (or just come up with new fixes, where the 1.7 versions require extensive work). We will run our usual slate of release testing and actually do the legwork of putting out release artifacts, but this version of JRuby is yours to make what you will!

    We’d like to get JRuby 1.6.8 out soon…like the end of next week. Here’s how you can help:

    • If you are running a patched version of JRuby 1.6.x right now, sort out the patches you need and send us pull requests against the jruby-1_6 branch on Github.

    • If you know of fixes from 1.7 you need on your 1.6-based systems, do the same thing, ideally by using git format-patch so the original committer is associated with the pull request.

    • Make sure your changes pass at least the following test runs: “ant test-extended”, “rake spec:ci_interpreted_18”, and “rake spec:ci_interpreted_19”. If the patch affects the compiler, you might want to run the “compiled” version of the “spec:ci” targets.

    We will then have a look at your pull request, merge it in, and look at a full JRuby 1.6.8 release in about two weeks.

    If you’d like to try out early builds of JRuby 1.6.8, you can download dev artifacts from JRuby’s CI server.

    JRuby 1.6.8 will really, truly be the last in the 1.6.x line, so this is your chance to make it a good transition before JRuby 1.7. Now go forth and backport patches!

  • Bridging The Gap With JRuby

    Published by Brian Ploetz on May 18, 2012

    The only things certain in life are death, taxes, and your technology stack will change over time. While architectural changes are complicated in their own right, the challenges are even greater when your primary data store is changing to a fundamentally different technology.

    A recent project involved migrating applications from a legacy architecture based on Java/Hibernate/Oracle to a new architecture based on Ruby/MongoMapper/MongoDB. In order to facilitate the transition from Oracle to MongoDB, we needed a temporary ETL solution to migrate data from Oracle to MongoDB. A new domain model and document structure had been designed and developed for MongoDB with Ruby/MongoMapper, and there were existing Java/Hibernate entities mapped to Oracle.

    Rather than having to re-map one database or the other in the other persistence technology to facilitate the ETL process (not DRY), JRuby allowed the two persistence technologies to interoperate. By utilizing JRuby’s powerful embedding capabilities, we were able to read data out of Oracle via Hibernate and write data to MongoDB via MongoMapper.

    Example Domain Model

    To demonstrate the RDMBS to MongoDB ETL process, consider the ubiquitous blog domain model.

    blog domain model

    A Blog contains many Posts, and a Post contains many Comments. Users create Posts and Comments. The relational model for this domain model would look something like this:

    blog ER diagram

    The schema is highly normalized. Entities live in their own tables, and are tied together via foreign keys.

    With document databases like MongoDB, you typically want to denormalize data according to your access patterns, as you can’t rely on joins. In our example blog domain model, storing posts and comments in separate collections would result in unnecessary querying. Thus, these will become embedded collections within their respective parent documents, and our resulting Blog MongoDB document would look something like this:

    posts is an embedded collection within a blog document, and comments is an embedded collection within a post document. We denormalize the username of the author of posts/comments, and also store the user’s ObjectId, which will allow us to generate links like

    Posted by <a href="http://myblog.com/users/4f7d0176f1bb3e1223000005">bill</a>
    

    Translators

    Translator classes are Ruby classes which translate Java/Hibernate objects to their Ruby/MongoMapper counterparts, and contain the logic for dealing with denormalization.

    Let’s look at an example. The Hibernate domain model class for Blog would look something like this:

    Its MongoMapper counterpart would look something like this:

    The BlogTranslator class contains the logic to translate Blog entities to Blog documents:

    Some things to note:

    • Each Translator is idempotent and knows whether to create or update the document in MongoDB. We store the RDBMS identifer of the source entity in the MongoDB document to facilitate this logic.
    • Translators can call other Translators as they traverse the Hibernate model’s object graph. Above we see that the BlogTranslator calls the PostTranslator to translate each associated post.
    • Having each Translator be responsible for a single entity (or logical entity) allows you to plug the Translator into your applications to perform real-time incremental ETL as entities are created/updated, as well as chain Translators together to create large scale batch sync ETL processes.

    Embedding Translators in Java

    With the use of JRuby’s ScriptingContainer class, we can embed our Translator objects into our Java applications to facilitate the ETL process. Suppose we have a command line app which ETLs all Blog entities. It would embed the BlogTranslator and pass each Blog Hibernate model object to the BlogTranslator object’s translate method.

    Example ETL application

    A complete RDBMS -> MongoDB ETL application for our blog domain model can be found here:

    https://github.com/bploetz/jruby-etl

    The repository contains two main directories: java and ruby.

    The java directory contains the Hibernate domain model mapped to the relational database, as well as the example ETLManager class which demonstrates JRuby’s embedding capability.

    The ruby directory is a RubyGem containing the MongoMapper domain model mapped to MongoDB, as well as the Translator classes.

    To run this project the following are required:

    • JDK 1.5 or higher
    • Maven 2.2
    • JRuby (examples below assume JRuby is installed via RVM)
    • The Bundler gem installed
    • MongoDB running on the default port at localhost

    For simplicity, this example application uses HSQLDB for the RDBMS, so there is no need to have a separate RDBMS installed/running. You can obviously change the Spring/Hibernate configuration to use your RDBMS of choice if you so desire.

    Clone the jruby-etl git repository and run the following to compile the Java source files and create the distribution:

    rvm use jruby
    cd java-etl/java
    mvn clean package
    

    cd to the distribution directory and load the example seed data into the relational database.

    cd target/jruby-etl-1.0.0-SNAPSHOT-bin/bin
    ./load-seed-data.sh
    

    Finally, run the ETL app to translate the seed data from the relational database to MongoDB.

    ./etl.sh
    

    The project is configured to log all SQL statements and all MongoDB queries so that you can see the translation happening.

    This ETL application is just one example of how JRuby can help facilitate bridging Java and Ruby based technologies. What interesting solutions are you building with JRuby?

  • Using Trinidad to Run Multiple Apps

    Published by Joe Kutner on April 06, 2012

    This is part of a series of blog posts leading up to JRubyConf 2012. Joe Kutner is author of Deploying with JRuby and an expert on JRuby deployment options. Joe will be attending and speaking at JRubyConf…register for JRubyConf 2012 today!

    One of the advantages of running Ruby on the JVM is that we can deploy multiple applications to the same webserver. Using one JRuby webserver means that there is only one process to manage, monitor, start and stop. Your sysadmins will thank you.

    Having mutliple applications on one virtual machine also means we can configure them to share resources, thus reducing the overhead required for a production server. In this post, we’ll walk through an example of deploying two applications to one Trinidad server.

    Trinidad is a light-weight JRuby web server that runs Rails and Rack applications in an embedded Apache Tomcat container. Let’s install it by running this command:

    $ gem install trinidad -v 1.3.4
    

    Next, let’s create a Trinidad home directory. The examples in this post will use /opt/trinidad, but you can use whatever you’d like.

    Under the /opt/trinidad directory, we’ll create two more directories called thing1 and thing2, which will contain the applications we’re going to run on our single Trinidad server. In the thing1 directory, create a config.ru file and put this code in it:

    In the thing2 directory, create another config.ru file and put this code in it:

    Next, we’ll create a /opt/trinidad/trinidad.yml file, which will be used to configure our Trinidad server.

    Our Trinidad home directory should look like this:

    /opt/trinidad/
    |-- trinidad.yml/
    |-- thing1/
        `-- config.ru/
    `-- thing2/
        `-- config.ru/
    

    Before we start the server, let’s make sure Sinatra is installed by running this command:

    $ gem install sinatra
    

    Now we can run our Trinidad server by executing this command:

    As the server starts up, we’ll see that its instatiated two runtimes – one for each of our applications. We can see each of them by browsing to http://localhost:3000 and http://localhost:3000/thing2.

    The two applications are completely isolated. That means if you monkey-patch the String class in one application, it won’t affect the other application. If you set a global variable to a constant value in one application, you can set it to a different value in the other application.

    Now let’s move on and really take advantage of what we’ve created!

    Because these applications are running in the same JVM, they can share a Database Connection Pool. To do this, we’ll need to use the trinidad_dbpool_extension. Trinidad provides an extension mechanism that allows us to plug-in many kinds of features.They are particularly useful when we need to hook into the embedded Tomcat container, as our database connection pool will.

    To use the trinidad_dbpool_extension, we’ll need to add an extensions: entry to our trinidad.yml file. The new entry will contain the configuration for the Database Connection Pool. The entire file should look like this now:

    The extension creates the database connection pool inside the Tomcat container and gives it a JNDI name. JNDI is a registry service for resources inside of a JVM.

    You’ll have to use a real database for this to work, but you don’t have to use PostgreSQL. The extension also supports MySQL, MSSQL, Oracle, and a generic adapter that covers most other JDBC implementations.

    Next, let’s use the pool in our applications. Change the thing1/config.ru file to look like this:

    First, we’ve loaded the active_record Gem, which we’ll use to interface with our database. Next, we’ve added two statements to our get service. The first statement establishes a connection from the pool by referencing the JNDI resource we definined earlier. The second line executes a simple query against PostgreSQL’s internal tables. Finally, we’re returning the result of the query as the service response.

    Next, modify thing2/config.ru so it looks similar to the code above, but with “Thing two” in the response.

    Before we can launch these applications, we’ll need to install a few more gems by running these commands:

    $ gem install activerecord 
    $ gem install trinidad_postgresql_dbpool_extension 
    $ gem install activerecord-jdbcpostgresql-adapter
    

    Now kill the Trinidad server if it’s still running by pressing Ctrl+C from it’s console, and start it up again by running this command once more:

    $ trinidad --config /opt/trinidad/trinidad.yml
    

    When we point our browser to http://localhost:3000 and http://localhost:3000/thing2 we’ll see something like this (depending on the number of tables in your database):

    Thing one found: [{"count" => 0}]
    

    Both applications are connecting to the database!

    Sharing a database connection pool simplifies our production architecture by eliminating the need for additional layers like pg_pool. Trinidad makes it very easy to configure, but this same kind of setup can be achieved with any JRuby web server – including TorqueBox and Warbler+Tomcat/Jetty/etc.

    If you found this useful, I encourage you to pick up a copy of my book, Deploying with JRuby, which has tons of other JRuby examples like this one.

    The complete source for this example can be found on Github at trinidad-dbpool-example.

  • Rails 3.2 and Rubygems.org source

    Published by Nick Sieger on January 31, 2012

    We announced this on Twitter, but it’s important enough to put here for posterity.

    FYI, since 3.2 rubygems.org is the default Gemfile source, this means you need to have jruby-openssl installed before "rails new".

    — JRuby Dev Team (@jruby) January 31, 2012

    To clarify, the following is put in Gemfile for new Rails 3.2 apps:

    source 'https://rubygems.org'
    

    This means that the jruby-openssl gem must be installed before you can generate a new Rails application.

    An alternative is to run rails new --skip-bundle, ensure jruby-openssl is installed, and then run bundle install inside your new application.

    We’re looking at options for incorporating more of jruby-openssl into JRuby proper without importing the export-controlled crypto bits (which is the reason we don’t currently ship jruby-openssl with JRuby). If you’re interested, join us.

  • JRuby at Square

    Published by Nick Sieger on January 27, 2012

    At this month’s past SF JRuby Meetup Xavier Shay gave a compelling experience report on Square’s expanding use of JRuby.

    He also announces the open-sourcing of Jetpack, Square’s tool for deploying JRuby applications in their production environment.

    </param></param></param></embed>

    (Thanks to Marakana TechTV for recording and posting the talk!)

  • Monitoring Memory Allocation Per Thread

    Published by Charles Oliver Nutter on December 29, 2011

    Perhaps the largest benefit of JRuby being on the JVM is the excellent tool ecosystem. There’s an enormous collections of debuggers, profilers, and general monitoring tools available for JVM that work great with JRuby. Even better, a surprising number of these tools are built into each JVM.

    One of these tool sets is the java.lang.management package. Here, you’ll find a number of JMX beans for monitoring the status and health of the JVM. Some of the information presented by these beans is standard, like lists of memory pools (heaps) or the number of available processors on the current system. But each JVM may also expose additional information.

    On OpenJDK, starting with 6u25, the built-in ThreadMXBean exposes an additional operation: getThreadAllocatedBytes. How can JRubyists take advantage of it?

    Monitoring Thread Allocation

    Of course, via JRuby’s Java integration, we can easily call any of the management beans’ operations, and getThreadAllocatedBytes is no different.

    We start by loading the ‘java’ and ‘jruby’ libraries, to access Java classes and some normally-hidden JRuby features.

    require 'java'
    require 'jruby'
    

    We get access to the ThreadMXBean via the ManagementFactory class.

    thread_bean = java.lang.management.ManagementFactory.thread_mx_bean
    

    Now, we will create a thread that endlessly creates a new string, and get references to that thread’s and the main thread’s native java.lang.Thread object.

    t1 = Thread.new do
      a = nil
      loop do
        a = 'foo'
      end
    end
    t1_thread = JRuby.reference(t1).native_thread
    
    main = Thread.current
    main_thread = JRuby.reference(main).native_thread
    

    Now that we’ve got a thread busily allocating data, we set up a loop that prints out both threads’ allocated bytes once every second. The getThreadAllocatedBytes method takes an array of thread IDs and returns an array of byte counts, both as long[].

    loop do
      sleep 1
      t1_alloc = thread_bean.get_thread_allocated_bytes([t1_thread.id].to_java(:long))[0]
      main_alloc = thread_bean.get_thread_allocated_bytes([main_thread.id].to_java(:long))[0]
      puts "main allocated: #{main_alloc}"
      puts "t1 allocated: #{t1_alloc}"
    end
    

    (Note the bit of Java integration array-munging; par for the course going from Ruby’s heterogeneous Array to Java’s homogeneous arrays.)

    And that’s it! Here’s the output on my system for five iterations of the loop:

    main allocated: 11343752
    t1 allocated: 378806608
    main allocated: 11359632
    t1 allocated: 767226768
    main allocated: 11361624
    t1 allocated: 1156928944
    main allocated: 11363616
    t1 allocated: 1547160976
    main allocated: 11365608
    t1 allocated: 1930237360
    

    I’ve gisted the full script here: Monitoring Thread Allocation.

    Your Turn

    This is just one of many fun (and useful!) ways you can monitor the JVM using JRuby. Poke around in ManagementFactory and see what else you can find!

  • Getting Started with JRuby and Java 7

    Published by Charles Oliver Nutter on December 19, 2011

    Unless you’ve been living under a rock, you’ve probably heard about the new hotness for JRuby: Java 7’s support for dynamic languages. You may also have heard about the huge perf gains that JRuby’s seeing when running on Java 7. How can you try it yourself?

    Get Java 7

    The reference implementation for Java is OpenJDK, and OpenJDK 7 has been out for almost six months now. The current version is 7u2 (‘u’ stands for ‘update’), and includes a number of improvements over the GA (‘General Availability’) release.

    Most platforms have easy access to OpenJDK builds. I’ll summarize the steps here.

    Linux, Windows, and Solaris

    Oracle provides binary downloads for Windows, Linux, and Solaris on its site. The JavaSE Downloads page links to both JDK and JRE download pages. You’ll probably want the JDK, since it includes other JVM-related dev tools, but the JRE will work too. Download, install, and you’re ready.

    Additionally, package managers for Linux and Solaris will likely soon have OpenJDK 7u2 packages available, if they don’t already.

    OS X

    The official preview of OpenJDK for OS X lags behind, but you can get the current builds from the openjdk-osx-build project. The build you want is currently labeled “OpenJDK-OSX-1.7-x64-u2-b21”, but any build labeled “1.7” and “u2” in the future will get what you need. The .dmg provides either a self-contained JDK for you to drop onto your system or a .pkg installer that does it for you.

    Update: Henri Gomez, the primary guy behind openjdk-osx-build, has set up a page specifically for the update builds. Grab the JDK or JRE from his OpenJDK7JDK7UOSX page.

    Update 2: Oracle now has a supported build of Java 7 update 4 for OS X, so you can get it from them! It only supports Lion, though, so if you’re on Snow Leopard you will still need to use a build from Henri or build it yourself.

    *BSD

    The OS X work is based off the “bsd-port” branch of OpenJDK. There are links to Java 7 package information for FreeBSD, NetBSD, DragonFly BSD, and OpenBSD on the BSD Port wiki. These may not be updated to 7u2 yet.

    Why Update 2?

    We haven’t previously made a lot of noise about Java 7 and JRuby, nor assembled a blog post/tutorial like this, primarily because Java 7 GA was missing key optimizations in the invokedynamic subsystem. JRuby 1.7 will make heavy use of invokedynamic, and if we had released it before those optimizations were in place, it would have given people a bad impression of the power of invokedynamic.

    Update 2 now has a small set of optimizations that make a very large difference. If you intend to start playing with JRuby 1.7 builds, we strongly recommend you use OpenJDK 7u2 or higher.

    Update: Your jruby -v output should look something like this:

    jruby 1.7.0.dev (ruby-1.8.7-p352) (2011-12-19 f404f75) (OpenJDK 64-Bit Server VM 1.7.0-u2-b21) [darwin-amd64-java]
    

    The important bit is that “u2” appear somewhere in that line.

    Getting JRuby

    Of course getting JRuby is always pretty easy.

    JRuby 1.6.x (current release)

    The current release of JRuby is always available on the JRuby homepage. Here, you’ll find tarballs, zipfiles, Windows installers, and JRuby in other forms. Download, unpack, add bin/ to PATH, and you’re ready.

    If you want to get the leading edge of the JRuby 1.6 line, including fixes that have not yet been released, you can download a nightly snapshot from JRuby’s release snapshots page.

    You can also install JRuby through RVM or rbenv, using rvm install jruby or rbenv install jruby-1.6.5, respectively. This is our recommended procedure for folks already using RVM or rbenv. It’s also possible to build/install JRuby 1.6.x snapshots using rvm install --branch jruby-1\_6 jruby-head.

    Windows users may be interested in pik, an RVM-like tool for managing Ruby installations. It supports JRuby, naturally.

    There are also JRuby packages for most major Linux and BSD variants. They’re not always up-to-date, however.

    Finally, you can clone JRuby from the JRuby github repository and build the jruby-1_6 branch.

    JRuby 1.7.x (in development)

    Update: JRuby 1.7.0.preview1 has been released! We are very interested in bug reports for the new invokedynamic support, and wanted to get this preview out for people to test. There will be issues, don’t think for a moment there will not…but that’s what previews and release candidates are for. Help us make 1.7.0 awesome!

    JRuby 1.7 is not out yet…we had been waiting for OpenJDK 7u2 to drop before starting our finalization process. But we’re looking for folks to start playing with it now. Until we release JRuby 1.7, you can get it a few different ways.

    Simplest is probably to grab a snapshot from the JRuby’s master snapshots page. You’ll find the usual complement of packages and installers there.

    RVM can install JRuby master using rvm install jruby-head.

    And of course, you can clone from Github and build the master branch yourself, by running ant. JRuby runs fine from the working copy.

    Use the Right Java Version

    Ironically, the most complicated part of this process is making sure your system is set up correctly to use Java 7 instead of some other version. The simple answer is to hardcode the Java 7 bin/ dir in your shell’s PATH, but that’s both inelegant and incompatible with some systems’ preferred mechanisms. Here’s a short survey of more elegant ways to easily swap Java versions.

    Linux

    As with most things, Linux variants don’t agree on how to manage multiple alternative versions of a given package. Below I summarize the “blessed” way to do it on various Linux flavors.

    Alternatively, you can rig up a trivial shell function or script that, when run, rewrites your environment to point at the target Java installation. See the “pickjdk” script for OS X below.

    Debian variants (Debian, Ubuntu, etc)

    On Debian, your command of choice will be update-java-alternatives. This resets a set of global symlinks to point at the Java installation you prefer. It’s not the most elegant way, since the change is made globally, but it is the blessed way.

    RedHat variants

    RedHat has a similar command called “alternatives”, under which there’s a “java” namespace. the JBoss 5 docs have a nice page on setting the default JDK on RHEL

    Gentoo and other Linux variants

    I have so far been unable to find a way to easily manage multiple installed Java versions on Gentoo. Feel free to submit suggestions in the comments.

    Update: Gentoo’s mechanism is the java-config command. java-config -L lists all installed runtimes, and java-config -set X sets the default to runtime X.

    Windows

    On Windows, your best best is generally to put the preferred Java version’s bin/ dir in PATH. If you have other suggestions, feel free to comment.

    OS X

    Your best option will be to use the oft-tweaked “pickjdk” script, which scans installed JDK versions and presents a menu. Selecting a version rewrites your environment to point at that version. I prefer my pickjdk variant, since it allows specifying an install number directly without going through the menu.

    An alternative is to configure your environment manually. Java installations are located under /Library/Java/JavaVirtualMachines; set JAVA_HOME to /Library/Java/JavaVirtualMachines/1.7.0u.jdk/Contents/Homeand prepend $JAVA_HOME/bin to your PATH. You’re ready to go.

    Update: There’s an easy way to find available JAVA_HOMEs: the java_home command. /usr/libexec/java_home will return the path to the default JVM (from Java Preferences). You can also specify -v 1.7 for the first Java 7 (1.7) install, or pass -V to list all available JVMs.

    You can also open up the Java Preferences utility (located in /Applications/Utilities) and drag your preferred Java version to the top. This is a global change, and will affect any programs that use the default Java version. Because the GUI parts of the OS X Java 7 preview are still in development, THIS IS NOT RECOMMENDED.

    Other OSes

    I don’t know the proper mechanism for managing Java installations on the other BSDs or on Solaris. Feel free to comment.

    Try It Out!

    Once you’ve got JRuby installed and in PATH (via whatever mechanism) and Java 7 installed and in PATH (via whatever mechanism), you’re ready to test it out! Start up jirb, launch your favorite JRuby-based app, or just run some benchmarks.

    If you’re especially interested in performance, try out bench/bench_red_black.rb from JRuby’s benchmark suite. It’s a pure-Ruby implementation and benchmark of a red/black tree, and a good representation of the kind of performance improvements you should see from JRuby on Java 7. There’s plenty of other benchmarks in our suite and in the wild… play around and let us know how it goes.

    What to Expect

    Java 7 brings a lot of performance updates, even without invokedynamic. If you’re using JRuby 1.6.x, you should see an immediate performance improvement moving from Java 6 to Java 7. I have heard reports of anywhere from 10-30% faster applications.

    If you’re trying out JRuby master (1.7), you should see even more significant improvements. JRuby 1.7’s use of invokedynamic means that Ruby code runs faster, optimizes better, and uses fewer resources. In fact, if you don’t see better performance with JRuby 1.7 versus JRuby 1.6 on Java 7, please report an issue at JRuby’s bug tracker. You’ve probably found a flaw in our compiler…a flaw we’ll want to fix before release.

    As a bit of a teaser, here’s my numbers running the red/black tree benchmark from above (the numbers are time in seconds). Compared to JRuby on Java 6, JRuby on Java 7 without invokedynamic is around 25% faster, and JRuby with invokedynamic is nearly 3 times faster.

    It’s also worth mentioning that invokedynamic isn’t “done”. There’s a new optimizer planned for Java 7u4 and my OpenJDK friends tell me there are many opportunities to increase performance. JRuby on Java 7 will just keep getting faster.

    JRuby has room to grow as well. We’re using invokedynamic heavily for the upcoming 1.7 release, but there’s many places yet to be adapted. The performance you see today is not the end of the story…there’s a lot more we can do.

    Your Turn

    That’s about it for this tutorial. Hopefully you’ll be up and running on JRuby with Java 7 very quickly. If you have any trouble, please comment…we’ll try update this article with fixes and suggestions. And I repeat my call for feedback on JRuby master + Java 7…this is the future of JRuby, and it could be the future of high-performance Ruby. Let’s work together to make it awesome!

  • JRuby CI: Keeping it Real

    Published by Charles Oliver Nutter on December 16, 2011

    Building a Ruby implementation is a long and challenging project. There’s thousands of tests you need to pass, tens of thousands of libraries you need to run, and lots of edge cases you need to discover and fix over time. Perhaps even more challenging is keeping your Ruby implementation working from release to release, commit to commit. Continuous integration is an absolute necessity.

    JRuby has had a CI server for at least the past five years, running hand-rolled options at first, and later to Jenkins (nee Hudson) where we will stay for the foreseeable future. This post will help you understand how much effort we put into remaining compatible and stable over time, and how you can track JRuby’s dev process from a CI perspective.

    The Server

    As mentioned above, we run Jenkins for our CI server. The ci.jruby.org machine runs on EC2 on a modest-sized instance funded by Engine Yard. There are dozens of builds running on that machine, and it’s busy almost 24 hours a day.

    There are several dimensions across which we test JRuby:

    • “master” versus “release” - Currently 1.7 dev versus 1.6.x, the master branch and jruby-1_6 branch.
    • basic versus extended versus “all” tests - The “test” builds are doing our normal “test” target, which runs quickly and includes a smaller subset of the full suite. These take about 3-5 minutes. The “test-all” builds run an extended suite of tests across many combinations of JRuby settings, and take anywhere from 30 to 60 minutes (run nightly).
    • JVM vendor and version - We run our basic suite across several JVMs and try to keep them green…but it’s a challenge.
    • RubySpecs - We run the full RubySpec suite across several combinations of JRuby settings.
    • Domain-specific tests - We ensure the jruby-complete.jar works properly, jruby libraries like jruby-rack and jruby-openssl pass their tests, and various rails releases pass their tests as well. These aren’t always kept green, since they depend on external repos and changes, but we try to periodically tidy them up.
    • Platform-specific tests - We also run our test suite on Windows, and have several test runs for Ruboto, the JRuby-on-Android framework.

    It’s probably safe to say JRuby runs more tests in more combinations than any other Ruby implementation, including MRI itself. What do the tests include?

    The Suite

    JRuby’s test suite obviously includes our own JRuby-specific tests, but over time it has grown to include several other suites.

    • JRuby’s tests and specs - These are largely testing JRuby-specific features like Java integration or our Java-facing embedding APIs. We also have some tests for JRuby-specific enhancements to core Ruby functionality, like URL support in File and Dir methods.
    • Legacy runit and minirunit tests - Inherited from older suites in MRI, this suite has slowly been shrinking over time.
    • MRI’s test suite - In order to keep up with MRI’s feature changes, we also run MRI’s suite in various forms. Most recently, we started running MRI 1.9.3’s test suite unmodified, using the new “excludes” feature in minitest.
    • Rubicon - Rubicon was a suite of tests written originally to support the “Programming Ruby” book from PragProg. We have always run it, and over time tidied it up and just use our local copy. This too has shrunk over time, as we move more tests into RubySpec.
    • The ruby_test suite - This is a suite of tests created by Daniel Berger to support his “facets” project. We run them just because.
    • Our “main” Java-based suite - A set of JUnit test for JRuby’s Java APIs.
    • RubySpec - And of course, we run RubySpec for both 1.8 and 1.9 modes. If we encounter bugs or missing tests, we almost always add to RubySpec, rather than to any of the other suites.

    All six of these test groups are run as part of the “test-extended” and “test-all” targets, adding up to literally millions of assertions.

    The Snapshots

    In order to aid people testing JRuby, and to give people easier access to the latest features on master and fixes on our release branches, we publish nightly snapshots to ci.jruby.org/snapshots.

    Here you will find 1.7.x and 1.6.x builds, or if you prefer to use our rolling development aliases, master and release builds.

    Your Turn

    There’s a lot to track on our CI server, and we’d love your help in keeping builds green or fixing builds that are red. We’re also looking to add other key libraries to our CI server, to help ensure we’re maintaining a high level of compatibility. If you think you can help, post a message to the JRuby dev list, or ping @jruby on Twitter!

  • Gracious Eloise Interview

    Published by Chris White on November 20, 2011

    It’s always interesting to see how JRuby is being utilized by our users. Sometimes it’s ways we expect, other times the results are unexpected. Rebecca Miller-Webster (@rmillerwebster), Head of Technology at Gracious Eloise (@graciouseloise), posted a blog entry titled The Power of JRuby showing a rather interesting use of JRuby. Wanting to know more about how JRuby fit into Gracious Eloise’s architecture, I conducted an interview so that users could see what kind of exciting things people are doing with JRuby!

    To start off, what is Gracious Eloise and what problem does it look to solve?

    Gracious Eloise is making handwriting digital and handwritten notes as easy as email. We are creating a platform that allows business and individuals to write handwritten notes from their computer – the notes are either printed, stamped, and mailed or emailed (coming soon!)

    Our founder, Eloise Bune, came up with the idea when she had to write 300 thank you notes after her wedding. In the process of building the algorithm and talking with investors, she realized that companies in many sectors, such as retail, non-profits, car dealerships, elected officials, and PR, currently have handwritten note programs that they are unable to scale or ensure quality and corporate standards. That’s where Gracious Eloise comes in.

    When did you first find out about JRuby?

    I had heard rumblings of JRuby for a while – a friend who is a Ruby and Java/Hadoop guy kept suggesting it to me for Gracious Eloise. Our handwriting replication algorithm is written in Mathematica, and I was struggling to build a Java web service that would allow our web app to connect to it.

    At what point did you decide to use JRuby, and was it a tough decision?

    After struggling to get a Spring MVC web service to just return JSON without a view, I gave myself 2 hours to try to do it in JRuby. It was done and working in 30 minutes. Not a tough decision at all!

    How does JRuby fit in to your current architecture?

    JRuby is the glue that connects everything together. It connects our handwriting replication code (with a light Java wrapper around it) to our MRI Ruby on Rails web app via Resque jobs. Ultimately, we will get rid of the Java code altogether and move that into JRuby as well as rewriting some or all of the handwriting replication algorithm using JRuby. Because we can use Java’s image and graphics libraries, JRuby is a huge win for us in terms of the algorithm itself.

    What is the architecture like that keeps everything running?

    We have Mathematica, Java, and JRuby running together in EC2 to do algorithm related processing. Our web app is Rails 3 with Backbone.js running on Heroku. Pusher allows us to send messages about the status of processing to the web app. Handwriting data is stored in MySQL (RDS), while customer and other web app related data is in Postgres.

    What do you consider to be JRuby’s strengths and weaknesses?

    As I said in a recent blog post, I think the biggest strength of JRuby is that it opens you up to using any Java library out there. Used in conjunction with Resque and MRI or REE Ruby, you can also use any C library out there. Basically, JRuby hands you most of the world of code on a platter.

    As for weaknesses, I think it’s biggest weaknesses are Java’s biggest weaknesses. And I’m mostly talking about Java’s insane love of memory. :) Obviously, using the JVM and having access to Java libraries have huge advantages, so as with all technology choices, it’s a trade off. But, again, you could always have code that is a memory-suck in Java moved to C and connect with other JRuby code in Resque. JRuby allows you to choose the best tool for each job at hand and that, to me, is huge.

    You mentioned that you were looking for a JRuby developer. What kind of work would be involved?

    The main project our JRuby Developer would tackle would be creating an app for processing handwriting samples, likely a combination desktop and web app. Currently, the process of getting someone’s handwriting is a huge pain and requires a review process that is terrible to do in Mathematica. We have some code for this here and there, but it would really be building something from scratch. Beyond that, the job would involve keeping the glue between the algorithm and the web app working and improving the speed and efficiency. Also, helping our algorithm engineers move code out of Mathematica.

    We are super small (i.e. I’m the only full-time developer), so if someone wanted to work on the web app side or the algorithm side as well that is on the table. There’s also work to do with printer and email provider integration as well as CRM integration.

    Thank you for taking the time for this interview! Do you have any closing words for our readers?

    JRuby rocks my world!

  • JRuby Community Improvements

    Published by Chris White on November 17, 2011

    JRuby community guy Chris White (@cwgem) here. First off as I’ll be offering topics you can contact me about, here’s the best ways to do so:

    • IRC: cwgem @ freenode
    • Mail: cwprogram at live dot com
    • Twitter: @cwgem

    As of late I’ve been getting more involved in helping with the JRuby community, and finding out the best ways to reach out to new and existing users. Knowing who your community is helps to understand what needs should be filled, and what possible pain points are. That’s why I’ve made a few changes that I’d like to talk about to hopefully get you, the community, involved with JRuby better.

    Twitter Accounts

    Previously JRuby related tweets were getting spread across multiple accounts, and the JRuby official account was somewhat dry with content. Twitter is a great information aggregator, and those using the service often want a centralized place to check on related content. If someone asks “Where’s the best place to get JRuby related information?”, the answer should always have an official account with regularly updated content. So with this in mind I’m working with other JRuby team members to keep the account fresh. So please be sure to follow @JRuby on Twitter to stay up to date on happenings!

    Now another interesting issue I’ve run into is that there are a few JRuby job postings that trickle through on twitter. At first my main thought was to talk about them on the main @JRuby account. However the problem with that is it has the potential to make @JRuby perceived as a “spammy” account. Also the point of the account is to get job openings pushed out to people that actually care about them. This means they need to be focused to such users. @JRuby can’t achieve this well because the expectation isn’t setup to keep your eyes on the account for updates. To help alleviate these issues, the @JRubyJobs account has been created. If you’re an employer looking for JRuby developers, or a JRuby developer who wants to use their skills in the workplace, be sure to check the account out! Those wanting to have JRuby job opportunities posted to the account please cc @JRubyJobs on the listing, DM the account, or send me an email.

    JRuby Map

    An interesting question that comes up regarding open source communities is where everyone is from. In the internet age open source users are often spread across the globe, sometimes in unexpected places. To attempt to get an idea of where our JRuby users are, I created the JRuby User Map. My hope is to have a more populated map, so that I can see where our biggest user communities lie, but also make sure the smaller communities are recognized as well. Smaller communities are often put off as not worthwhile. However my belief is that these smaller communities are much more crucial. These are users who are working with JRuby in an environment where there is less support, which shows a tremendous amount of dedication. If you’re part of such a community and need help growing please contact me through Twitter or email.

    For those of you who haven’t added themselves to the map, be sure to check out the blog post showing how the process works. It’s only a few steps and helps us get to know our community better!

    Surveys

    The best way to get to know users is to ask them questions. With this in mind I created a two surveys and casually posed a JRuby OS/App Server question on twitter. Some results simply confirmed my suspicions, others were quite interesting.

    Java Version Survey

    First was the Java Version Survey. The purpose of this survey was to understand which Java version people were running JRuby with. There were a total of 83 respondents to this survey. As the answer was multiple choice, the number of selections, 104, was greater than the number of respondents. As for how the data ended up:

    • Java 8 - 1 user (1%)
    • Java 7 - 28 users (27%)
    • Java 6 - 72 users (69%)
    • Java 5 - 3 users (3%)

    This was more a confirmation of my assumptions. For the most part people are on Java 6, which makes sense as Java 7 came out recently. It also matches the JRuby 1.7 dev (trunk) usage. If you’re using trunk then upgrading to Java 7 is recommended to utilize the invokedynamic enhancements! There’s one brave Java 8 user, and a few Java 5 users still remaining.

    JRuby Version Survey

    Next was to figure out what JRuby version was being used, and what the ratio of 1.8 and 1.9 mode usage was. This particular survey was split into four questions, two development environment questions and two production environment questions (optional of course). There were a total of 59 respondents. The allocation of responses were as follows:

    • JRuby Development Version - 79 answers
    • JRuby Development Ruby Mode - 59 answers
    • JRuby Production Version - 66 answers
    • JRuby Production Ruby Mode - 54 answers

    There weren’t too many respondents who use JRuby only for development. The gap between JRuby dev respondents and answers is most likely due to people running multiple versions for testing. Personally I run 1.6.5 and trunk at the same time! Now for the results:

    JRuby Development Version

    • JRuby 1.7 dev (git master) - 9 users (11%)
    • JRuby 1.6.5 - 46 users (58%)
    • JRuby 1.6.4 - 12 users (15%)
    • JRuby 1.6.3 - 5 users (6%)
    • JRuby 1.6.2 - 2 user (3%)
    • JRuby 1.6.1 - 1 user (1%)
    • JRuby 1.5 - 3 users (4%)
    • JRuby 1.4 and lower - 1 user (1%)

    Most users are around 1.6.4 and 1.6.5, with a good number using trunk. This is expected for development use.

    JRuby Development 1.8/1.9 Mode

    • Ruby 1.8 Mode - 19 users (32%)
    • Ruby 1.9 Mode - 28 users (47%)
    • Both - 12 users (12%)

    This was not too surprising. A majority of development users are on 1.9 mode, with the rest between 1.8 mode or both 1.8 and 1.9 mode.

    JRuby Production Version

    • JRuby 1.7 dev (git master) - 2 users (3%)
    • JRuby 1.6.5 - 37 users (56%)
    • JRuby 1.6.4 - 9 users (14%)
    • JRuby 1.6.3 - 8 users (12%)
    • JRuby 1.6.2 - 1 users (2%)
    • JRuby 1.6.1 - 1 user (2%)
    • JRuby 1.5 - 6 users (9%)
    • JRuby 1.4 and lower - 1 user (3%)

    The 2 users of 1.7 dev was a bit of a surprise. If you’re out there and reading this please shoot me an email on how you’re using it and how it’s working for you! There are a lot of 1.6.5 users, which means a majority of users are good about keeping up to date (since 1.6.5 was very recently released). There are noticeable number of 1.5 users, which is understandable given that some business are very conservative about technology related changes. If however there’s a bug or other reason which is blocking you from upgrading to the 1.6 please let us know! Having everyone on the same page is what we’d like to achieve.

    JRuby 1.8/1.9 Mode

    • Ruby 1.8 mode - 26 users (48%)
    • Ruby 1.9 mode - 17 users (31%)
    • Both - 11 users (20%)

    The results here were a bit intriguing, as I was expecting a far larger gap between 1.8 and 1.9 mode usage. It will be interesting to revisit this question again when JRuby 1.7 becomes officially released. For those using both 1.8 and 1.9 mode, let us know how the Ruby mode usage is split up for your particular case.

    JRuby and Rails Deployment Survey

    The question was posed as to what OS and what app server was used for JRuby and Rails deployment. Most users mentioned that they were doing development work on Mac OS X, which is normal for the Ruby community in general. The server operating systems were a mix of RedHat and Debian based (RedHat, CentOS, Fedora, Debian, Ubuntu). There were a few Windows users (Windows 2008 Server), and a Solaris and AIX user. As for the app servers, Tomcat had the lead with Jetty, Trinidad and Torquebox also getting mentions. A few users also mentioned WebSphere and Glassfish.

    This leads me to the conclusion that:

    • We need to ensure the install guide for these app servers is up to date, especially the widely used Tomcat server.
    • On that note finding links to the official pages of specific distributions on installing JRuby would be helpful
    • A lot of users were noting that Mac OS X is their main development box, so revisiting the installer and ensuring it meets its needs would be a good idea
  • The JRuby User Map

    Published by Chris White on November 13, 2011

    Google maps provides an interesting feature for creating personalized maps. It is possible to allow these custom maps to be edited by others using collaboration features. With this in mind I’ve created a JRuby Users Map. The map looks like this at the moment:

    JRuby User Map

    Adding Yourself To The Map

    Adding yourself to the map takes a few simple steps. First off you will need a Google account to access the map. For those of you who don’t, see the wiki instructions at the end. Once logged in, click on the link to the map given. Then search for the location that you wish to add. As an example I’ll search for Portland to add the Engine Yard Portland office:

    Portland Search

    Next click on “Save To Map” on the left hand side. This will bring up a select box where you can select the “JRuby Users” map:

    Save To Map

    Finally, click “Save” to confirm and your location will be added:

    Location Saved

    Now you can also customize the location marker. To do so, return to the JRuby Users map using the original link. Then click the “Edit” button on the left, which will allow you to edit your entry:

    Editing A Location

    Make your edits (in this case I edited the title to “Engine Yard (Portland)”) and click “Save”, then “Done” on the left hand side to complete. This is the final result after the edit:

    The EY Portland Office Shown

    … You Can Also Add Yourself To The Wiki!

    JRuby Guy Charles Nutter has also created a wiki page on the JRuby wiki titled In Your Region that you can add yourself to as well. This is alternative to those with JS restrictions of some sort, or those who don’t have a Google account.

  • JRuby and ClojureScript Goodness

    Published by Chris White on November 11, 2011

    While Java is a major language on the JVM, it’s not the only one JRuby can interface with. JRuby can work with other JVM languages such as Scala, Groovy, and Clojure. JRuby committer Yoko Harada (@yokolet) has been doing some interesting work with ClojureScript, a Clojure to JS compiler. This post will take a look at how JRuby was used to help bring ClojureScript to Tilt, and in doing so the Rails Asset Pipeline.

    ClojureScript and Tilt

    The first experiment was getting ClojureScript to work with Tilt, which is a “Generic interface to multiple Ruby template engines”. Yoko’s blog post Tilt Template for ClojureScript describes the process of getting the two technologies to work together. JRuby’s jar import functionality was used to interact with the ClojureScript related jars, which allowed Ruby to be used to bring everything together. For those interested in taking a look, there is a git repository with the code available to check out.

    ClojureScript and The Rails Asset Pipeline

    It doesn’t stop there though! Since ClojureScript was available to Tilt, the next step was seeing if that could be used to interface with the Rails Asset Pipeline. The guide has a short snippet on registering gems with Tilt to get them recognized by Sprockets, which Yoko describes in the blog post ClojureScript on Rails Asset Pipeline. A great example of how JRuby can be use to do cool things with cool JVM technologies! This is also another reason to keep your eyes on the git repository to watch for new developments.

    You Can Do Closure Too!

    ClojureScript uses the Google Closure compiler behind the scenes to make the JS compilation process happen. Instella CEO Dylan Vaughn was inspired by a post on Closure Templates Discuss titled Closure Templates in Ruby to take a look on bringing JRuby and Closure together. Using some code for using Closure’s soy compiler with the Rails Asset Pipeline by Googler Ilya Grigorik, he was able to interface the two together. The result of this is the closure-templates gem, installable with gem install closure-templates. Be sure to check it out!

  • Recent JRuby Conference Videos and Materials

    Published by Chris White on November 08, 2011

    At any one time there always seems to be a number of conferences coming up or taking place. These conferences are an excellent way to interact with members of the JRuby community. However not everyone can make it to every single conference. Fortunately sites like Confreaks, SlideShare, and Lanyard have made it easy to access pre-recorded conference videos, slides, and other materials. This post is meant to introduce some highlight videos and materials from recent conferences where JRuby presentations were held.

    But First, JRubyConf Is Coming!

    As was announced on Twitter, JRubyConf 2012 will be taking place in Minneapolis, Minnesota from May 21st - 23rd. The JRuby team has some great things planned, so be sure to keep your eyes on the @JRubyConf account for more updates.

    StarTech Conf

    Building Languages for the JVM

    It used to be that Java was the main language to interface with the JVM. This has changed with languages such as Clojure, Scala, and Groovy stepping up to provide alternative ways to utilize the platform. What exactly goes into making a language for it? JRuby Guy Charles Nutter takes a look at the challenges for implementing a language using JRuby as a case study. Slides for the presentation are available on slideshare.

    Ruby Midwest

    Recommendation Engines using Machine Learning, and JRuby

    Wonder how a site like NetFlix recommends movies to users? Matt Kirk discusses how such recommendation engines work and how to implement one in JRuby. PDF Slides are available from the author’s website.

    High Performance Ruby: Threading versus Evented

    While not specific to JRuby, Dr. Nic takes a look at the often debated topic of threaded versus evented when dealing with high performance Ruby. In particular JRuby is mentioned for how it handles the threaded concurrency issue. Slides are available on Slideshare for viewing (there’s also a PDF download link). There’s also a recorded video of a previous version of the talk from Windy City Rails.

    Ruby Conference

    Be a Minecraft modman with Purugin

    Minecraft is a game that has gained an immense following. Users explore worlds and construct things along the way. However, there are a unique set of users who like to tinker around with the game and create mods for it. These users are known as modman, or so JRuby team member Thomas Enebo has decided to call them. This talk discusses Purugin, a framework that uses JRuby to allow for creating Minecraft plugins using Ruby syntax. A video of the talk is available at Confreaks.

    JRuby: Polyglot Heaven

    With languages such as Scala, Clojure, and Groovy setting a new trend for languages on the JVM, projects utilizing multiple languages are not a rare site. This talk by JRuby team members Charles Nutter and Thomas Enebo takes a look at how JRuby can be used to interact with other JVM languages. A video of the talk is available at Confreaks.

    JRuby and Big Data

    Jeremy Hinegardner presents different ways that JRuby can work with big data. The talk discusses interfacing with big data solutions such as Apache Hadoop, HDFS, Avro, and more. A video of the talk can be found on Confreaks and Youtube.

    Update Added RubyConf Brazil Talks. Thanks to @qmx on twitter for the heads up!

    RubyConf Brazil

    JRUBY ON STEROIDS

    Technology is constantly improving, and the JVM is no exception. JRuby contributor Douglas Campos takes a look at Java7’s improvements for dynamic languages, and how JRuby benefits from them. HTML Slides can be found on the author’s website. A video recording in Brazilian Portuguese can be found at eventials.

    TORQUEBOX - CROSSING THE CHASM BETWEEN JAVA AND RUBY

    Scale is always a hot topic in the web development world. However you don’t have to reinvent the wheel to achieve it. TorqueBox contributor Bruno Oliveira looks at how Rails/Sinatra/Rack applications can be combined with JVM technologies to provide scalable applications. Slides can be found at slideshare. A video recording in Brazilian Portuguese can be found at eventials.

  • Why Isn't JRuby Implemented in Ruby?

    Published by Charles Oliver Nutter on October 24, 2011

    As Ruby implementations mature and Ruby code runs faster and faster, the question starts to come up again and again: why not implement more in Ruby? There’s many good reasons to do it: easier for Rubyists to maintain and contribute; no native library dependencies; better visibility for debuggers and profilers; consistency all the way into the core… the list goes on. As you’d expect, we often get this question about JRuby itself, given that JRuby now runs Ruby code very fast and most Rubyists would rather not read or write Java code. So why isn’t JRuby implemented in Ruby?

    The answer: it’s complicated.

    Ruby is Not the Best Language for Everything

    The simplest answer is perhaps the most obvious: Ruby isn’t always the best tool. There’s many cases where Ruby’s dispatch overhead, coercion protocols, arbitrary-precision integers, or mutable types get in the way of expressivity or performance. What makes Ruby “beautiful” sometimes obscures intent from either the programmer or the underlying platform.

    Performance is obviously a key issue. Sometimes, you really need raw native maths or byte arrays and Fixnum, Float, and Array introduce too much overhead. Using Java gives us a “known quantity” when it comes to performance.

    Now of course I’m not saying Ruby won’t continue to get faster and faster. JRuby on Java 7 has started to approach Java performance for many algorithms, and as JRuby and the JVM improve, the gap will continue to narrow. But optimizing a dynamic language is challenging even on the best VMs, so it’s nice to have that “known quantity” when performance is critical.

    JRuby’s a Ruby Implementation and a JVM Language

    Then there’s also the matter of interfacing with statically-typed JVM libraries. JRuby makes heavy use of JVM libraries for much of its internals. That has meant we don’t have to implement our own collections, IO subsystem, JVM bytecode generator, YAML 1.1, and much more. Of course some of these could be called via our Java integration layer, but there’s always a bit more overhead down that road than by having Java calling Java.

    Almost as important is the fact that nearly all of JRuby’s core classes can be called as normal Java classes from any piece of JVM code. Java integration is a two-way street, and having Ruby-only implementations would make one direction more challenging to support.

    Don’t Throw Out the Baby

    Moving to Ruby for new code is easy enough, but moving existing code to Ruby would mean throwing out known-working, battle-tested, optimized Java implementations for something completely new. Any good developer knows that a “big rewrite” seldom ends well, so we’d be doing a great disservice to the thousands of JRuby users out there by making a wholesale move to Ruby. There’s no measure of benefit (from rewriting in Ruby) that would outweigh losing years of maturity in our codebase.

    Inertia

    Inertia may be the biggest motivator here. The JRuby committers are very familiar with Java and with the current implementation. They also may know Ruby very well, but change is always accompanied by some measure of confusion.

    Most of the JRuby core team manages a subset of JRuby; Tom Enebo works on parser, interpreter, and the new IR compiler. Nick Sieger works on libraries like activerecord-jdbc and jruby-rack. Wayne Meissner works on our native library integration layers like FFI. I work on compilation, optimization, and Java integration. Do we force everyone to start writing in Ruby when they may prefer to use Java?

    Developer Pool

    As much as Ruby has grown in recent years, there are still far more Java developers in the world. They may not love the language, but they represent a tremendous potential pool of contributors to JRuby. Yes, it’s true that a Java developer is probably less likely to contribute to JRuby than a Rubyist… but there’s still a hell of a lot of them out there.

    There’s also a very large portion of JRuby users (perhaps even a majority) that are either primarily or originally Java folks. Having a mostly-Java codebase means they can more easily investigate bugs, integrate JRuby into their JVM-based applications, and generally reason about how JRuby actually works. That’s very powerful.

    But We Still Want to Do It!

    Even though I list a bunch of reasons for having a mostly Java codebase, we do recognize that Ruby is an excellent tool for both writing apps and for implementing Ruby’s core. And we have always intended to make it possible for JRuby to use more Ruby code as part of the core implementation, even if we never do a wholesale rewrite.

    To that end, I’ve started restructing the (admittedly small) Ruby-based “kernel” of JRuby into a structure that’s more approachable to Rubyists that want to contribute to JRuby. The restructured Ruby kernel is under src/jruby, and while there’s not much there right now we’re willing to accept new code in either Ruby or Java. If it becomes a performance or integration problem, we may rewrite that code in Java…but having a working implementation in Ruby is far better than having nothing at all.

    Whither Rubinius?

    You might be asking yourself “why not just use Rubinius’s kernel?” We’ve always hoped (maybe intended) to use as much as possible of Rubinius’s mostly-Ruby kernel in JRuby, if at some point that seemed feasible. With recent performance improvements in JRuby, that day may be approaching. We would need to patch away anything that’s Rubinius-specific, but I have toyed with how to start using Rubinius’s kernel in JRuby several times in the past few years. If we can borrow their code for missing or poorly-implemented parts of JRuby, it would be stupid for us not to do so.

    It’s also worth pointing out that Rubinius has very few of the challenges JRuby does when it comes to integrating with an existing platform. Rubinius was designed as a Ruby VM alone, so there’s no equivalent to Java integration. When Rubinius wants to utilize native libraries, they do what we do: write wrapper logic in C/++ (equivalent to JRuby’s Java code) or bind those libraries with FFI (similar to but more basic than our Java integration). And Rubinius exposes no native, statically-typed API to its implementation classes.

    How Can You Help?

    Right now we’re looking to use Ruby mostly for missing features. Since we’re still in the midst of filling out Ruby 1.9.2 and 1.9.3 features, that’s a good place to start.

    We use and contribute to RubySpec, just like Rubinius does, so you can easily find missing or broken features by looking under spec/tags in our codebase.

    (RubySpec supports the concept of “tagging”, where known-failing specs can be “tagged” until they pass. This allows implementations to maintain a “watermark” of passing specs over time, and allows contributors to easily see and fill in implementation gaps.)

    You’ll want to fetch the revision of RubySpec we currently test against by running rake spec:fetch_stable_specs (or ant fetch-stable-specs; git must be installed in both cases), but after that you can run specs using spec/mspec/bin/mspec in the usual way.

    And of course if there are Ruby 1.8 or 1.9 features that are weakly specified by available tests, we strongly encourage you to contribute specs directly to the RubySpec project, so that all implementations can benefit.

    We hope that making it easier to implement JRuby using Ruby code will make it more approachable to Rubyists, and we’re looking forward to helping you craft your first pull request! Stop by #jruby on Freenode IRC this week and we’ll help you out!

  • The Painting's on the Wall

    Published by Shane Becker on October 13, 2011

    The fine folks at Lunar Logic Polska love JRuby so much that they put their money where their mouth is. Or rather, they put their paint where their heart is. Showing their affection for JRuby, they painted JRuby Duke on their office wall for everyone to see.

    First, they used a projector to trace the image onto the wall (an effective and simple solution that I’ve used before too).

    Tracing the image onto the wall

    Many hands make light work.

    Two people painting

    Almost there. Almost there.

    Rough draft

    Putting on the finishing touches.

    Polishing the details

    The final product.

    Finished painting

    Clearly, the Lunar Logic Polska team is full of very smart and good looking people!

    Lunar Logic Polska team

    See the full gallery on Konrad Malawski’s Google Plus account.

  • Bringing JRuby to the Cloud

    Published by Charles Oliver Nutter on September 28, 2011

    My friends, I’m proud to announce we’ve reached another milestone with JRuby: the full, non-beta, general availability of Engine Yard Cloud’s JRuby support!

    The release of JRuby on our Cloud comes after years of work on JRuby and months of work by David Calvera, Hiro Asari, and the awesome stack team at Engine Yard. It is, in many ways, the “big goal” we had when Tom Enebo, Nick Sieger and I came to Engine Yard in 2009 to continue working on JRuby. We’re very excited to have accomplished our big goal for JRuby at Engine Yard, and will now look forward to new goals and milestones. But what does this mean to you? And how did we get here?

    JRuby on Engine Yard Cloud

    If you’ve ever used Engine Yard Cloud before, you already know what it feels like. JRuby support looks and feels pretty much the same; you just select JRuby from the Ruby versions drop-down, choose Trinidad, and deploy your app as normal. Provisioning, deployment, and migration all happen for you automatically. You can configure Trinidad to spin up enough JRuby instances to handle your concurrent load, or run “threadsafe” using a single instance. And that’s it! You have your JRuby application in the cloud, with support from the best team in the Ruby cloud universe.

    The Cloud’s support for JRuby represents milestones for the wider Ruby world, too. It’s obviously the first cloud to officially support JRuby, but it’s also the first cloud with a concurrency-capable Ruby and the first cloud supporting an alternative Ruby implementation. You get the best cloud with the best support story and one of the best Ruby implementations on one of the best VMs in the world. What’s not to love?

    We at Engine Yard and on the JRuby team are very proud to have finally achieved this milestone. Let’s take a look back at the past five years of JRuby that led us to this point.

    A Brief History

    I’ve talked about the history of JRuby in many posts, and I’m preparing one on JRuby’s 10-year anniversary as you read this. The journey really started in 2006, when Tom and I first demonstrated JRuby running a Rails application at JavaOne. That was JRuby 0.8.3, and six months prior we couldn’t even run IRB. In those days, the JVM world was just starting to explore alternative languages, with most of that attention on Jython and Groovy. Scala, Clojure, and the other half-dozen “new” JVM languages you may have heard about were either still growing up or still hiding behind the curtain of academia.

    That first demo saw JRuby running on WEBrick, because there were no other servers for JRuby yet. No native DB support existed for JRuby, so we had to get the pure-Ruby MySQL driver working. We were able to install gems and run IRB, but the Rails console didn’t work and everything felt ready to fly apart. Just days before JavaOne, we got it working.

    Tom and I were sitting at the Espresso Royale coffee shop near the University of Minnesota campus, walking through the basic CRUD operations and making sure everything functioned. It all seemed to work – and that was very exciting – but the performance was really dreadful. It took seconds for each page refresh, sometimes so long we thought the app had hung.

    On a hunch, we started looking for Rails tuning advice. One page talked about something called “development mode” and highly recommended using “production mode” for production applications. Without any other leads, we flipped the switch…and the JRuby on Rails age dawned! Performance was not spectacular, but it was totally acceptable for a first public showing. Rails was running atop the JVM, and JRuby made it possible!

    A year later, Tom and I had accepted positions at Sun Microsystems and were preparing to release JRuby 1.0 for JavaOne 2007. We were optimistic…we felt like JRuby was ready for simple, non-critical production apps, and we were eager to show the JVM world what we could do. This time, we had Nick Sieger’s ActiveRecord-JDBC for database access and an early precursor to jruby-rack called “GoldSpike” (after the golden spike that joined east to west in the early USA rail system) to allow servlet engines to serve up Rails requests.

    JRuby 1.0 was fully interpreted, quite slow, and far less Ruby-compatible than JRuby today, but it worked. And it was enough to draw in a few early production users like Oracle and Thoughtworks.

    The next year saw the release of JRuby 1.1, the first Ruby implementation ever to incorporate a runtime just-in-time (JIT) compiler to improve performance. We were starting to beat Ruby 1.8 on simple benchmarks, and stability kept increasing.

    JRuby has had many more releases, always focusing on the user’s experience and the user’s needs. JRuby 1.1.1 through 1.1.6 made huge leaps forward in compatibility and performance, and JRuby 1.2 may have been the first release really ready for production. JRuby 1.3, 1.4, and 1.5 each involved thousands of commits and hundreds of fixed bugs, along with more and more production users ranging from airports to the Allen Telescope Array.

    This year, we released JRuby 1.6 with Ruby 1.9 features and experimental support for C extensions, and have done four 1.6.x maintenance releases (with a fifth just around the corner). JRuby 1.7 will take advantage of the new “invokedynamic” support in Java 7, and runs far faster than any previous release.

    JRuby is now more compatible and boasts better performance than ever before, and has earned a place in both the Ruby and Java worlds.

    JRuby meets the Cloud

    The earliest talk about JRuby at Engine Yard started in late 2008. Tom Mornini reached out to us, interested in talking about what a JRuby-powered Engine Yard offering might look like. We talked on and off with him and other Engine Yarders in early 2009, and finally visited the Engine Yard office to talk seriously about making something happen.

    We were lost deep within another cloud: the cloud of doubt hanging over the Oracle takeover of Sun Microsystems. With change in the air, Tom, Nick and I accepted new positions at Engine Yard, and the wheels were set in motion for JRuby support.

    It was a hard slog to get here. Engine Yard’s cloud was under heavy development, marketing, and rebranding, so we kept cranking out JRuby releases and helping anyone with available cycles get to know JRuby better. In early 2010, Engine Yard hired Hiro Asari, a long time JRuby contributor also interested in making a move. Hiro became the first-ever-anywhere JRuby support engineer, and we launched official commercial support for JRuby later that year.

    The arrival at engine yard of David Calavera, creator of the Trinidad server, finally gave us the missing piece needed for JRuby on Engine Yard Cloud. We went to alpha stage early in 2011 and to beta some months later for RailsConf.

    With a few production users under our belt, we decided RubyConf 2011 was the right time to go to GA (general availability). And here we are!

    Next Steps For You

    Engine Yard wants to help you bootstrap your application, and to do so we’re continuing to offer 500 free compute hours. That applies to JRuby too, so there’s really no reason not to give it a shot. If you’ve ever wanted to try deploying to JRuby, or if you’ve never played with Engine Yard Cloud, today is the day!

    All the Engine Yard JRuby team members will also be at RubyConf this week, and we’ll be holding continuous office hours wherever we stand (perhaps with some scheduled office hours too) to help you get started on Engine Yard Cloud, help you attempt a migration to JRuby, or just to hear what you want from JRuby. We’ve done all this work for you, the Rubyists and JRubyists of the world, and we want you to have the best experience possible!

    Finally, I’d really like everyone to send a big “Thank You” to @engineyard on Twitter. Without their support these past couple years, JRuby would not have made so much progress. Without a commercial support offering, several large JRuby users might never have used Ruby at all. And now, with official cloud support, deploying JRuby is a fire-and-forget proposition. Engine Yard helped us bring JRuby to maturity, and the Ruby world is a better place as a result.

    Thank you all, friends, for your support these many years. I hope to hear from each and every one of you, and you can rest assured more great things are coming from JRuby and Engine Yard.

  • HELP WANTED JavaOne Script Bowl Demos

    Published by Thomas E. Enebo on September 22, 2011

    JavaOne Script Bowl (Weds. Oct. 5, 8:30am) is an annual event at JavaOne where various languages which run on the JVM get to showcase the best they have to offer in two short ~5 minute segments: technology and community. Ruby (via JRuby) has been involved in this event for the four years it has existed. This year we are facing off against Clojure, Scala, and Groovy. We are trying to prepare for this event and we need your help!

    The main goal of this event is for Java language programmers to get a good taste of what the alternative JVM languages have to offer. By the end of the script bowl, the typical attendee has hopefully been infected with the desire to look into one or more new languages. Our goal is to entice the attendee to fall in love with Ruby.

    For the technology segment we plan on showing several things which make Ruby shine in comparison to other JVM languages (Java included). We plan on showing the simplicity of Sinatra; The brevity and power of Rake along with JRuby’s Java Ant integration; The future of Jenkins via Ruby plugins; Also perhaps a display of our ability to install any Maven artifact as it it were a Ruby gem. We are still open to any other cool technology demos, so if you can cook up a cool demo then let us know.

    For the community segment we are looking for examples/demos which underscore why the Ruby community is worth taking notice of. Rails is the 500 pound gorilla in the room, but technologies like Sass underscore how much innovation is happening in the Ruby community. This segment can be done with live demos, but we are also looking for reasoned arguments of why the Ruby community is great. A few other ideas: interesting testing technologies, zero-turnaround deploys.

    So how can you help? Please send us:

    • A cool demo using a Ruby technology
    • A simple pitch (like 4-5 slides) showing an example of how the Ruby community shines

    If we end up using your idea or demo, you will get a JRuby t-shirt as thanks for helping. Hell, if we don’t use your idea but appreciate the effort you put into your submission, you may get a t-shirt anyways.

    Your submissions, whether code or a tech pitch, should be sent to [email protected] as a link to a github.com repository with a description of what you are sending us (also put it in the README in the repo). Any pitches or demos will probably only be shown for 1 minute or less during script bowl so take this into consideration when making your submissions. Oh….one more small detail: deadline for accepting submissions is Sept 30! So get cracking and help us make this the most memorable Script Bowl yet.

  • New JRuby T-Shirts

    Published by Shane Becker on September 14, 2011

    I Heart JRuby shirt

    I <3 JRuby shirt

    Do you totally love JRuby? Of course you do. Want a t-shirt to show the world just how much you love JRuby? Of course you do. Here’s how you can get one.

    • Write up an amazing blog post about JRuby – your experience with it, something great you’ve learned about it (and yourself), clever solutions to tricky problems, etc
    • Present about JRuby at a local meetup – try to video record it and post it online
    • Give a talk about JRuby at a conference
    • Convince the company that you work for to start using JRuby in its stack
    • Get part of your work time budget to contribute to JRuby and/or JRuby related projects

    Do one of those things and you’ll earn yourself one of these super comfy t-shirts to wear proudly.

    Stay tuned for how to request your shirt

    A JRuby Production shirt

    A JRuby Production shirt

    Are you using JRuby in production? Are you willing to talk about it publicly? Will you let us interview you and/or your team to do a post about your experience? If so, we’ve got special t-shirts for you. Get in touch and tell us what you’re up to with JRuby and who we should talk to about it.

    Email: [email protected]


    Shirts modeled by my friends Kristen and Alex at The Farmhouse in Hollywood, California

  • activerecord-jdbc-adapter 1.2.0 Released!

    Published by Nick Sieger on September 13, 2011

    With the advent of our new jruby.org blog comes a new software release. Our JDBC-based adapter for ActiveRecord is now compatible with the Rails 3.1 release. AR-JDBC is also tested to be compatible with 2.3.x and 3.0.x.

    Install it as usual with gem install activerecord-jdbc-adapter.

    A new and notable feature of Rails 3.1 is that support for AR-JDBC is built-in. So when you generate a new Rails application with JRuby, your Gemfile will be set up automatically for use with JRuby and AR-JDBC. The rails new command:

    rails new photoblog -d mysql
    

    creates the following section of the Gemfile:

    gem 'activerecord-jdbcmysql-adapter'

    So, no more -m http://jruby.org, no more rails generate jdbc, nothing. JRuby on Rails works out of the box.

    I also want to take a moment to welcome Anthony Juckel, Arun Agrawal, Guillermo Iguaran, Matt Kirk, Luca Simone, and Samuel Kadolph for stepping up to the plate to help maintain AR-JDBC going forward. Thanks everyone!

  • A Start

    Published by Shane Becker on September 09, 2011

    Ready, Set… Go!

    For some time now, there’s been a unified feed of mostly release notes. But never really a unified place for non-release notes information about JRuby. There was the [Engine Yard blog](http://www.engineyard.com/blog/?s=jruby “Jruby Engine Yard Ruby on Rails Blog”), Charles Nutter’s blog, Nick Sieger’s blog, Tom Enebo’s blog and various other sources. (The release notes feed will continue to exist. No need to change your feed readers.)

    Today we change that. You now are looking at the new home for news, information and all of the things JRuby related that aren’t release notes.

    Tell your friends and stay tuned for more.

  • JRuby.org Launched!

    Published by JRuby Team on June 13, 2009

    Of course we launched the new JRuby.org yesterday. There’s still some content to be refined/revised and plenty of styling to clean up, but it’s a vast improvement over our previous non-existent web presence. We’re thrilled with the design of the site and keen to add more useful content over the next couple weeks.

    And for anyone interested, contact [email protected] if you want to get a similarly smoov design for a site of your own.

    Check it: http://www.jruby.org

All post content is licensed under Creative Commons Attribution 3.0 unless stated otherwise by the author in that post.

OSZAR »