Thursday, October 29, 2009

Remote debugging of any JVM...

...is possible if you start that JVM with these arguments:

  • -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=1044

e.g. a Blackberry or a Grails/SmartGWT app.

Of course, it helps to have the source code available so you can hit breakpoints, etc.in your favourite IDE.

I wouldn't say that Eclipse is my favourite IDE, but try this:

  1. Create a new Java Project in Eclipse IDE e.g. name it: test_remote_debugging

  2. Create a new main class e.g. RunMe

e.g. something like:


public class RunMe {
public static void main(String[] args) {
System.out.println("RunMe has started...");
HelperClass helper = new HelperClass();
for (int i = 0; i < 10; i++) {
System.out.println("RunMe is tickling the Help...");
System.out.println("Help is in a state i.e. tickled = " + helper.property);
helper.property++;
}
}
}

and here's the helper class.:


public class HelperClass {
public int property = 0;
public HelperClass() {}
public void tickleMe() { property++; }
}

Eclipse auto-compiles this source as you save it so the java.class files are already under your Eclipse workspace's %project_name%/bin directory (assuming you accepted all the defaults when creating the Eclipse Java project); open a command prompt there and issue this command to run your main class such that it will start & wait for a debugger to attach to (the JPDA default) port 1044:

  • java -cp . -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=1044 RunMe

You can verify that the JVM is listening by:

  • watching the response to the command above, it should look like:

    • Listening for transport dt_socket at address: 1044

  • running from another command prompt the following:

    • netstat -a | findstr 1044

    • expect output like so:

      • TCP your_host:1044 your_host:0 LISTENING

  • running from another command prompt the following:

    • telnet localhost 1044

    • expect output like so:

      • Connecting To localhost...

      • screen goes blank

    • Press the Enter key a few times to escape the TCP conversation

      • The output at the JVM's stdout will look something like this:



        • Debugger failed to attach: handshake failed - received >


          < - excepted >JDWP-Handshake<


        • see here for more info. about the Java Debug Wire Protocol


  • connect Eclipse to the JVM by doing the following:

    • Select from Eclipse's Run menu the Debug configurations... option

    • Select from the left pane of the ensuing dialogue the 'Remote Java Application' configuration type

    • Click on the 'New launch configuration' icon at the top left of the left pane...

    • Give the config. a new name or leave the default

    • Select a different project if the default is NOT the one you want

    • Default Connection type of: Standard (Socket Attach) is the one you want

    • Host should be localhost for this example but could be any host (this is where it helps to have the remote host JVM's source code at hand)

    • Port should be what you used in the java.exe command line to start the remote JVM

    • Press Apply to save this config. and then press Debug if you want

      • It helps if you've set a breakpoint in the source viewed in Eclipse or debugging isn't going to do much for you at this point

        • hint: create a breakpoint in Eclipse by double-clicking in the left-gutter of a source code view


    • If you didn't jump straight into debugging in the last step, set a breakpoint or two in Eclipse now

    • To debug the remote JVM, select the named launch configuration from the Eclipse dropdown menu that appears to the right of the 'bug' icon, just under the Refavtor menu in Eclipse v3.4

      • you should now be in, or prompted to be in, Eclipse's Debug perspective with your first breakpoint highlighted in the source view

      • you'll know you've screwed up something in your launch config.if you get a dialogue box that says something like:



        • 'Launching RunMe' has encountered a problem. Failed to connect to remote VM. Connection refused.


For more info on JPDA see also:

No comments: