Home | History | Annotate | Download | only in docs
      1 <HTML>
      2 
      3 
      4 <head>
      5   <title>Dalvik VM Debug Monitor</title>
      6   <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      7   <link href="http://www.google.com/favicon.ico" type="image/x-icon"
      8  rel="shortcut icon">
      9   <link href="../android.css" type="text/css" rel="stylesheet">
     10   <script language="JavaScript1.2" type="text/javascript">
     11 function highlight(name) {
     12   if (document.getElementById) {
     13     tags              = [ 'span', 'div', 'tr', 'td' ];
     14     for (i in tags) {
     15       elements        = document.getElementsByTagName(tags[i]);
     16       if (elements) {
     17         for (j = 0; j < elements.length; j++) {
     18           elementName = elements[j].getAttribute("id");
     19           if (elementName == name) {
     20             elements[j].style.backgroundColor = "#C0F0C0";
     21           } else if (elementName && elementName.indexOf("rev") == 0) {
     22             elements[j].style.backgroundColor = "#FFFFFF";
     23           }
     24         }
     25       }
     26     }
     27   }
     28 }
     29   </script>
     30 </head>
     31 <body onload="prettyPrint()">
     32 
     33 <h1><a name="My_Project_"></a>Dalvik VM<br>Debug Monitor</h1>
     34 
     35 <!-- Status is one of: Draft, Current, Needs Update, Obsolete -->
     36 <p style="text-align:center"><strong>Status:</strong><em>Draft</em> &nbsp;
     37 <small>(as of March 6, 2007)</small></p>
     38 <address>
     39 [authors]
     40 </address>
     41 
     42 <!-- last modified date can be different to the "Status date." It automatically
     43 updates
     44 whenever the file is modified. -->
     45 <i>Modified:</i>
     46  <!-- this script automatically sets the modified date,you don't need to modify
     47 it -->
     48     <script type=text/javascript>
     49         <!--
     50         var lm = new Date(document.lastModified);
     51         document.write(lm.toDateString());
     52         //-->
     53         </script>
     54 </address>
     55 
     56 <p><br>
     57 <HR>
     58 
     59 <h2>Introduction</h2>
     60 
     61 <p>It's extremely useful to be able to monitor the live state of the
     62 VM.  For Android, we need to monitor multiple VMs running on a device
     63 connected through USB or a wireless network connection.  This document
     64 describes a debug monitor server that interacts with multiple VMs, and
     65 an API that VMs and applications can use to provide information
     66 to the monitor.
     67 
     68 <p>Some things we can monitor with the Dalvik Debug Monitor ("DDM"):
     69 <ul>
     70     <li> Thread states.  Track thread creation/exit, busy/idle status.
     71     <li> Overall heap status, useful for a heap bitmap display or
     72     fragmentation analysis.
     73 </ul>
     74 
     75 <p>It is possible for something other than a VM to act as a DDM client, but
     76 that is a secondary goal.  Examples include "logcat" log extraction
     77 and system monitors for virtual memory usage and load average.
     78 
     79 <p>It's also possible for the DDM server to be run on the device, with
     80 the information presented through the device UI.  However, the initial goal
     81 is to provide a display tool that takes advantage of desktop tools and
     82 screen real estate.
     83 
     84 <p>This work is necessary because we are unable to use standard JVMTI-based
     85 tools with Dalvik.  JVMTI relies on bytecode insertion, which is not
     86 currently possible because Dalvik doesn't support Java bytecode.
     87 
     88 <p>The DDM server is written in the Java programming language
     89 for portability.  It uses a desktop
     90 UI toolkit (SWT) for its interface.
     91 
     92 
     93 <h2>Protocol</h2>
     94 
     95 <p>To take advantage of existing infrastructure we are piggy-backing the
     96 DDM protocol on top of JDWP (the Java Debug Wire Protocol, normally spoken
     97 between a VM and a debugger).  To a
     98 non-DDM client, the DDM server just looks like a debugger.
     99 
    100 <p>The JDWP protocol is very close to what we want to use.  In particular:
    101 <ul>
    102     <li>It explicitly allows for vendor-defined packets, so there is no
    103     need to "bend" the JDWP spec.
    104     <li>Events may be posted from the VM at arbitrary points.  Such
    105     events do not elicit a response from the debugger, meaning the client
    106     can post data and immediately resume work without worrying about the
    107     eventual response.
    108     <li>The basic protocol is stateless and asynchronous.  Request packets
    109     from the debugger side include a serial number, which the VM includes
    110     in the response packet.  This allows multiple simultaneous
    111     conversations, which means the DDM traffic can be interleaved with
    112     debugger traffic.
    113 </ul>
    114 
    115 <p>There are a few issues with using JDWP for our purposes:
    116 <ul>
    117     <li>The VM only expects one connection from a debugger, so you couldn't
    118     attach the monitor and a debugger at the same time.  This will be
    119     worked around by connecting the debugger to the monitor and passing the
    120     traffic through.  (We're already doing the pass-through with "jdwpspy";
    121     requires some management of our request IDs though.)  This should
    122     be more convenient than the current "guess the port
    123     number" system when we're attached to a device.
    124     <li>The VM behaves differently when a debugger is attached.  It will
    125     run more slowly, and any objects passed to the monitor or debugger are
    126     immune to GC.  We can work around this by not enabling the slow path
    127     until non-DDM traffic is observed.  We also want to have a "debugger
    128     has connected/disconnected" message that allows the VM to release
    129     debugger-related resources without dropping the net connection.
    130     <li>Non-DDM VMs should not freak out when DDM connects.  There are
    131     no guarantees here for 3rd-party VMs (e.g. a certain mainstream VM,
    132     which crashes instantly), but our older JamVM can be
    133     configured to reject the "hello" packet.
    134 </ul>
    135 
    136 
    137 <h3>Connection Establishment</h3>
    138 
    139 <p>There are two basic approaches: have the server contact the VMs, and
    140 have the VMs contact the server.  The former is less "precise" than the
    141 latter, because you have to scan for the clients, but it has some
    142 advantages.
    143 
    144 <p>There are three interesting scenarios:
    145 <ol>
    146     <li>The DDM server is started, then the USB-attached device is booted
    147     or the simulator is launched.
    148     <li>The device or simulator is already running when the DDM server
    149     is started.
    150     <li>The DDM server is running when an already-started device is
    151     attached to USB.
    152 </ol>
    153 <p>If we have the VMs connect to the DDM server on startup, we only handle
    154 case #1.  If the DDM server scans for VMs when it starts, we only handle
    155 case #2.  Neither handles case #3, which is probably the most important
    156 of the bunch as the device matures.
    157 <p>The plan is to have a drop-down menu with two entries,
    158 "scan workstation" and "scan device".
    159 The former causes the DDM server to search for VMs on "localhost", the
    160 latter causes it to search for VMs on the other side of an ADB connection.
    161 The DDM server will scan for VMs every few seconds, either checking a
    162 range of known VM ports (e.g. 8000-8040) or interacting with some sort
    163 of process database on the device.  Changing modes causes all existing
    164 connections to be dropped.
    165 <p>When the DDM server first starts, it will try to execute "adb usb"
    166 to ensure that the ADB server is running.  (Note it will be necessary
    167 to launch the DDM server from a shell with "adb" in the path.)  If this
    168 fails, talking to the device will still be possible so long as the ADB
    169 daemon is already running.
    170 
    171 <h4>Connecting a Debugger</h4>
    172 
    173 <p>With the DDM server sitting on the JDWP port of all VMs, it will be
    174 necessary to connect the debugger through the DDM server.  Each VM being
    175 debugged will have a separate port being listened to by the DDM server,
    176 allowing you to connect a debugger to one or more VMs simultaneously.
    177 
    178 <p>In the common case, however, the developer will only want to debug
    179 a single VM.  One port (say 8700) will be listened to by the DDM server,
    180 and anything connecting to it will be connected to the "current VM"
    181 (selected in the UI).  This should allow developers to focus on a
    182 single application, which may otherwise shift around in the ordering, without
    183 having to adjust their IDE settings to a different port every time they
    184 restart the device.
    185 
    186 
    187 <h3>Packet Format</h3>
    188 
    189 <p>Information is sent in chunks.  Each chunk starts with:
    190 <pre>
    191 u4   type
    192 u4   length
    193 </pre>
    194 and contains a variable amount of type-specific data.
    195 Unrecognized types cause an empty response from the client and
    196 are quietly ignored by the server.  [Should probably return an error;
    197 need an "error" chunk type and a handler on the server side.]
    198 
    199 <p>The same chunk type may have different meanings when sent in different
    200 directions.  For example, the same type may be used for both a query and
    201 a response to the query.  For sanity the type must always be used in
    202 related transactions.
    203 
    204 <p>This is somewhat redundant with the JDWP framing, which includes a
    205 4-byte length and a two-byte type code ("command set" and "command"; a
    206 range of command set values is designated for "vendor-defined commands
    207 and extensions").  Using the chunk format allows us to remain independent
    208 of the underlying transport, avoids intrusive integration
    209 with JDWP client code, and provides a way to send multiple chunks in a
    210 single transmission unit.  [I'm taking the multi-chunk packets into
    211 account in the design, but do not plan to implement them unless the need
    212 arises.]
    213 
    214 <p>Because we may be sending data over a slow USB link, the chunks may be
    215 compressed.  Compressed chunks are written as a chunk type that
    216 indicates the compression, followed by the compressed length, followed
    217 by the original chunk type and the uncompressed length.  For zlib's deflate
    218 algorithm, the chunk type is "ZLIB".
    219 
    220 <p>Following the JDWP model, packets sent from the server to the client
    221 are always acknowledged, but packets sent from client to server never are.
    222 The JDWP error code field is always set to "no error"; failure responses
    223 from specific requests must be encoded into the DDM messages.
    224 
    225 <p>In what follows "u4" is an unsigned 32-bit value and "u1" is an
    226 unsigned 8-bit value.  Values are written in big-endian order to match
    227 JDWP.
    228 
    229 
    230 <h3>Initial Handshake</h3>
    231 
    232 <p>After the JDWP handshake, the server sends a HELO chunk to the client.
    233 If the client's JDWP layer rejects it, the server assumes that the client
    234 is not a DDM-aware VM, and does not send it any further DDM queries.
    235 <p>On the client side, upon seeing a HELO it can know that a DDM server
    236 is attached and prepare accordingly.  The VM should not assume that a
    237 debugger is attached until a non-DDM packet arrives.
    238 
    239 <h4>Chunk HELO (server --&gt; client)</h4>
    240 <p>Basic "hello" message.
    241 <pre>
    242 u4   DDM server protocol version
    243 </pre>
    244 
    245 
    246 <h4>Chunk HELO (client --&gt; server, reply only)</h4>
    247 Information about the client.  Must be sent in response to the HELO message.
    248 <pre>
    249 u4   DDM client protocol version
    250 u4   pid
    251 u4   VM ident string len (in 16-bit units)
    252 u4   application name len (in 16-bit units)
    253 var  VM ident string (UTF-16)
    254 var  application name (UTF-16)
    255 </pre>
    256 
    257 <p>If the client does not wish to speak to the DDM server, it should respond
    258 with a JDWP error packet.  This is the same behavior you'd get from a VM
    259 that doesn't support DDM.
    260 
    261 
    262 <h3>Debugger Management</h3>
    263 <p>VMs usually prepare for debugging when a JDWP connection is established,
    264 and release debugger-related resources when the connection drops.  We want
    265 to open the JDWP connection early and hold it open after the debugger
    266 disconnects.
    267 <p>The VM can tell when a debugger attaches, because it will start seeing
    268 non-DDM JDWP traffic, but it can't identify the disconnect.  For this reason,
    269 we need to send a packet to the client when the debugger disconnects.
    270 <p>If the DDM server is talking to a non-DDM-aware client, it will be
    271 necessary to drop and re-establish the connection when the debugger goes away.
    272 (This also works with DDM-aware clients; this packet is an optimization.)
    273 
    274 <h4>Chunk DBGD (server --&gt; client)</h4>
    275 <p>Debugger has disconnected.  The client responds with a DBGD to acknowledge
    276 receipt.  No data in request, no response required.
    277 
    278 
    279 <h3>VM Info</h3>
    280 <p>Update the server's info about the client.
    281 
    282 <h4>Chunk APNM (client --&gt; server)</h4>
    283 
    284 <p>If a VM's application name changes -- possible in our environment because
    285 of the "pre-initialized" app processes -- it must send up one of these.
    286 <pre>
    287 u4   application name len (in 16-bit chars)
    288 var  application name (UTF-16)
    289 </pre>
    290 
    291 <h4>Chunk WAIT (client --&gt; server)</h4>
    292 
    293 <p>This tells DDMS that one or more threads are waiting on an external
    294 event.  The simplest use is to tell DDMS that the VM is waiting for a
    295 debugger to attach.
    296 <pre>
    297 u1   reason  (0 = wait for debugger)
    298 </pre>
    299 If DDMS is attached, the client VM sends this up when waitForDebugger()
    300 is called.  If waitForDebugger() is called before DDMS attaches, the WAIT
    301 chunk will be sent up at about the same time as the HELO response.
    302 
    303 
    304 <h3>Thread Status</h3>
    305 
    306 <p>The client can send updates when their status changes, or periodically
    307 send thread state info, e.g. 2x per
    308 second to allow a "blinkenlights" display of thread activity.
    309 
    310 <h4>Chunk THEN (server --&gt; client)</h4>
    311 
    312 <p>Enable thread creation/death notification.
    313 <pre>
    314 u1   boolean (true=enable, false=disable)
    315 </pre>
    316 <p>The response is empty.  The client generates THCR packets for all
    317 known threads.  (Note the THCR packets may arrive before the THEN
    318 response.)
    319 
    320 <h4>Chunk THCR (client --&gt; server)</h4>
    321 <p>Thread Creation notification.
    322 <pre>
    323 u4   VM-local thread ID (usually a small int)
    324 u4   thread name len (in 16-bit chars)
    325 var  thread name (UTF-16)
    326 </pre>
    327 
    328 <h4>Chunk THDE (client --&gt; server)</h4>
    329 <p>Thread Death notification.
    330 <pre>
    331 u4   VM-local thread ID
    332 </pre>
    333 
    334 <h4>Chunk THST (server --&gt; client)</h4>
    335 
    336 <p>Enable periodic thread activity updates.
    337 Threads in THCR messages are assumed to be in the "initializing" state.  A
    338 THST message should follow closely on the heels of THCR.
    339 <pre>
    340 u4   interval, in msec
    341 </pre>
    342 <p>An interval of 0 disables the updates.  This is done periodically,
    343 rather than every time the thread state changes, to reduce the amount
    344 of data that must be sent for an actively running VM.
    345 
    346 <h4>Chunk THST (client --&gt; server)</h4>
    347 <p>Thread Status, describing the state of one or more threads.  This is
    348 most useful when creation/death notifications are enabled first.  The
    349 overall layout is:
    350 <pre>
    351 u4   count
    352 var  thread data
    353 </pre>
    354 Then, for every thread:
    355 <pre>
    356 u4   VM-local thread ID
    357 u1   thread state
    358 u1   suspended
    359 </pre>
    360 <p>"thread state" must be one of:
    361 <ul>    <!-- don't use ol, we may need (-1) or sparse -->
    362     <li> 1 - running (now executing or ready to do so)
    363     <li> 2 - sleeping (in Thread.sleep())
    364     <li> 3 - monitor (blocked on a monitor lock)
    365     <li> 4 - waiting (in Object.wait())
    366     <li> 5 - initializing
    367     <li> 6 - starting
    368     <li> 7 - native (executing native code)
    369     <li> 8 - vmwait (waiting on a VM resource)
    370 </ul>
    371 <p>"suspended" will be 0 if the thread is running, 1 if not.
    372 <p>[Any reason not to make "suspended" be the high bit of "thread state"?
    373 Do we need to differentiate suspend-by-GC from suspend-by-debugger?]
    374 <p>[We might be able to send the currently-executing method.  This is a
    375 little risky in a running VM, and increases the size of the messages
    376 considerably, but might be handy.]
    377 
    378 
    379 <h3>Heap Status</h3>
    380 
    381 <p>The client sends what amounts to a color-coded bitmap to the server,
    382 indicating which stretches of memory are free and which are in use.  For
    383 compactness the bitmap is run-length encoded, and based on multi-byte
    384 "allocation units" rather than byte counts.
    385 
    386 <p>In the future the server will be able to correlate the bitmap with more
    387 detailed object data, so enough information is provided to associate the
    388 bitmap data with virtual addresses.
    389 
    390 <p>Heaps may be broken into segments within the VM, and due to memory
    391 constraints it may be desirable to send the bitmap in smaller pieces,
    392 so the protocol allows the heap data to be sent in several chunks.
    393 To avoid ambiguity, the client is required
    394 to send explicit "start" and "end" messages during an update.
    395 
    396 <p>All messages include a "heap ID" that can be used to differentiate
    397 between multiple independent virtual heaps or perhaps a native heap.  The
    398 client is allowed to send information about different heaps simultaneously,
    399 so all heap-specific information is tagged with a "heap ID".
    400 
    401 <h4>Chunk HPIF (server --&gt; client)</h4>
    402 <p>Request heap info.
    403 <pre>
    404 u1   when to send
    405 </pre>
    406 <p>The "when" values are:
    407 <pre>
    408 0: never
    409 1: immediately
    410 2: at the next GC
    411 3: at every GC
    412 </pre>
    413 
    414 <h4>Chunk HPIF (client --&gt; server, reply only)</h4>
    415 <p>Heap Info.  General information about the heap, suitable for a summary
    416 display.
    417 <pre>
    418 u4   number of heaps
    419 </pre>
    420 For each heap:
    421 <pre>
    422 u4   heap ID
    423 u8   timestamp in ms since Unix epoch
    424 u1   capture reason (same as 'when' value from server)
    425 u4   max heap size in bytes (-Xmx)
    426 u4   current heap size in bytes
    427 u4   current number of bytes allocated
    428 u4   current number of objects allocated
    429 </pre>
    430 <p>[We can get some of this from HPSG, more from HPSO.]
    431 <p>[Do we need a "heap overhead" stat here, indicating how much goes to
    432 waste?  e.g. (8 bytes per object * number of objects)]
    433 
    434 <h4>Chunk HPSG (server --&gt; client)</h4>
    435 <p>Request transmission of heap segment data.
    436 <pre>
    437 u1   when to send
    438 u1   what to send
    439 </pre>
    440 <p>The "when" to send will be zero to disable transmission, 1 to send
    441 during a GC.  Other values are currently undefined.  (Could use to pick
    442 which part of the GC to send it, or cause periodic transmissions.)
    443 <p>The "what" field is currently 0 for HPSG and 1 for HPSO.
    444 <p>No reply is expected.
    445 
    446 <h4>Chunk NHSG (server --&gt; client)</h4>
    447 <p>Request transmission of native heap segment data.
    448 <pre>
    449 u1   when to send
    450 u1   what to send
    451 </pre>
    452 <p>The "when" to send will be zero to disable transmission, 1 to send
    453 during a GC.  Other values are currently undefined.
    454 <p>The "what" field is currently ignored.
    455 <p>No reply is expected.
    456 
    457 <h4>Chunk HPST/NHST (client --&gt; server)</h4>
    458 <p>This is a Heap Start message.  It tells the server to discard any
    459 existing notion of what the client's heap looks like, and prepare for
    460 new information.  HPST indicates a virtual heap dump and must be followed
    461 by zero or more HPSG/HPSO messages and an HPEN.  NHST indicates a native
    462 heap dump and must be followed by zero or more NHSG messages and an NHEN.
    463 
    464 <p>The only data item is:
    465 <pre>
    466 u4   heap ID
    467 </pre>
    468 
    469 <h4>Chunk HPEN/NHEN (client --&gt; server)</h4>
    470 <p>Heap End, indicating that all information about the heap has been sent.
    471 A HPST will be paired with an HPEN and an NHST will be paired with an NHEN.
    472 
    473 <p>The only data item is:
    474 <pre>
    475 u4   heap ID
    476 </pre>
    477 
    478 <h4>Chunk HPSG (client --&gt; server)</h4>
    479 <p>Heap segment data.  Each chunk describes all or part of a contiguous
    480 stretch of heap memory.
    481 <pre>
    482 u4   heap ID
    483 u1   size of allocation unit, in bytes (e.g. 8 bytes)
    484 u4   virtual address of segment start
    485 u4   offset of this piece (relative to the virtual address)
    486 u4   length of piece, in allocation units
    487 var  usage data
    488 </pre>
    489 <p>The "usage data" indicates the status of each allocation unit.  The data
    490 is a stream of pairs of bytes, where the first byte indicates the state
    491 of the allocation unit, and the second byte indicates the number of
    492 consecutive allocation units with the same state.
    493 <p>The bits in the "state" byte have the following meaning:
    494 <pre>
    495 +---------------------------------------+
    496 |  7 |  6 |  5 |  4 |  3 |  2 |  1 |  0 |
    497 +---------------------------------------+
    498 |  P | U0 | K2 | K1 | K0 | S2 | S1 | S0 |
    499 +---------------------------------------+
    500 </pre>
    501 <ul>
    502     <li>'S': solidity
    503     <ul>
    504         <li>0=free
    505         <li>1=has hard reference
    506         <li>2=has soft reference
    507         <li>3=has weak reference
    508         <li>4=has phantom reference
    509         <li>5=pending finalization
    510         <li>6=marked, about to be swept
    511     </ul>
    512     <li>'K': kind
    513     <ul>
    514         <li>0=object
    515         <li>1=class object
    516         <li>2=array of byte/boolean
    517         <li>3=array of char/short
    518         <li>4=array of Object/int/float
    519         <li>5=array of long/double
    520     </ul>
    521     <li>'P': partial flag (not used for HPSG)
    522     <li>'U': unused, must be zero
    523 </ul>
    524 
    525 <p>The use of the various 'S' types depends on when the information is
    526 sent.  The current plan is to send it either immediately after a GC,
    527 or between the "mark" and "sweep" phases of the GC.  For a fancy generational
    528 collector, we may just want to send it up periodically.
    529 
    530 <p>The run-length byte indicates the number of allocation units minus one, so a
    531 length of 255 means there are 256 consecutive units with this state.  In
    532 some cases, e.g. arrays of bytes, the actual size of the data is rounded
    533 up the nearest allocation unit.
    534 <p>For HPSG, the runs do not end at object boundaries.  It is not possible
    535 to tell from this bitmap whether a run contains one or several objects.
    536 (But see HPSO, below.)
    537 <p>[If we find that we have many long runs, we can overload the 'P' flag
    538 or dedicate the 'U' flag to indicate that we have a 16-bit length instead
    539 of 8-bit.  We can also use a variable-width integer scheme for the length,
    540 encoding 1-128 in one byte, 1-16384 in two bytes, etc.]
    541 <p>[Alternate plan for 'K': array of byte, array of char, array of Object,
    542 array of miscellaneous primitive type]
    543 <p>To parse the data, the server runs through the usage data until either
    544 (a) the end of the chunk is reached, or (b) all allocation units have been
    545 accounted for.  (If these two things don't happen at the same time, the
    546 chunk is rejected.)
    547 <p>Example: suppose a VM has a heap at 0x10000 that is 0x2000 bytes long
    548 (with an 8-byte allocation unit size, that's 0x0400 units long).
    549 The client could send one chunk (allocSize=8, virtAddr=0x10000, offset=0,
    550 length=0x0400) or two (allocSize=8, virtAddr=0x10000, offset=0, length=0x300;
    551 then allocSize=8, virtAddr=0x10000, offset=0x300, length=0x100).
    552 <p>The client must encode the entire heap, including all free space at
    553 the end, or the server will not have an accurate impression of the amount
    554 of memory in the heap.  This refers to the current heap size, not the
    555 maximum heap size.
    556 
    557 <h4>Chunk HPSO (client --&gt; server)</h4>
    558 <p>This is essentially identical to HPSG, but the runs are terminated at
    559 object boundaries.  If an object is larger than 256 allocation units, the
    560 "partial" flag is set in all runs except the last.
    561 <p>The resulting unpacked bitmap is identical, but the object boundary
    562 information can be used to gain insights into heap layout.
    563 <p>[Do we want to have a separate message for this?  Maybe just include
    564 a "variant" flag in the HPST packet.  Another possible form of output
    565 would be one that indicates the age, in generations, of each block of
    566 memory.  That would provide a quick visual indication of "permanent vs.
    567 transient residents", perhaps with a 16-level grey scale.]
    568 
    569 <h4>Chunk NHSG (client --&gt; server)</h4>
    570 <p>Native heap segment data.  Each chunk describes all or part of a
    571 contiguous stretch of native heap memory.  The format is the same as
    572 for HPSG, except that only solidity values 0 (= free) and 1 (= hard
    573 reference) are used, and the kind value is always 0 for free chunks
    574 and 7 for allocated chunks, indicating a non-VM object.
    575 <pre>
    576 u4   heap ID
    577 u1   size of allocation unit, in bytes (e.g. 8 bytes)
    578 u4   virtual address of segment start
    579 u4   offset of this piece (relative to the virtual address)
    580 u4   length of piece, in allocation units
    581 var  usage data
    582 </pre>
    583 
    584 <h3>Generic Replies</h3>
    585 
    586 The client-side chunk handlers need a common way to report simple success
    587 or failure.  By convention, an empty reply packet indicates success.
    588 
    589 <h4>Chunk FAIL (client --&gt; server, reply only)</h4>
    590 <p>The chunk includes a machine-readable error code and a
    591 human-readable error message.  Server code can associate the failure
    592 with the original request by comparing the JDWP packet ID.
    593 <p>This allows a standard way of, for example, rejecting badly-formed
    594 request packets.
    595 <pre>
    596 u4   error code
    597 u4   error message len (in 16-bit chars)
    598 var  error message (UTF-16)
    599 </pre>
    600 
    601 <h3>Miscellaneous</h3>
    602 
    603 <h4>Chunk EXIT (server --&gt; client)</h4>
    604 <p>Cause the client to exit with the specified status, using System.exit().
    605 Useful for certain kinds of testing.
    606 <pre>
    607 u4   exit status
    608 </pre>
    609 
    610 <h4>Chunk DTRC (server --&gt; client)</h4>
    611 <p>[TBD] start/stop dmtrace; can send the results back over the wire.  For
    612 size reasons we probably need "sending", "data", "key", "finished" as
    613 4 separate chunks/packets rather than one glob.
    614 
    615 
    616 <h2>Client API</h2>
    617 
    618 <p>The API is written in the Java programming language
    619 for convenience.  The code is free to call native methods if appropriate.
    620 
    621 <h3>Chunk Handler API</h3>
    622 
    623 <p>The basic idea is that arbitrary code can register handlers for
    624 specific chunk types.  When a DDM chunk with that type arrives, the
    625 appropriate handler is invoked.  The handler's return value provides the
    626 response to the server.
    627 
    628 <p>There are two packages.  android.ddm lives in the "framework" library,
    629 and has all of the chunk handlers and registration code.  It can freely
    630 use Android classes.  org.apache.harmony.dalvik.ddmc lives in the "core"
    631 library, and has
    632 some base classes and features that interact with the VM.  Nothing should
    633 need to modify the org.apache.harmony.dalvik.ddmc classes.
    634 
    635 <p>The DDM classes pass chunks of data around with a simple class:
    636 
    637 <pre class=prettyprint>
    638 class Chunk {
    639     int type;
    640     byte[] data;
    641     int offset, length;
    642 };
    643 </pre>
    644 
    645 <p>The chunk handlers accept and return them:
    646 <pre class=prettyprint>
    647 public Chunk handleChunk(Chunk request)
    648 </pre>
    649 <p>The code is free to parse the chunk and generate a response in any
    650 way it chooses.  Big-endian byte ordering is recommended but not mandatory.
    651 <p>Chunk handlers will be notified when a DDM server connects or disconnects,
    652 so that they can perform setup and cleanup operations:
    653 <pre class=prettyprint>
    654 public void connected()
    655 public void disconnected()
    656 </pre>
    657 
    658 <p>The method processes the request, formulates a response, and returns it.
    659 If the method returns null, an empty JDWP success message will be returned.
    660 <p>The request/response interaction is essentially asynchronous in the
    661 protocol.  The packets are linked together with the JDWP message ID.
    662 <p>[We could use ByteBuffer here instead of byte[], but it doesn't gain
    663 us much.  Wrapping a ByteBuffer around an array is easy.  We don't want
    664 to pass the full packet in because we could have multiple chunks in one
    665 request packet.  The DDM code needs to collect and aggregate the responses
    666 to all chunks into a single JDWP response packet.  Parties wanting to
    667 write multiple chunks in response to a single chunk should send a null
    668 response back and use "sendChunk()" to send the data independently.]
    669 
    670 <h3>Unsolicited event API</h3>
    671 
    672 <p>If a piece of code wants to send a chunk of data to the server at some
    673 arbitrary time, it may do so with a method provided by
    674 org.apache.harmony.dalvik.DdmServer:
    675 
    676 <pre class=prettyprint>
    677 public static void sendChunk(Chunk chunk)
    678 </pre>
    679 
    680 <p>There is no response or status code.  No exceptions are thrown.
    681 
    682 
    683 <h2>Server API</h2>
    684 
    685 <p>This is similar to the client side in many ways, but makes extensive
    686 use of ByteBuffer in a perhaps misguided attempt to use java.nio.channels
    687 and avoid excessive thread creation and unnecessary data copying.
    688 
    689 <p>Upon receipt of a packet, the server will identify it as one of:
    690 <ol>
    691     <li>Message to be passed through to the debugger
    692     <li>Response to an earlier request
    693     <li>Unsolicited event packet
    694 </ol>
    695 <p>To handle (2), when messages are sent from the server to the client,
    696 the message must be paired with a callback method.  The response might be
    697 delayed for a while -- or might never arrive -- so the server can't block
    698 waiting for responses from the client.
    699 <p>The chunk handlers look like this:
    700 <pre class=prettyprint>
    701 public void handleChunk(Client client, int type,
    702     ByteBuffer data, boolean isReply, int msgId)
    703 </pre>
    704 <p>The arguments are:
    705 <dl>
    706     <dt>client
    707     <dd>An object representing the client VM that send us the packet.
    708     <dt>type
    709     <dd>The 32-bit chunk type.
    710     <dt>data
    711     <dd>The data.  The data's length can be determined by calling data.limit().
    712     <dt>isReply
    713     <dd>Set to "true" if this was a reply to a message we sent earlier,
    714     "false" if the client sent this unsolicited.
    715     <dt>msgId
    716     <dd>The JDWP message ID.  Useful for connecting replies with requests.
    717 </dl>
    718 <p>If a handler doesn't like the contents of a packet, it should log an
    719 error message and return.  If the handler doesn't recognize the packet at
    720 all, it can call the superclass' handleUnknownChunk() method.
    721 
    722 <p>As with the client, the server code can be notified when clients
    723 connect or disconnect.  This allows the handler to send initialization
    724 code immediately after a connect, or clean up after a disconnect.
    725 <p>Data associated with a client can be stored in a ClientData object,
    726 which acts as a general per-client dumping around for VM and UI state.
    727 
    728 
    729 <P><BR>
    730 
    731 <HR>
    732 
    733 <address>Copyright &copy; 2007 The Android Open Source Project</address>
    734 
    735 </body>
    736 </HTML>
    737