Saturday, November 30, 2013

Running JRuby under JDB in Windows

I am working on some JRuby code that calls third-party Java libraries. The Java libraries were behaving oddly so I wanted to run them under JDB, the Java Debugger, so I can step through them line by line and inspect important values.

In Linux and Mac OS X, I think you should be able to do this by passing the --jdb option to JRuby when you run it. In Windows, JRuby does not support that option, but I was able to figure out how to do it anyway. Here is the command I used:

"C:/Program Files/Java/jdk1.7.0_45/bin/jdb.exe" -classpath "C:/jruby-1.7.4/lib/jruby.jar" -Djruby.home="C:/jruby-1.7.4" org.jruby.Main

The -classpath argument to JDB allows it to find the jruby.jar file, which defines jruby's org.jruby.Main class, which is the class to start if you want to use JRuby. The -Djruby.home option is recognized by JRuby and allows it to find its libraries and gems. If you want to pass any arguments to JRuby, then you can add them on to the end of this command, after org.jruby.Main. For my situation, I wanted to run RSpec so I added -S rspec:

"C:/Program Files/Java/jdk1.7.0_45/bin/jdb.exe" -classpath "C:/jruby-1.7.4/lib/jruby.jar" -Djruby.home="C:/jruby-1.7.4" org.jruby.Main -S rspec

Once you have started JDB successfully, you should see a message like "Initializing jdb ..." and a command prompt on the next line. My basic workflow is that I would figure out what class and method I want to inspect, and then I would add a breakpoint for it by running a command like this:

stop in com.example.namespace.ExampleClass.exampleMethod

Then run the run command. The JRuby and Java code will run until the specified breakpoint is hit, at which point the debugger will stop and let you interact with it again. Here are some more common commands I use:

  • where prints a full stack trace. These tend to be very long because of the internals of JRuby but if you scroll to the top you can see what part of the Java code you are in.
  • step advances to the next line of code, stepping into method calls if they are present.
  • next advances to the next line of code, skipping any method calls that might be present.
  • print EXPR evaluates the Java expression EXPR and prints the result. For example, if there is a local variable named "foo" you can type print foo to see its value.
This works in both the normal Command Prompt that comes with Windows and also the Git Bash shell that comes with Git. There are a couple more things that would be nice to have:
  • It would be nice to have a JDB command that prints out the current filename, method name, and line number. You get this info whenever you run next or step, but sometimes that output ends up really far up in my buffer and I would like a way to quickly see that information again.
  • It would be nice to do this inside some kind of an graphical interface or IDE. Has anyone gotten that working?
By the way, I think JDB is only for debugging Java code. If you want to debug JRuby code there are other tools for that. One that worked for me is the ruby-debug gem, even though people claim it is not maintained.