Home | History | Annotate | Download | only in docs
      1 <html>
      2 <head>
      3 <title>Dalvik Debugger Support</title>
      4 </head>
      5 
      6 <body>
      7 <h1>Dalvik Debugger Support</h1>
      8 
      9 <p>
     10 The Dalvik virtual machine supports source-level debugging with many popular
     11 development environments.  Any tool that allows remote debugging over JDWP
     12 (the
     13 <a href="http://java.sun.com/javase/6/docs/technotes/guides/jpda/jdwp-spec.html">
     14 Java Debug Wire Protocol</a>) is expected work.  Supported debuggers
     15 include jdb, Eclipse, IntelliJ, and JSwat.
     16 </p><p>
     17 The VM does not support tools based on JVMTI (Java Virtual
     18 Machine Tool Interface).  This is a relatively intrusive approach that
     19 relies on bytecode insertion, something the Dalvik VM does not currently
     20 support.
     21 </p><p>
     22 Dalvik's implementation of JDWP also includes hooks for supporting
     23 DDM (Dalvik Debug Monitor) features, notably as implemented by DDMS
     24 (Dalvik Debug Monitor Server) and the Eclipse ADT plugin.  The protocol
     25 and VM interaction is described in some detail
     26 <a href="debugmon.html">here</a>.
     27 </p><p>
     28 All of the debugger support in the VM lives in the <code>dalvik/vm/jdwp</code>
     29 directory, and is almost entirely isolated from the rest of the VM sources.
     30 <code>dalvik/vm/Debugger.c</code> bridges the gap.  The goal in doing so
     31 was to make it easier to re-use the JDWP code in other projects.
     32 </p><p>
     33 
     34 
     35 <h2>Implementation</h2>
     36 
     37 <p>
     38 Every VM that has debugging enabled starts a "JDWP" thread.  The thread
     39 typically sits idle until DDMS or a debugger connects.  The thread is
     40 only responsible for handling requests from the debugger; VM-initated
     41 communication, such as notifying the debugger when the VM has stopped at
     42 a breakpoint, are sent from the affected thread.
     43 </p><p>
     44 When the VM is started from the Android app framework, debugging is enabled
     45 for all applications when the system property <code>ro.debuggable</code>
     46 is set to </code>1</code> (use <code>adb shell getprop ro.debuggable</code>
     47 to check it).  If it's zero, debugging can be enabled via the application's
     48 manifest, which must include <code>android:debuggable="true"</code> in the
     49 <code>&lt;application&gt;</code> element.
     50 
     51 </p><p>
     52 The VM recognizes the difference between a connection from DDMS and a
     53 connection from a debugger (either directly or in concert with DDMS).
     54 A connection from DDMS alone doesn't result in a change in VM behavior,
     55 but when the VM sees debugger packets it allocates additional data
     56 structures and may switch to a different implementation of the interpreter.
     57 </p><p>
     58 Pre-Froyo implementations of the Dalvik VM used read-only memory mappings
     59 for all bytecode, which made it necessary to scan for breakpoints by
     60 comparing the program counter to a set of addresses.  In Froyo this was
     61 changed to allow insertion of breakpoint opcodes.  This allows the VM
     62 to execute code more quickly, and does away with the hardcoded limit
     63 of 20 breakpoints.  Even with this change, however, the debug-enabled
     64 interpreter is much slower than the regular interpreter (perhaps 5x).
     65 </p><p>
     66 The JDWP protocol is stateless, so the VM handles individual debugger
     67 requests as they arrive, and posts events to the debugger as they happen.
     68 </p><p>
     69 
     70 
     71 <h2>Debug Data</h2>
     72 <p> Source code debug data, which includes mappings of source code to
     73 bytecode and lists describing which registers are used to hold method
     74 arguments and local variables, are optionally emitted by the Java compiler.
     75 When <code>dx</code> converts Java bytecode to Dalvik bytecode, it must
     76 also convert this debug data.
     77 </p><p>
     78 <code>dx</code> must also ensure that it doesn't perform operations
     79 that confuse the debugger.  For example, re-using registers that hold
     80 method arguments and the "<code>this</code>" pointer is allowed in
     81 Dalvik bytecode if the values are never used or no longer needed.
     82 This can be very confusing for the debugger (and the programmer)
     83 since the values have method scope and aren't expected to disappear.  For
     84 this reason, <code>dx</code> generates sub-optimal code in some situations
     85 when debugging support is enabled.
     86 </p><p>
     87 Some of the debug data is used for other purposes; in particular, having
     88 filename and line number data is necessary for generating useful exception
     89 stack traces.  This data can be omitted by <code>dx</code> to make the DEX
     90 file smaller.
     91 </p><p>
     92 
     93 
     94 <h2>Usage</h2>
     95 
     96 <p>
     97 The Dalvik VM supports many of the same command-line flags that other popular
     98 desktop VMs do.  To start a VM with debugging enabled, you add a command-line
     99 flag with some basic options.  The basic incantation looks something
    100 like this:
    101 
    102 <pre>-Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=y</pre>
    103 or
    104 <pre>-agentlib:jdwp=transport=dt_socket,address=8000,server=y,suspend=y</pre>
    105 
    106 </p><p>
    107 After the initial prefix, options are provided as name=value pairs.  The
    108 options currently supported by the Dalvik VM are:
    109 <dl>
    110     <dt>transport (no default)</dt>
    111     <dd>Communication transport mechanism to use.  Dalvik supports
    112     TCP/IP sockets (<code>dt_socket</code>) and connection over USB
    113     through ADB (<code>dt_android_adb</code>).
    114     </dd>
    115 
    116     <dt>server (default='n')</dt>
    117     <dd>Determines whether the VM acts as a client or a server.  When
    118     acting as a server, the VM waits for a debugger to connect to it.
    119     When acting as a client, the VM attempts to connect to a waiting
    120     debugger.
    121     </dd>
    122 
    123     <dt>suspend (default='n')</dt>
    124     <dd>If set to 'y', the VM will wait for a debugger connection
    125     before executing application code.  When the debugger connects (or
    126     when the VM finishes connecting to the debugger), the VM tells the
    127     debugger that it has suspended, and will not proceed until told
    128     to resume.  If set to 'n', the VM just plows ahead.
    129     </dd>
    130 
    131     <dt>address (default="")</dt>
    132     <dd>This must be <code>hostname:port</code> when <code>server=n</code>,
    133     but can be just <code>port</code> when <code>server=y</code>.  This
    134     specifies the IP address and port number to connect or listen to.
    135     <br>
    136     Listening on port 0 has a special meaning: try to
    137     listen on port 8000; if that fails, try 8001, 8002, and so on.  (This
    138     behavior is non-standard and may be removed from a future release.)
    139     <br>This option has no meaning for <code>transport=dt_android_adb</code>.
    140     </dd>
    141 
    142     <dt>help (no arguments)</dt>
    143     <dd>If this is the only option, a brief usage message is displayed.
    144     </dd>
    145 
    146     <dt>launch, onthrow, oncaught, timeout</dt>
    147     <dd>These options are accepted but ignored.
    148     </dd>
    149 </dl>
    150 
    151 </p><p>
    152 To debug a program on an Android device using DDMS over USB, you could
    153 use a command like this:
    154 <pre>% dalvikvm -agentlib:jdwp=transport=dt_android_adb,suspend=y,server=y -cp /data/foo.jar Foo</pre>
    155 
    156 This tells the Dalvik VM to run the program with debugging enabled, listening
    157 for a connection from DDMS, and waiting for a debugger.  The program will show
    158 up with an app name of "?" in the process list, because it wasn't started
    159 from the Android application framework.  From here you would connect your
    160 debugger to the appropriate DDMS listen port (e.g.
    161 <code>jdb -attach localhost:8700</code> after selecting it in the app list).
    162 
    163 </p><p>
    164 To debug a program on an Android device using TCP/IP bridged across ADB,
    165 you would first need to set up forwarding:
    166 <pre>% adb forward tcp:8000 tcp:8000
    167 % adb shell dalvikvm -agentlib:jdwp=transport=dt_socket,address=8000,suspend=y,server=y -cp /data/foo.jar Foo</pre>
    168 and then <code>jdb -attach localhost:8000</code>.
    169 </p><p>
    170 (In the above examples, the VM will be suspended when you attach.  In jdb,
    171 type <code>cont</code> to continue.)
    172 </p><p>
    173 The DDMS integration makes the <code>dt_android_adb</code> transport much
    174 more convenient when debugging on an Android device, but when working with
    175 Dalvik on the desktop it makes sense to use the TCP/IP transport.
    176 </p><p>
    177 
    178 
    179 <h2>Known Issues and Limitations</h2>
    180 
    181 </p><p>
    182 Most of the optional features JDWP allows are not implemented.  These
    183 include field access watchpoints and better tracking of monitors.
    184 </p><p>
    185 Not all JDWP requests are implemented.  In particular, anything that
    186 never gets emitted by the debuggers we've used is not supported and will
    187 result in error messages being logged.  Support will be added when a
    188 use case is uncovered.
    189 </p><p>
    190 &nbsp;
    191 </p><p>
    192 The debugger and garbage collector are somewhat loosely
    193 integrated at present.  The VM currently guarantees that any object the
    194 debugger is aware of will not be garbage collected until after the
    195 debugger disconnects.  This can result in a build-up over time while the
    196 debugger is connected.  For example, if the debugger sees a running
    197 thread, the associated Thread object will not be collected, even after
    198 the thread terminates.
    199 </p><p>
    200 The only way to "unlock" the references is to detach and reattach the
    201 debugger.
    202 </p><p>
    203 &nbsp;
    204 </p><p>
    205 The translation from Java bytecode to Dalvik bytecode may result in
    206 identical sequences of instructions being combined.  This can make it
    207 look like the wrong bit of code is being executed.  For example:
    208 <pre>    int test(int i) {
    209         if (i == 1) {
    210             return 0;
    211         }
    212         return 1;
    213     }</pre>
    214 The Dalvik bytecode uses a common <code>return</code> instruction for both
    215 <code>return</code> statements, so when <code>i</code> is 1 the debugger
    216 will single-step through <code>return 0</code> and then <code>return 1</code>.
    217 </p><p>
    218 &nbsp;
    219 </p><p>
    220 Dalvik handles synchronized methods differently from other VMs.
    221 Instead of marking a method as <code>synchronized</code> and expecting
    222 the VM to handle the locks, <code>dx</code> inserts a "lock"
    223 instruction at the top of the method and an "unlock" instruction in a
    224 synthetic <code>finally</code> block.  As a result, when single-stepping
    225 a <code>return</code> statement, the "current line" cursor may jump to
    226 the last line in the method.
    227 </p><p>
    228 This can also affect the way the debugger processes exceptions.  The
    229 debugger may decide to break on an
    230 exception based on whether that exception is "caught" or "uncaught".  To
    231 be considered uncaught, there must be no matching <code>catch</code> block
    232 or <code>finally</code> clause between the current point of execution and
    233 the top of the thread.  An exception thrown within or below a synchronized
    234 method will always be considered "caught", so the debugger won't stop
    235 until the exception is re-thrown from the synthetic <code>finally</code> block.
    236 </p><p>
    237 
    238 
    239 <address>Copyright &copy; 2009 The Android Open Source Project</address>
    240 </p>
    241 
    242 </body>
    243 </html>
    244