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

JRuby: Past, Present, and Future

Avatar for headius headius
September 17, 2026

JRuby: Past, Present, and Future

JRuby on Rails is 20 years old! This talk reviews the last 20 years of JRuby development, with a focus on the challenges of supporting Ruby and Rails year after year.

We'll look at the state-of-the-art features that make JRuby attractive and talk about the next generation of JRuby capabilities and applications. JRuby brings a whole new world of opportunities to Ruby — come learn how to use it to do more with Ruby.

Presented at Euruko 2026 in Brno, Czechia.

Avatar for headius

headius

September 17, 2026

More Decks by headius

Other Decks in Programming

Transcript

  1. @headius headius.com Dobrý den! • Charles Oliver Nutter ("headius") •

    My rst EuRuKo was 2008 (Prague!) • 20 years full-time JRuby dev • Stickers and t-shirts! • Co-founder of Headius Enterprises • fi • "The JRuby Company" I love Ruby, karaoke, and beer!
  2. Professional Career • 1996-1998: University of Minnesota • Java applets,

    web-based registration system • 1998-2002: Senior Java Developer at various jobs • 2002-2006: Java Enterprise Architect • Converting mainframe apps for US government
  3. RubyConf 2004 • My rst Ruby conference • • Hallway

    hacking: Rake, RubyGems • Pickaxe 2 released by PragProg • A total of 65 attendees! • fi I didn't even know Ruby! Including some names you know...
  4. Ko1 に聞け YARV Ko1 に聞け YARV RubyVM Yet Another Yet

    Another RubyVM ささだ こういち ささだ日本Rubyの会 こういち 東京農工大学大学院 東京農工大学大学院 [email protected] 日本Rubyの会 [email protected] RubyConf2004 Oct. 2 3 RubyConf2004 Oct. 2 3
  5. A. Self Introduction (cont.)  Software • Rava: A JavaVM

    in Ruby • My best joke software Ear ly in for spirat JRu ion by? ! • Rucheme: A Scheme interpreter in Ruby • Compile to instruction set which I designed • I like Scheme • Nadoka: IRC Client Server software • IRC proxy/bouncer • Ruby’s killer application (… nobody else may agree) 9
  6. JRuby is Reborn • 2001-2004: Early work on JRuby •

    • 2004: low activity, few developers • • Parser, interpreter, basic core classes (Ruby 1.6) Tom Enebo, my university co-worker! It seemed like destiny • But what are we going to do with it?
  7. Ruby on Rails • Rails was changing the web dev

    world • JVM is amazing for web apps • The obvious path: JRuby on Rails! • Could it be done? 🤔
  8. The Road to Rails • JRuby in 2005: Nothing worked!

    • Started with basic tools • Ran every test we could nd, wrote our own • Ruby on the JVM is really hard In other words... challenge accepted! fi •
  9. IRB • First step: run the REPL • Language compatibility

    work • Implement "eval" • Console work: stdio and readline support • One day in early 2006, it worked! $ irb irb(main):001:0> 1 + 2 => 3 irb(main):002:1* class Foo irb(main):003:2* def foo irb(main):004:2* puts 1 irb(main):005:1* end irb(main):006:0> end => :foo irb(main):007:0> Foo.new.foo 1 => nil
  10. [] jruby-0.8.3 $ ls bin COPYING.CPL COPYING.LGPL lib samples COPYING

    COPYING.GPL docs README [] jruby-0.8.3 $ bin/jruby -v ruby 1.8.2 (0) [java] [] jruby-0.8.3 $ bin/jruby -e "puts 'hello, world'" hello, world [] jruby-0.8.3 $ ls samples beer.rb eval.rb java2.rb swing2.rb xslt.rb error.rb fib.rb swing.rb thread.rb [] jruby-0.8.3 $ bin/jruby samples/swing2.rb [] jruby-0.8.3 $ bin/jruby -I ../ruby-1.8.2/lib ../ruby-1.8.2/bin/irb irb(main):001:0> RUBY_VERSION => "1.8.2" irb(main):002:0> PLATFORM => "java" irb(main):003:0>
  11. Rake and RubyGems • After RubyConfs 2004 and 2005, tools

    started to solidify • Rake for build tooling • RubyGems for packaging • Sockets, zlib, YAML fi • File/IO APIs, Dir, lesystem access
  12. It All Comes Together • • JRuby on Rails works!

    • But it's SUPER SLOW! 😂 • Still in development mode! 🤦 JavaOne 2006 • • 1800 people in the room! Sun Microsystems hires us • Full-time JRuby!
  13. @headius headius.com JRuby = Opportunity • • Ruby is amazing,

    but has many challenges • C extensions break optimization • Real world needs parallelism, big data • Ruby ecosystem missing functionality JRuby is enterprise-ready! • JVM is trusted, optimized, parallel, scalable
  14. CRuby JRuby High Concurrency CLI Tools Low Memory Data Pipelines

    Legacy C Exts Web Apps Forking API Servers POSIX Ecosystem Big Data JVM Ecosystem Packaged Deployment GUIs and Games
  15. JRuby Worldwide • Thousands of applications running JRuby • Production

    users since 2007 • Most users could not use Ruby without JRuby • JRuby opens up new opportunities for Ruby • I'll highlight some users along the way
  16. @headius headius.com User: Quantum Inventions • Software for intelligent transport

    systems, focusing on smart city mobility and eet mobility as a service. • Rails-based GUI apps deployed onpremises with Oracle DB and WebLogic • User-acceptance testing using packaged JRuby apps within customer environments • Ruby-based data processing packaged as JRuby apps run by customers https://quantuminventions.com/ fl • "We use [JRuby] for running Ruby in environments without Ruby!"
  17. @headius headius.com JVM Language • JRuby is a JVM language

    • Libraries, ecosystem, extensions written in JVM languages • JVM can optimize all of this code • No C extensions to prevent optimization • True concurrency everywhere
  18. Class#new Optimization • CRuby 4 added opt_new to optimize Class#new

    • • Using C code to allocate + initialize is hard to optimize JRuby implemented in 2016 • Normal Class#new: allocate and call #initialize directly • Everything can inline and optimize
  19. JIT Compilers • • HotSpot JIT introduced in 1999 •

    27 years of improvements • Thousands of development years of work JRuby compiles to JVM bytecode • JVM JIT compiles that to native code • First native JIT for Ruby!
  20. Garbage Collectors • • JVM has the best GCs! •

    Scale up to enormous heap sizes • High throughput, low pause times GC won't be your problem • Cleans up faster than you allocate
  21. @headius headius.com Concurrency • • Ractors bring concurrency to Ruby

    • Many VM challenges • Dif cult* to use (immutability, C extensions) JRuby Threads are already 100% parallel • Low overhead for threads and shared memory • Easy* to use! fi * Concurrency is never easy.
  22. @headius headius.com fi User: OpenVox Server • Unpredictable performance of

    con g compiler on CRuby • Scaling did not linearly improve throughput, diminishing returns with more nodes • JRuby brought near-linear scaling with the same code • Codebase combines Ruby and Clojure • https://github.com/OpenVoxProject "Using JRuby to put the compiler into the JVM alleviated that [scaling] problem"
  23. @headius headius.com puts "single-threaded version" 10.times do t = Time.now

    1000.times.map do JSON.parse File.read("1MB.json") end puts Time.now - t end
  24. @headius headius.com puts "Thread version" 10.times do t = Time.now

    100.times.map do Thread.new do 10.times.map do JSON.parse File.read("1MB.json") end end end.each(&:join) puts Time.now - t end
  25. @headius headius.com puts "Ractor version" 10.times do t = Time.now

    100.times.map do Ractor.new do 10.times.map do JSON.parse File.read("1MB.json") end end end.each(&:join) puts Time.now - t end
  26. @headius headius.com Threads vs Ractors (~6 cores) CRuby threads CRuby

    ractors 6x 6 4.5 3.7x 3 1.5 0 JRuby threads 1.6x
  27. @headius headius.com Threads vs Ractors (20 cores) CRuby threads CRuby

    ractors 20x 20 15 10 5 1.7x 0 JRuby threads 3.8x
  28. @headius headius.com User Focus: Poshmark • Leading social commerce marketplace

    with millions of users • High concurrency and heavy transaction volumes daily • Leveraging JVM ecosystem for resilience, growth, and scaling • Migrating to MongoDB Java driver reduced p50 by 30% and p95 by 35% • https://poshmark.com/ "JRuby has been integral to Poshmark's stack for over a decade and remains a cornerstone of scalability and innovation"
  29. @headius headius.com Libraries • • JVM ecosystem has hundreds of

    thousands of libraries • Graphics, GUIs, servers, document formats, ML/AI/LLM • One of the largest collections in the dev world All available to Ruby! • Easy integration into Ruby apps and code • "Magic" to make Java APIs look like Ruby
  30. @headius headius.com Dependencies Jar le • Jar le for JVM

    deps • jar 'org.jfree:jfreechart:1.5.5' jar 'org.jfree:org.jfree.chart3d:2.1.0' Like Bundler's Gem le $ lock_jars • lock_jars command • Like `bundle install` -- jar root dependencies -org.jfree:jfreechart:1.5.5:compile org.jfree:org.jfree.chart3d:2.1.0:compile org.jfree:org.jfree.svg:5.0.6:compile org.jfree:org.jfree.pdf:2.0:compile fi fi fi Jars.lock updated
  31. Load Data into Dataset require 'json' dataset = StandardCategoryDataset3D.new data

    = JSON.load(File.read("revenue.json")) data.each do |name, subset| values = DefaultKeyedValues.new subset.each { values.put(_1, _2) } dataset.add_series_as_row name, values end
  32. Create a 3D Bar Chart chart = Chart3DFactory.create_bar_chart( "Quarterly Revenues",

    "Application Monitoring Companies", dataset, nil, "Quarter", "$million Revenues") chart.chart_box_color = Color.new(255, 255, 255, 127) chart.legend_anchor = LegendAnchor::BOTTOM_RIGHT chart.plot.gridline_paint_for_values = Color::BLACK
  33. @headius headius.com Generate PNG width, height = 600, 500 image

    = BufferedImage.new(width, height, BufferedImage::TYPE_INT_RGB) graphics = image.create_graphics chart.draw(graphics, Rectangle.new(width, height)) png_file = File.open("category_chart.png", "w") ImageIO.write(image, "PNG", png_file.to_outputstream)
  34. @headius headius.com User Example: eazyBI World-class reporting and business intelligence,

    integrated into the Atlassian stack • JRuby user since 2011 • Integration with Java libraries like Mondrian OLAP, Apache POI, Batik • Deployment as a Jira plugin .jar le • Real multithreading without global lock for heavy parallel worker pools and data import jobs • Deploy on Windows more easily than CRuby • https://eazybi.com/ fi •
  35. • Open-world exploration, construction, and combat game available on Steam

    • DragonRuby used for front-end graphics • World management handled by JRuby backend •
  36. Ractor? • • Ractor = Thread? • ractor_shim gem just

    uses Thread internally • json example is same code for Ractor and Thread Don't really need Ractor on JRuby • Everything can run in parallel already • Immutable state remains just as safe
  37. Box? • • JRuby has always supported isolated runtimes •

    org.jruby.Ruby.new_instance => new JRuby runtime • Deploy fully isolated apps in one process Experiment: Box on top of org.jruby.Ruby • Fully parallel as usual • Fully isolated is better than monkey-patching
  38. example.rb require './box' box = JRuby::Box.new box.require("./funky.rb") obj = box::Funky.call

    puts obj puts Funky rescue puts $! $ jruby example.rb hello from Funky uninitialized constant Funky
  39. box.rb module JRuby class Box def self.new Class.new(Box) do @ruby

    = org.jruby.Ruby.new_instance end end def self.const_missing(const) @ruby.object.const_get(const) end def self.require(feature) @ruby.load_service.require(feature) end end end
  40. Stable and Edge • JRuby 10.0.x is the "stable" line

    • Ruby 3.4 compatible • Mostly bug and security xes JRuby 10.1.x is the "edge" line • Ruby 4.0 compatible (released only 3 months after CRuby 4.0!) • Active performance experimentation • More invasive refactoring and improvements fi •
  41. Shrinking Objects • • Reduced object size in JRuby 10.1

    • Smaller objects across the system • Better throughput, less GC overhead Much smaller JRuby processes!
  42. fl JRuby 10.0 • 32-byte objects • JVM object header:

    12 bytes • Flags: 4 bytes (shared by all objects) • Class pointer: 4 bytes • Instance variable array: 4 bytes padding lock ivars ags 32 bytes 12 4 4 4 • Instance variable table lock: 4 bytes • Padding for object alignment: 4 bytes 4 4 class header
  43. fl JRuby 10.1 • padding lock ivars ags 24-byte objects

    • JVM object header: 12 bytes • Flags: 1 byte (other objects have their own) • Class pointer: 4 bytes 12 • Instance variable array: 4 bytes 1 1 • Instance variable table lock: 1 byte 4 Padding for object alignment: 2 bytes 4 2 • 24 bytes class header
  44. JVM Improvements • • Compressed Pointers (Compressed OOPs, 2006) •

    Use 32 bits instead of 64 bits for object references • GC manages indirection Compact Object Headers (Project Lilliput, 2023) • Shrink the size of all JVM objects
  45. fl Project Lilliput • padding lock ivars ags class header

    Object headers 12 bytes to 4 bytes 24 bytes • • • • Reduced class pointer size Lazy identity hash code (object ID) Expand other data as needed 16-byte objects! 12 16 bytes 1 1 4 1 1 4 4 4 2 4 2 Normal Lilliput
  46. Object.new memory size 40 bytes 32 bytes 24 bytes 16

    bytes CRuby 4 JRuby 10 JRuby 10.1 JRuby 10.1 (L)
  47. Fixnum Splitting • JRuby always boxes integers and oats •

    JRuby 10.0 integers: 40 bytes • JRuby 10.1 integers: 32 or 24 bytes • • short version goes down to 24 bytes But this is an object so there's also a 4-byte pointer reference fl • 32 byte object + 8 byte long
  48. 28 bytes 28 bytes y ub JR y ub JR

    y ub JR y ub JR y ub JR by Ru C .1 10 .1 10 .1 10 .1 10 .0 10 4 L) ) (L t( or sh ng lo t or sh ng lo fi Pointer + xnum size 44 bytes 36 bytes 20 bytes 8 bytes
  49. 32k Fixnum Array Size 1,431,616 bytes 911,416 bytes 649,272 bytes

    262,184 bytes y ub JR y ub JR y ub JR by Ru C .1 10 .1 10 .0 10 4 L) t( or sh t or sh
  50. while i < 100_000_000 7 6.34x 5.25 3.08x 3.5 1.75

    0 1x 1.06x CRuby 3.4 CRuby 4.0 JRuby 10.0 Times faster JRuby 10.1
  51. Marshal Load Performance medium_data = { :id => 1, :name

    => "test" * 100, :values => (1..1000).to_a, :nested => { :a => 1, :b => 2, :c => (1..100).to_a } } # Load only benchmark dumped = Marshal.dump(medium_data) loop { t = Time.now 100000.times { Marshal.load(dumped) } puts Time.now - t }
  52. Marshal.load 100k medium data 6 5.23s 4.5 3 2.03s 1.83s

    1.5 0 CRuby 4.0 JRuby 10.0 JRuby 10.1
  53. ! N O SO C O M IN G Advanced

    Shaping • Guessed at rst allocate • Never change after that 10.1+: Allow object shape to evolve • Expand as more instance variables discovered • Shape selection at allocation site fi • 10.0: Object shapes in JRuby are xed fi •
  54. ! N O SO C O M IN G Specialized

    Strings • Codepoint (immutable) • • Compact • • Use 2-byte padding for UTF-16 char Embed small string in 8-byte long Java String wrapper (immutable) • Reduce cost of calling JVM APIs
  55. ! N O SO G IN O M C Specialized

    Array • Exact size using Java elds (no Object[]) • Direct numeric values (packed integers or doubles) • Mixed (both numerics and objects) • Any JVM List type Including thread-safe, trees, native memory fi •
  56. ! N O SO C O M IN G Specialized

    Hash • Open addressing • Direct key/value elds (2*N elds instead of buckets or Object[]) • Mutexed fallback where needed • Any JVM Map fi Concurrent, trees, database result set, ... fi •
  57. ! N O SO G IN O M C Direct

    Argument Passing • All arguments passed directly on stack • Even to core class methods • Optional values, keyword layout in call site metadata • Zero-allocation for all forms up to N wide • JVM inlining optimizes register use
  58. Foo.new(1) vs Foo.new(a:1) allocation rates 28.2x 30 23.8x 22.5 15

    WE CAN FIX THIS 7.5 1x 5.37x 2.8x 1x 2.65x 0 Foo.new(1) CRuby 3.4 Foo.new(a:1) CRuby 4.0 JRuby JRuby (L) 3.29x
  59. ! N O SO G IN O M C Value

    Type Numerics • • Boxed numeric objects are slow and heavy • All Integer and Float are objects in JRuby • JVM is good, but not that good yet Project Valhalla brings true value types (stack-allocated) • JRuby will move numerics to value types • Zero-alloc maths and compact collections for free!
  60. ! N O SO G IN O M C Fast

    Native Access • • FFI is the future of native integration • Avoid C extensions and problems they cause • Portable to all Ruby implementations Project Panama brings fast Foreign Functions and Memory • Optimized native invocation and memory management • JIT, GC understand and optimize native access
  61. JRuby in 2026 • JRuby remains 100% Open Source Software

    • One self-funded developer, many community members • We need your support! • Try JRuby and help us improve • Present JRuby to your companies • Sponsor a JRuby developer to keep working
  62. @headius headius.com Commercial Support • Expert support for your JRuby

    apps • New dev, migrations, upgrades • Bug prioritization, security SLAs • Help with your code under NDA • headius.com/welcome • Site by
  63. @headius headius.com Thank You! • • Please get in touch!

    • @headius on socials • [email protected] • JRuby Matrix chat JRuby support • headius.com/welcome