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><application></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 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 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 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 © 2009 The Android Open Source Project</address> 240 </p> 241 242 </body> 243 </html> 244