Skip to main content

Project of the day: YouDebug

Posted by kohsuke on November 8, 2009 at 7:30 AM PST

As a programmer, I spend a lot of time fixing bugs. And a considerable portion of that is the time spent on reproducing a problem. Here is how a typical such session goes. Your user reports that your program doesn't work and throws such and such exception. Or given the symptom he's describing, you suspect some "if" statements to be evaluating to false.

If you are lucky and experienced, you can sometimes fix the problem through careful reasoning, but often you need to collect more data to be able to fix the bug. Logging is one such measure, but I often find myself thinking "if only I could ask him to run the program with a debugger and report what the variable 'x' refers to!" After all, a debugger is an ultimate data collection tool. Unlike logging, your program doesn't need to be written a-priori to report data. Similarly, with an ability to inspect stack frames all the way down, evaluate arbitrary expressions, and modify the state of the target problem, a debugger is a far more powerful trouble-shooting tool. The one and the only problem with asking your user to run a debugger is that it's too difficult.

So to that end, I developed YouDebug.

YouDebug is a debugger but it's not a debugger. It's a debugger, because it builds on top of Java Platform Debug Architecture, and therefore is capable of doing everything your debugger can do — such as attaching to another process, breaking when certain conditions are met, inspect/manipulate variables, and so on.

But at the same time, it's not your typical debugger, because it's not interactive. You don't need source code either. Instead of using point-and-click and GUI, it comes with a DSL-like syntax sugar on top of Groovy that controls what YouDebug would do against the target program. Groovy was chosen so that Java programmers can comfortably write scripts, while still allowing me to do enough magic behind the scene.

Let's say you have the following program, which computes a String and then do substring.

public class SubStringTest {
    public static void main(String[] args) {
        String s = someLengthComputationOfString();
        System.out.println(s.substring(5));
    }

    private static String someLengthComputationOfString() {
        ...;
    }
}

One of your user is reporting that it's failing with the StringIndexOutOfRangeException:

Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: -1
        at java.lang.String.substring(String.java:1949)
        at java.lang.String.substring(String.java:1916)
        at SubStringTest.main(SubStringTest.java:7)

So you know s.substring(5) isn't working, but you want to know the value of the variable 's'.

To do this, let's set the breakpoint at line 7 and see what 's' is:

breakpoint("com.acme.SubStringTest",7) {
  println "s="+s;
}

Now, you send this script to the user and ask him to run the program as following:

$ java -agentlib:jdwp=transport=dt_socket,server=y,address=5005 SubStringTest
Listening for transport dt_socket at address: 5005

And then the user executes YouDebug on a separate terminal. YouDebug attaches to your program, and your script will eventually produce the value of 's':

$ java -jar youdebug.jar -socket 5005 SubStringMonitor.ydb
s=test

See the user guide about all the other things you can do with YouDebug and how you do it. The download is available from here(I posted a new version here that fixes several bugs), and the source code is hosted here.

Related Topics >>

Comments

Attach to live process

This would be really really wonderful if it would allow attaching to a live process. Something like the "btrace PID BTRACE_SCRIPT " of BTrace. Is it possible with JPDA?

There's the -pid option to

There's the -pid option to let you choose the target process by PID, but the debugger support in JVM cannot be activated on demand, so the target JVM still has to be started with a debug option. There's an RFE in BugParade that tracks this for several years, but no progress was made on it.

Understood. It is a pity ...

Understood. It is a pity ... this would be a fantastic tool to detect bugs in a production environment. Still a wonderful tool. Great work as in all your projects! Thanks in the name of the Java community.

Didn't you reinvent BTrace ?

This seems to be something I would expect from BTrace. They don't seem to have per line breakpoints, but perhaps a patch there would be see by more people compared to a separate project.

I think BTrace is an useful

I think BTrace is an useful tool but its sweet spot is different. For example, being on top of the debugger API allows us to do things that bytecode manipulation can't do, like pop stack frames for re-execution inspect the whole stack frames, not just the top one, or break at the exception, obtain monitor contention information, and so on.

I also think a scripting language is better suited for this kind of things than a compiled program.

Indeed, you might do some new

Indeed, you might do some new things, but I would have preferred it to be on top of BTrace. From the outside they rather look similar, I didn't know they are based on different principles altogether.

You can compile the BTrace script on the fly, so it's quite flexible in this regard.

Maybe what I would like is some unified tool for the both :-)

As always, you're the man!

I actually started writing something very similar a few months back: http://fisheye.codehaus.org/browse/gmod/debuggerbuilder/trunk/ Perhaps not coincidentally, I started DebuggerBuilder while fixing the Hudson remoting issues I submitted patches for around the same time I created it :)

This idea actually came from

This idea actually came from a conversation with my colleagues, but I certainly intend to use it with Hudson troubleshooting.

Didn't mean to imply that you

Didn't mean to imply that you got the idea from me or anything; I certainly didn't publish or publicize it in any meaningful way (or even really finish it to the point where it was worth doing so). I find it heartening that you guys came up with pretty much the same idea since it shows that I'm not just a crazy person to want such a tool to exist :)

Oh no, sorry for a confusion.

Oh no, sorry for a confusion. I thought you assumed this idea came while troubleshooting Hudson problems, and I was trying to say "no, it was different." I don't think you implied I copied your idea, and I didn't take it that way.

Debug from other server

Great idea to enable debugging via command line. How do we enable debugging from a different machine (host). I tried to insert the host name using the command "java -jar youdebug.jar -socket myhost:5005 SubStringMonitor.ydb" but it does not work. Thanks again.

Well, "-socket myhost:5005"

Well, "-socket myhost:5005" is supposed to do it. What do you get if you try that?