00:00:04.860
Foreign.
00:00:11.059
Thank you so much for having me. I'm really excited to be here.
00:00:15.900
Let me preface this session by saying that all credit is due to the team that is working on JRuby, the individual contributors, and everyone involved. All credit goes to them, so big kudos to them; they're working on amazing features.
00:00:20.220
Now, I'm not a contributor, so let's get that out of the way. But thank you to me because I'm going to talk about Java at a Ruby conference, so that takes some courage, right?
00:00:38.579
So yeah, I'm just here to spread the word and tell you guys about my story with JRuby. Let me start by introducing myself. I'm Yarden Laifenfeld, a software engineer at Rookout. I have a background in low-level programming, C, and Linux IoT environments, and I jump around between languages a lot.
00:01:02.579
At Rookout, we're developing a debugger for production, supporting six different languages. This means I can code in up to six, or maybe even seven, different languages—not in a day, but maybe in like a month or two. I mainly work with Ruby, Java, and Go, but I also delve into C#, Python, JavaScript, and C++.
00:01:28.439
Then, one day, my boss came to me with a task: support JRuby. I was like, "What is JRuby?" So that's what I did; I looked it up. Now, let me take you back in time to the year 2000.
00:01:50.040
The panic about the Y2K bug was dying down, and maybe I could walk, but certainly not code. A lot of people were working on a very big problem that exists in Ruby even today, which is Ruby's performance. In 2007, YARV was created to improve performance to be about four times faster than Ruby. But in 2001, JRuby was created for the same reason.
00:02:20.640
JRuby is a hundred percent Java implementation of the Ruby programming language; it is Ruby for the JVM. Okay, that’s a very general thing to say, and let’s just jump right to it. Should we use JRuby? Should you use JRuby today? Let’s talk about the advantages.
00:02:46.680
First of all, JRuby is written in Java, which means the core libraries and everything work seamlessly with Java libraries. You can also call Java code from Ruby and Ruby code from Java. You may not enjoy coding in Java, but other people do, and they might write code that's really useful for you, so you could just write Ruby and integrate with their code using JRuby.
00:03:36.060
In addition, JRuby runs atop the JVM, giving it access to features like threads. Threads don't exist or aren't managed well in Ruby, but in Java, they work great, and you should definitely use them. So if your code is going to utilize threads, JRuby is probably better performance-wise. The JVM is known for handling long-running applications well; the longer an application runs, the more optimizations the JVM can apply.
00:04:36.780
For short-running applications, Ruby does just fine, but if your application is intended to run for a long time, the JVM excels in optimizing it based on previous function calls. There are amazing stories about people running services in JRuby for ten years, which is quite long.
00:05:07.680
JRuby has its advantages, and I found a GitHub gist from 2010 that I was proud of because, well, 2010 was a long time ago. Jordan Sissel was asked why he uses JRuby in Logstash, and he gives a few reasons. I won’t name them all, but he mentions that Ruby had some undocumented breaking changes between versions 1.8 and 1.9.
00:05:32.340
He noted that with JRuby, you're not using the Ruby core implementations, so you won't encounter those breaking changes and could therefore trust JRuby more than Ruby. Also, his code needed threads for asynchronous operations.
00:05:45.660
Now, in 2010, people chose JRuby, and not much has changed since then. However, CRuby also has its advantages, largely due to having a larger community. More people use CRuby than JRuby, which leads to more features being built. There are more contributors finding bugs, which means that if there’s an edge case in JRuby that only you experienced, it might take longer to fix.
00:06:05.040
A large community is important when talking about programming languages because a larger community translates to more support and more features. The latest version of JRuby is still being developed today and is compatible with Ruby versions 2.6 and down.
00:06:48.300
So these are the things to consider. Performance-wise, JRuby delivers, but in terms of syntax support, CRuby has its advantages. This isn’t to say that the JRuby community isn’t supportive, but it doesn't operate at the same scale.
00:07:35.160
To the question of whether you should use JRuby, my answer is: I don't know, you decide. Just like the choice of any language for your next project, choosing between JRuby and regular Ruby shouldn’t be any different. Consider performance, support, bugs, and how long you expect your code to run.
00:08:13.620
One major advantage of JRuby is that you don’t need to learn a new language. I’m guessing most of you know Ruby, so transitioning to JRuby isn't that difficult. But I'm getting ahead of myself because my original task wasn’t to learn what JRuby is; it was to support JRuby in a debugger for production.
00:08:37.500
So let’s discuss that. I split this task into subtasks. First was running an app, but this wasn’t just running an app with JRuby—it was running an app with JRuby while one of our debuggers was attached. The second part was adding a breakpoint; just being able to manipulate the code and stop it at a certain point. The third aspect involved collecting data, like a stack trace or local variables.
00:09:25.440
If you just add a breakpoint and stop the code without collecting anything, that’s not useful. So, it was decision time. We support both Java and Ruby; each has its own product. We have a Java debugger and a Ruby debugger, and JRuby is this unique mix of both. What should I choose? Everyone was telling me to try to support JRuby along with Java, but I did the only logical thing I could do: I ignored them.
00:10:05.760
I started working on Ruby. Just to bring you up to speed, I created a simple to-do app running on Rails. It’s running smoothly, and I use RVM (Ruby Version Manager) which comes with support for JRuby, making it really convenient. I could simply run 'rvm install jruby' and 'rvm use jruby', and voila, I had JRuby on my computer.
00:10:56.160
I ran the bundle install, and everything was working perfectly until... So, bundle install didn’t work as smoothly as I expected. I spent three full business days trying to install my gems. I swear it was three days because I remember it distinctly. I was contemplating whether I should even include this part in my talk.
00:11:26.100
But if even one of you goes home and tries JRuby and runs into this bug, it will save you so much time and frustration. Apparently, as a young Ruby developer, someone advised me to set 'force_ruby_platform' to true globally on my computer. This works great if you’re working with Ruby, but that’s not the case with JRuby.
00:12:14.700
In essence, JRuby doesn't support native extensions. When I set 'force_ruby_platform' to true, I was instructing bundler to utilize native extensions, which JRuby doesn't support. This led to an endless loop of nothing working, which was really frustrating.
00:12:51.600
The big fix is with the command 'bundle config unset force_ruby_platform'. This slide is the one you should be taking a picture of. It's the bug you don’t want. It’s quite straightforward to fix, and after that, the bundle install functioned smoothly.
00:13:53.760
I could run my Rails app with JRuby just like I did with Ruby. Everything was running well, and you could see right there that it was indeed running with JRuby. I made no changes to my code at all, so if you’re considering moving to JRuby, you might wonder about performance and how long it would take to start your application. Do it! It really is that easy.
00:14:23.520
Next, I wanted to run the app with the debugger attached. This is very easy; our debugger is just a gem. You add it with 'bundle add ruckout', and then you have to add an initialization line. After that, I was running again, and Ruckout was there, functioning perfectly with JRuby.
00:15:03.900
Now it was time to add a breakpoint. In Ruby, we handle this with something called the TracePoint API. The TracePoint API is quite useful; it allows you to trace your code by capturing various events, such as each time a line of code is executed or when a thread starts or ends.
00:15:30.480
You can sign up to listen for many events, allowing you to trigger actions when an event occurs. With the line event, for example, you can create a new TracePoint that subscribes to the line event and enables it so that every time a new line is executed, your code breaks and runs a callback.
00:16:24.480
However, we needed to consider performance, since this is a debugger for production. We don’t want to stop at every line; we only want to stop at the lines of interest. So, we give the enable method two parameters: one for the target method we want to pause at and one for the specific line number.
00:17:20.460
I tried integrating this in Ruby and JRuby but kept running into an error: 'wrong number of arguments calling enable'. I then realized that JRuby did not support the target parameter for enabling events.
00:18:08.040
So, for now, I could only use tracepoint.enable without those parameters, but that seriously affected performance, meaning placing a breakpoint in this way wasn’t viable. I had to reconsider my approach and ultimately decided to switch to Java.
00:18:54.120
With Java, we had to revisit our original three tasks. Running an app with a Java agent is a bit more complex. A Java agent is a Java program running alongside another app, which means it’s not useful by itself.
00:19:37.740
The agent uses the Java agent flag along with a JAR file to attach to the application. Instead of starting at the main method, it runs at pre-main, which is a minor difference. The agent has access to the instrumentation API, which allows it to inject bytecode into a running application.
00:20:24.540
Since JRuby operates at the top of the JVM, we can also pass flags to the JVM. By using the Java agent flag, I managed to get everything up and running smoothly.
00:20:57.540
Now it was time to add a breakpoint. Language integration on the JVM works by compiling all languages into bytecode, and the JVM knows how to run and optimize that bytecode.
00:21:29.040
However, I placed a breakpoint in a function that creates a to-do task, but the breakpoint didn’t activate. The class was supposed to load; I created a task and expected the function to run, leading to the class loader and transformation.
00:22:25.200
Frustrated, I added additional tasks, but even this didn’t help. By repeatedly invoking the function, the breakpoint then registered. Sometimes, it seems that frantic activity makes things happen.
00:23:11.040
It seemed that JRuby utilizes three compilation modes: interpretation, JIT, and actual compilation. In interpretation mode, JRuby interprets code line by line, which doesn’t load classes. During compilation mode, however, every Ruby class is loaded like a Java class and transformed through the class loader.
00:23:58.200
The JIT mode serves as a balance, compiling the code running frequently. Early on, when I called a function once or twice, JRuby didn’t prioritize it for loading, but as I invoked it rapidly, JRuby identified it as significant and compiled it through the class loader.
00:24:50.040
Finally, with force compilation, I could ensure that the bytecode would be compiled when needed, hence the breakpoints began activating seamlessly.
00:25:18.240
Yet, data collection proved to be challenging. I set a breakpoint to collect local variables, expecting to retrieve both the task variable and 'self' from the TasksController.
00:25:44.760
However, when I checked the collected variables, it gathered way more than just those two variables. It logged class scope, self, and a slew of additional contextual variables I hadn’t anticipated.
00:26:25.320
Parsing through these collected variables was tedious, but eventually, I managed to isolate and access the pertinent information to support JRuby.
00:26:50.640
In conclusion, I was able to implement support for JRuby successfully. Thank you so much for your time!
00:27:33.840
Now, there’s always a saying: if you're going to present Java at a Ruby conference, you better start strong. I think you did a fantastic job with that!
00:27:46.560
Looking back at what you've done from different points of view, what have been the key learnings from your journey with JRuby?
00:28:12.420
First of all, it’s incredible how innovative JRuby is considering it was created in 2001, which feels like a long time ago. I had no idea how much work went into building a Ruby interpreter in Java, integrating features like interpretation and compilation.
00:28:57.260
Also, the team behind JRuby is impressive. They’re attentive and engaged; any questions in their chat receive prompt answers, and they clearly have a deep understanding of their code.