l Machine Tool Interface). This is a relatively intrusive approach that relies on bytecode insertion, something the Dalvik VM does not currently support.
Dalvik's implementation of JDWP also includes hooks for supporting DDM (Dalvik Debug Monitor) features, notably as implemented by DDMS (Dalvik Debug Monitor Server) and the Eclipse ADT plugin. The protocol and VM interaction is described in some detail here.
All of the debugger support in the VM lives in the dalvik/vm/jdwp directory, and is almost entirely isolated from the rest of the VM sources. dalvik/vm/Debugger.c bridges the gap. The goal in doing so was to make it easier to re-use the JDWP code in other projects.
Every VM that has debugging enabled starts a "JDWP" thread. The thread typically sits idle until DDMS or a debugger connects. The thread is only responsible for handling requests from the debugger; VM-initated communication, such as notifying the debugger when the VM has stopped at a breakpoint, are sent from the affected thread.
When the VM is started from the Android app framework, debugging is enabled for all applications when the system property ro.debuggable is set to 1 (use adb shell getprop ro.debuggable to check it). If it's zero, debugging can be enabled via the application's manifest, which must include android:debuggable="true" in the element.
The VM recognizes the difference between a connection from DDMS and a connection from a debugger (either directly or in concert with DDMS). A connection from DDMS alone doesn't result in a change in VM behavior, but when the VM sees debugger packets it allocates additional data structures and may switch to a different implementation of the interpreter.
Because Dalvik maps bytecode into memory read-only, some common techniques are difficult to implement without allocating additional memory. For example, suppose the debugger sets a breakpoint in a method. The quick way to handle this is to insert a breakpoint instruction directly into the code. When the instruction is reached, the breakpoint handler engages. Without this, it's necessary to perform an "is there a breakpoint here" scan. Even with some optimizations, the debug-enabled interpreter is much slower than the regular interpreter (perhaps 5x).
The JDWP protocol is stateless, so the VM handles individual debugger requests as they arrive, and posts events to the debugger as they happen.
Source code debug data, which includes mappings of source code to bytecode and lists describing which registers are used to hold method arguments and local variables, are optionally emitted by the Java compiler. When dx converts Java bytecode to Dalvik bytecode, it must also convert this debug data.
dx must also ensure that it doesn't perform operations that confuse the debugger. For example, re-using registers that hold method arguments and the "this" pointer is allowed in Dalvik bytecode if the values are never used or no longer needed. This can be very confusing for the debugger (and the programmer) since the values have method scope and aren't expected to disappear. For this reason, dx generates sub-optimal code in some situations when debugging support is enabled.
Some of the debug data is used for other purposes; in particular, having filename and line number data is necessary for generating useful exception stack traces. This data can be omitted by dx to make the DEX file smaller.
The Dalvik VM supports many of the same command-line flags that other popular desktop VMs do. To start a VM with debugging enabled, you add a command-line flag with some b