Turn free functions that take a JdwpState* into member functions.

Change-Id: Idf96803c12e160939dbc98be2df41c35a10987da
diff --git a/src/debugger.cc b/src/debugger.cc
index ef44816..f8b52bc 100644
--- a/src/debugger.cc
+++ b/src/debugger.cc
@@ -27,11 +27,7 @@
 static bool gJdwpConfigured = false;
 
 // Broken-down JDWP options. (Only valid if gJdwpConfigured is true.)
-static JDWP::JdwpTransportType gJdwpTransport;
-static bool gJdwpServer;
-static bool gJdwpSuspend;
-static std::string gJdwpHost;
-static int gJdwpPort;
+static JDWP::JdwpOptions gJdwpOptions;
 
 // Runtime JDWP state.
 static JDWP::JdwpState* gJdwpState = NULL;
@@ -58,27 +54,27 @@
 static bool ParseJdwpOption(const std::string& name, const std::string& value) {
   if (name == "transport") {
     if (value == "dt_socket") {
-      gJdwpTransport = JDWP::kJdwpTransportSocket;
+      gJdwpOptions.transport = JDWP::kJdwpTransportSocket;
     } else if (value == "dt_android_adb") {
-      gJdwpTransport = JDWP::kJdwpTransportAndroidAdb;
+      gJdwpOptions.transport = JDWP::kJdwpTransportAndroidAdb;
     } else {
       LOG(ERROR) << "JDWP transport not supported: " << value;
       return false;
     }
   } else if (name == "server") {
     if (value == "n") {
-      gJdwpServer = false;
+      gJdwpOptions.server = false;
     } else if (value == "y") {
-      gJdwpServer = true;
+      gJdwpOptions.server = true;
     } else {
       LOG(ERROR) << "JDWP option 'server' must be 'y' or 'n'";
       return false;
     }
   } else if (name == "suspend") {
     if (value == "n") {
-      gJdwpSuspend = false;
+      gJdwpOptions.suspend = false;
     } else if (value == "y") {
-      gJdwpSuspend = true;
+      gJdwpOptions.suspend = true;
     } else {
       LOG(ERROR) << "JDWP option 'suspend' must be 'y' or 'n'";
       return false;
@@ -86,10 +82,10 @@
   } else if (name == "address") {
     /* this is either <port> or <host>:<port> */
     std::string port_string;
-    gJdwpHost.clear();
+    gJdwpOptions.host.clear();
     std::string::size_type colon = value.find(':');
     if (colon != std::string::npos) {
-      gJdwpHost = value.substr(0, colon);
+      gJdwpOptions.host = value.substr(0, colon);
       port_string = value.substr(colon + 1);
     } else {
       port_string = value;
@@ -104,7 +100,7 @@
       LOG(ERROR) << "JDWP address has junk in port field: " << value;
       return false;
     }
-    gJdwpPort = port;
+    gJdwpOptions.port = port;
   } else if (name == "launch" || name == "onthrow" || name == "oncaught" || name == "timeout") {
     /* valid but unsupported */
     LOG(INFO) << "Ignoring JDWP option '" << name << "'='" << value << "'";
@@ -132,10 +128,10 @@
     ParseJdwpOption(pairs[i].substr(0, equals), pairs[i].substr(equals + 1));
   }
 
-  if (gJdwpTransport == JDWP::kJdwpTransportUnknown) {
+  if (gJdwpOptions.transport == JDWP::kJdwpTransportUnknown) {
     LOG(ERROR) << "Must specify JDWP transport: " << options;
   }
-  if (!gJdwpServer && (gJdwpHost.empty() || gJdwpPort == 0)) {
+  if (!gJdwpOptions.server && (gJdwpOptions.host.empty() || gJdwpOptions.port == 0)) {
     LOG(ERROR) << "Must specify JDWP host and port when server=n: " << options;
     return false;
   }
@@ -145,35 +141,31 @@
 }
 
 void Dbg::StartJdwp() {
+  if (!gJdwpAllowed || !gJdwpConfigured) {
+    // No JDWP for you!
+    return;
+  }
+
   // Init JDWP if the debugger is enabled. This may connect out to a
   // debugger, passively listen for a debugger, or block waiting for a
   // debugger.
-  if (gJdwpAllowed && gJdwpConfigured) {
-    JDWP::JdwpStartupParams params;
-    params.host = gJdwpHost;
-    params.transport = gJdwpTransport;
-    params.server = gJdwpServer;
-    params.suspend = gJdwpSuspend;
-    params.port = gJdwpPort;
-
-    gJdwpState = JDWP::JdwpStartup(&params);
-    if (gJdwpState == NULL) {
-      LOG(WARNING) << "debugger thread failed to initialize";
-    }
+  gJdwpState = JDWP::JdwpState::Create(&gJdwpOptions);
+  if (gJdwpState == NULL) {
+    LOG(WARNING) << "debugger thread failed to initialize";
   }
 
   // If a debugger has already attached, send the "welcome" message.
   // This may cause us to suspend all threads.
-  if (JDWP::JdwpIsActive(gJdwpState)) {
+  if (gJdwpState->IsActive()) {
     //ScopedThreadStateChange(Thread::Current(), Thread::kRunnable);
-    if (!JDWP::PostVMStart(gJdwpState, gJdwpSuspend)) {
+    if (!gJdwpState->PostVMStart()) {
       LOG(WARNING) << "failed to post 'start' message to debugger";
     }
   }
 }
 
 void Dbg::StopJdwp() {
-  JDWP::JdwpShutdown(gJdwpState);
+  delete gJdwpState;
 }
 
 void Dbg::SetJdwpAllowed(bool allowed) {
@@ -600,7 +592,7 @@
   if (gJdwpState == NULL) {
     LOG(VERBOSE) << "Debugger thread not active, ignoring DDM send: " << type;
   } else {
-    JDWP::DdmSendChunkV(gJdwpState, type, iov, iovcnt);
+    gJdwpState->DdmSendChunkV(type, iov, iovcnt);
   }
 }
 
diff --git a/src/jdwp/jdwp.h b/src/jdwp/jdwp.h
index 8455ba5..cd2bfa7 100644
--- a/src/jdwp/jdwp.h
+++ b/src/jdwp/jdwp.h
@@ -20,6 +20,7 @@
 #include "jdwp/jdwp_bits.h"
 #include "jdwp/jdwp_constants.h"
 #include "jdwp/jdwp_expand_buf.h"
+#include "../mutex.h" // TODO: fix our include path!
 
 #include <pthread.h>
 #include <stddef.h>
@@ -32,8 +33,6 @@
 
 namespace JDWP {
 
-struct JdwpState;       /* opaque */
-
 /*
  * Fundamental types.
  *
@@ -65,7 +64,6 @@
 static inline void expandBufAddRefTypeId(ExpandBuf* pReply, RefTypeId id) { expandBufAdd8BE(pReply, id); }
 static inline void expandBufAddFrameId(ExpandBuf* pReply, FrameId id) { expandBufAdd8BE(pReply, id); }
 
-
 /*
  * Holds a JDWP "location".
  */
@@ -86,10 +84,7 @@
 };
 std::ostream& operator<<(std::ostream& os, const JdwpTransportType& rhs);
 
-/*
- * Holds collection of JDWP initialization parameters.
- */
-struct JdwpStartupParams {
+struct JdwpOptions {
   JdwpTransportType transport;
   bool server;
   bool suspend;
@@ -97,121 +92,208 @@
   short port;
 };
 
-/*
- * Perform one-time initialization.
- *
- * Among other things, this binds to a port to listen for a connection from
- * the debugger.
- *
- * Returns a newly-allocated JdwpState struct on success, or NULL on failure.
- */
-JdwpState* JdwpStartup(const JdwpStartupParams* params);
+struct JdwpEvent;
+struct JdwpNetState;
+struct JdwpReqHeader;
+struct JdwpTransport;
 
 /*
- * Shut everything down.
+ * State for JDWP functions.
  */
-void JdwpShutdown(JdwpState* state);
+struct JdwpState {
+  /*
+   * Perform one-time initialization.
+   *
+   * Among other things, this binds to a port to listen for a connection from
+   * the debugger.
+   *
+   * Returns a newly-allocated JdwpState struct on success, or NULL on failure.
+   */
+  static JdwpState* Create(const JdwpOptions* options);
 
-/*
- * Returns "true" if a debugger or DDM is connected.
- */
-bool JdwpIsActive(JdwpState* state);
+  ~JdwpState();
 
-/*
- * Return the debugger thread's handle, or 0 if the debugger thread isn't
- * running.
- */
-pthread_t GetDebugThread(JdwpState* state);
+  /*
+   * Returns "true" if a debugger or DDM is connected.
+   */
+  bool IsActive();
 
-/*
- * Get time, in milliseconds, since the last debugger activity.
- */
-int64_t LastDebuggerActivity(JdwpState* state);
+  /*
+   * Return the debugger thread's handle, or 0 if the debugger thread isn't
+   * running.
+   */
+  pthread_t GetDebugThread();
 
-/*
- * When we hit a debugger event that requires suspension, it's important
- * that we wait for the thread to suspend itself before processing any
- * additional requests.  (Otherwise, if the debugger immediately sends a
- * "resume thread" command, the resume might arrive before the thread has
- * suspended itself.)
- *
- * The thread should call the "set" function before sending the event to
- * the debugger.  The main JDWP handler loop calls "get" before processing
- * an event, and will wait for thread suspension if it's set.  Once the
- * thread has suspended itself, the JDWP handler calls "clear" and
- * continues processing the current event.  This works in the suspend-all
- * case because the event thread doesn't suspend itself until everything
- * else has suspended.
- *
- * It's possible that multiple threads could encounter thread-suspending
- * events at the same time, so we grab a mutex in the "set" call, and
- * release it in the "clear" call.
- */
-//ObjectId GetWaitForEventThread(JdwpState* state);
-void SetWaitForEventThread(JdwpState* state, ObjectId threadId);
-void ClearWaitForEventThread(JdwpState* state);
+  /*
+   * Get time, in milliseconds, since the last debugger activity.
+   */
+  int64_t LastDebuggerActivity();
 
-/*
- * These notify the debug code that something interesting has happened.  This
- * could be a thread starting or ending, an exception, or an opportunity
- * for a breakpoint.  These calls do not mean that an event the debugger
- * is interested has happened, just that something has happened that the
- * debugger *might* be interested in.
- *
- * The item of interest may trigger multiple events, some or all of which
- * are grouped together in a single response.
- *
- * The event may cause the current thread or all threads (except the
- * JDWP support thread) to be suspended.
- */
+  /*
+   * When we hit a debugger event that requires suspension, it's important
+   * that we wait for the thread to suspend itself before processing any
+   * additional requests.  (Otherwise, if the debugger immediately sends a
+   * "resume thread" command, the resume might arrive before the thread has
+   * suspended itself.)
+   *
+   * The thread should call the "set" function before sending the event to
+   * the debugger.  The main JDWP handler loop calls "get" before processing
+   * an event, and will wait for thread suspension if it's set.  Once the
+   * thread has suspended itself, the JDWP handler calls "clear" and
+   * continues processing the current event.  This works in the suspend-all
+   * case because the event thread doesn't suspend itself until everything
+   * else has suspended.
+   *
+   * It's possible that multiple threads could encounter thread-suspending
+   * events at the same time, so we grab a mutex in the "set" call, and
+   * release it in the "clear" call.
+   */
+  //ObjectId GetWaitForEventThread();
+  void SetWaitForEventThread(ObjectId threadId);
+  void ClearWaitForEventThread();
 
-/*
- * The VM has finished initializing.  Only called when the debugger is
- * connected at the time initialization completes.
- */
-bool PostVMStart(JdwpState* state, bool suspend);
+  /*
+   * These notify the debug code that something interesting has happened.  This
+   * could be a thread starting or ending, an exception, or an opportunity
+   * for a breakpoint.  These calls do not mean that an event the debugger
+   * is interested has happened, just that something has happened that the
+   * debugger *might* be interested in.
+   *
+   * The item of interest may trigger multiple events, some or all of which
+   * are grouped together in a single response.
+   *
+   * The event may cause the current thread or all threads (except the
+   * JDWP support thread) to be suspended.
+   */
 
-/*
- * A location of interest has been reached.  This is used for breakpoints,
- * single-stepping, and method entry/exit.  (JDWP requires that these four
- * events are grouped together in a single response.)
- *
- * In some cases "*pLoc" will just have a method and class name, e.g. when
- * issuing a MethodEntry on a native method.
- *
- * "eventFlags" indicates the types of events that have occurred.
- */
-bool PostLocationEvent(JdwpState* state, const JdwpLocation* pLoc, ObjectId thisPtr, int eventFlags);
+  /*
+   * The VM has finished initializing.  Only called when the debugger is
+   * connected at the time initialization completes.
+   */
+  bool PostVMStart();
 
-/*
- * An exception has been thrown.
- *
- * Pass in a zeroed-out "*pCatchLoc" if the exception wasn't caught.
- */
-bool PostException(JdwpState* state, const JdwpLocation* pThrowLoc,
-    ObjectId excepId, RefTypeId excepClassId, const JdwpLocation* pCatchLoc,
-    ObjectId thisPtr);
+  /*
+   * A location of interest has been reached.  This is used for breakpoints,
+   * single-stepping, and method entry/exit.  (JDWP requires that these four
+   * events are grouped together in a single response.)
+   *
+   * In some cases "*pLoc" will just have a method and class name, e.g. when
+   * issuing a MethodEntry on a native method.
+   *
+   * "eventFlags" indicates the types of events that have occurred.
+   */
+  bool PostLocationEvent(const JdwpLocation* pLoc, ObjectId thisPtr, int eventFlags);
 
-/*
- * A thread has started or stopped.
- */
-bool PostThreadChange(JdwpState* state, ObjectId threadId, bool start);
+  /*
+   * An exception has been thrown.
+   *
+   * Pass in a zeroed-out "*pCatchLoc" if the exception wasn't caught.
+   */
+  bool PostException(const JdwpLocation* pThrowLoc, ObjectId excepId, RefTypeId excepClassId, const JdwpLocation* pCatchLoc, ObjectId thisPtr);
 
-/*
- * Class has been prepared.
- */
-bool PostClassPrepare(JdwpState* state, int tag, RefTypeId refTypeId,
-    const char* signature, int status);
+  /*
+   * A thread has started or stopped.
+   */
+  bool PostThreadChange(ObjectId threadId, bool start);
 
-/*
- * The VM is about to stop.
- */
-bool PostVMDeath(JdwpState* state);
+  /*
+   * Class has been prepared.
+   */
+  bool PostClassPrepare(int tag, RefTypeId refTypeId, const char* signature, int status);
 
-/*
- * Send up a chunk of DDM data.
- */
-void DdmSendChunkV(JdwpState* state, int type, const iovec* iov, int iovcnt);
+  /*
+   * The VM is about to stop.
+   */
+  bool PostVMDeath();
+
+  /*
+   * Send up a chunk of DDM data.
+   */
+  void DdmSendChunkV(int type, const iovec* iov, int iovcnt);
+
+  /*
+   * Process a request from the debugger.
+   *
+   * "buf" points past the header, to the content of the message.  "dataLen"
+   * can therefore be zero.
+   */
+  void ProcessRequest(const JdwpReqHeader* pHeader, const uint8_t* buf, int dataLen, ExpandBuf* pReply);
+
+  /*
+   * Send an event, formatted into "pReq", to the debugger.
+   *
+   * (Messages are sent asynchronously, and do not receive a reply.)
+   */
+  bool SendRequest(ExpandBuf* pReq);
+
+  void ResetState();
+
+  /* atomic ops to get next serial number */
+  uint32_t NextRequestSerial();
+  uint32_t NextEventSerial();
+
+  void Run();
+
+ private:
+  JdwpState(const JdwpOptions* options);
+  bool IsConnected();
+
+public: // TODO: fix privacy
+  const JdwpOptions* options_;
+private:
+
+  /* wait for creation of the JDWP thread */
+  Mutex thread_start_lock_;
+  ConditionVariable thread_start_cond_;
+
+  volatile int32_t debug_thread_started_;
+  pthread_t debugThreadHandle;
+public: // TODO: fix privacy
+  ObjectId debugThreadId;
+private:
+  bool run;
+
+  const JdwpTransport* transport;
+public: // TODO: fix privacy
+  JdwpNetState* netState;
+private:
+
+  /* for wait-for-debugger */
+  Mutex attach_lock_;
+  ConditionVariable attach_cond_;
+
+  /* time of last debugger activity, in milliseconds */
+  int64_t lastActivityWhen;
+
+  /* global counters and a mutex to protect them */
+  uint32_t requestSerial;
+  uint32_t eventSerial;
+  Mutex serial_lock_;
+
+  /*
+   * Events requested by the debugger (breakpoints, class prep, etc).
+   */
+public: // TODO: fix privacy
+  int numEvents;      /* #of elements in eventList */
+  JdwpEvent* eventList;      /* linked list of events */
+  Mutex event_lock_;      /* guards numEvents/eventList */
+private:
+
+  /*
+   * Synchronize suspension of event thread (to avoid receiving "resume"
+   * events before the thread has finished suspending itself).
+   */
+  Mutex event_thread_lock_;
+  ConditionVariable event_thread_cond_;
+  ObjectId eventThreadId;
+
+  /*
+   * DDM support.
+   */
+public: // TODO: fix privacy
+  bool ddmActive;
+private:
+};
 
 }  // namespace JDWP
 
diff --git a/src/jdwp/jdwp_adb.cc b/src/jdwp/jdwp_adb.cc
index 3a89f34..bd5e6e6 100644
--- a/src/jdwp/jdwp_adb.cc
+++ b/src/jdwp/jdwp_adb.cc
@@ -118,8 +118,8 @@
  * runs in the main thread, before the JDWP thread starts, so it shouldn't
  * do anything that might block forever.
  */
-static bool startup(JdwpState* state, const JdwpStartupParams* pParams) {
-  JdwpNetState*  netState;
+static bool startup(JdwpState* state, const JdwpOptions*) {
+  JdwpNetState* netState;
 
   LOG(VERBOSE) << "ADB transport startup";
 
@@ -445,7 +445,7 @@
     hdr.id = id;
     hdr.cmdSet = cmdSet;
     hdr.cmd = cmd;
-    ProcessRequest(state, &hdr, buf, dataLen, pReply);
+    state->ProcessRequest(&hdr, buf, dataLen, pReply);
     if (expandBufGetLength(pReply) > 0) {
       ssize_t cc = netState->writePacket(pReply);
 
diff --git a/src/jdwp/jdwp_event.cc b/src/jdwp/jdwp_event.cc
index 3a2d73e..835b182 100644
--- a/src/jdwp/jdwp_event.cc
+++ b/src/jdwp/jdwp_event.cc
@@ -120,24 +120,6 @@
 };
 
 /*
- * Get the next "request" serial number.  We use this when sending
- * packets to the debugger.
- */
-uint32_t NextRequestSerial(JdwpState* state) {
-  MutexLock mu(state->serial_lock_);
-  return state->requestSerial++;
-}
-
-/*
- * Get the next "event" serial number.  We use this in the response to
- * message type EventRequest.Set.
- */
-uint32_t NextEventSerial(JdwpState* state) {
-  MutexLock mu(state->serial_lock_);
-  return state->eventSerial++;
-}
-
-/*
  * Lock the "event" mutex, which guards the list of registered events.
  */
 static void lockEventMutex(JdwpState* state) {
@@ -584,7 +566,7 @@
     }
 
     /* grab this before posting/suspending again */
-    SetWaitForEventThread(state, Dbg::GetThreadSelfId());
+    state->SetWaitForEventThread(Dbg::GetThreadSelfId());
 
     /* leave pReq->invokeNeeded raised so we can check reentrancy */
     LOG(VERBOSE) << "invoking method...";
@@ -623,47 +605,47 @@
  * This could go to sleep waiting for another thread, so it's important
  * that the thread be marked as VMWAIT before calling here.
  */
-void SetWaitForEventThread(JdwpState* state, ObjectId threadId) {
+void JdwpState::SetWaitForEventThread(ObjectId threadId) {
   bool waited = false;
 
   /* this is held for very brief periods; contention is unlikely */
-  MutexLock mu(state->event_thread_lock_);
+  MutexLock mu(event_thread_lock_);
 
   /*
    * If another thread is already doing stuff, wait for it.  This can
    * go to sleep indefinitely.
    */
-  while (state->eventThreadId != 0) {
-    LOG(VERBOSE) << StringPrintf("event in progress (0x%llx), 0x%llx sleeping", state->eventThreadId, threadId);
+  while (eventThreadId != 0) {
+    LOG(VERBOSE) << StringPrintf("event in progress (0x%llx), 0x%llx sleeping", eventThreadId, threadId);
     waited = true;
-    state->event_thread_cond_.Wait(state->event_thread_lock_);
+    event_thread_cond_.Wait(event_thread_lock_);
   }
 
   if (waited || threadId != 0) {
     LOG(VERBOSE) << StringPrintf("event token grabbed (0x%llx)", threadId);
   }
   if (threadId != 0) {
-    state->eventThreadId = threadId;
+    eventThreadId = threadId;
   }
 }
 
 /*
  * Clear the threadId and signal anybody waiting.
  */
-void ClearWaitForEventThread(JdwpState* state) {
+void JdwpState::ClearWaitForEventThread() {
   /*
    * Grab the mutex.  Don't try to go in/out of VMWAIT mode, as this
    * function is called by dvmSuspendSelf(), and the transition back
    * to RUNNING would confuse it.
    */
-  MutexLock mu(state->event_thread_lock_);
+  MutexLock mu(event_thread_lock_);
 
-  CHECK_NE(state->eventThreadId, 0U);
-  LOG(VERBOSE) << StringPrintf("cleared event token (0x%llx)", state->eventThreadId);
+  CHECK_NE(eventThreadId, 0U);
+  LOG(VERBOSE) << StringPrintf("cleared event token (0x%llx)", eventThreadId);
 
-  state->eventThreadId = 0;
+  eventThreadId = 0;
 
-  state->event_thread_cond_.Signal();
+  event_thread_cond_.Signal();
 }
 
 
@@ -686,12 +668,12 @@
   uint8_t* buf = expandBufGetBuffer(pReq);
 
   set4BE(buf, expandBufGetLength(pReq));
-  set4BE(buf+4, NextRequestSerial(state));
+  set4BE(buf+4, state->NextRequestSerial());
   set1(buf+8, 0);     /* flags */
   set1(buf+9, kJdwpEventCommandSet);
   set1(buf+10, kJdwpCompositeCommand);
 
-  SendRequest(state, pReq);
+  state->SendRequest(pReq);
 
   expandBufFree(pReq);
 }
@@ -705,18 +687,18 @@
  * any application code has been executed".  The thread ID in the message
  * must be for the main thread.
  */
-bool PostVMStart(JdwpState* state, bool suspend) {
+bool JdwpState::PostVMStart() {
   JdwpSuspendPolicy suspendPolicy;
   ObjectId threadId = Dbg::GetThreadSelfId();
 
-  if (suspend) {
+  if (options_->suspend) {
     suspendPolicy = SP_ALL;
   } else {
     suspendPolicy = SP_NONE;
   }
 
   /* probably don't need this here */
-  lockEventMutex(state);
+  lockEventMutex(this);
 
   ExpandBuf* pReq = NULL;
   if (true) {
@@ -732,19 +714,19 @@
     expandBufAdd8BE(pReq, threadId);
   }
 
-  unlockEventMutex(state);
+  unlockEventMutex(this);
 
   /* send request and possibly suspend ourselves */
   if (pReq != NULL) {
-    int oldStatus = Dbg::ThreadWaiting();
+    int old_state = Dbg::ThreadWaiting();
     if (suspendPolicy != SP_NONE) {
-      SetWaitForEventThread(state, threadId);
+      SetWaitForEventThread(threadId);
     }
 
-    eventFinish(state, pReq);
+    eventFinish(this, pReq);
 
-    suspendByPolicy(state, suspendPolicy);
-    Dbg::ThreadContinuing(oldStatus);
+    suspendByPolicy(this, suspendPolicy);
+    Dbg::ThreadContinuing(old_state);
   }
 
   return true;
@@ -861,15 +843,15 @@
 
   /* send request and possibly suspend ourselves */
   if (pReq != NULL) {
-    int oldStatus = Dbg::ThreadWaiting();
+    int old_state = Dbg::ThreadWaiting();
     if (suspendPolicy != SP_NONE) {
-      SetWaitForEventThread(state, basket.threadId);
+      state->SetWaitForEventThread(basket.threadId);
     }
 
     eventFinish(state, pReq);
 
     suspendByPolicy(state, suspendPolicy);
-    Dbg::ThreadContinuing(oldStatus);
+    Dbg::ThreadContinuing(old_state);
   }
 
   free(nameAlloc);
@@ -934,14 +916,14 @@
 
   /* send request and possibly suspend ourselves */
   if (pReq != NULL) {
-    int oldStatus = Dbg::ThreadWaiting();
+    int old_state = Dbg::ThreadWaiting();
     if (suspendPolicy != SP_NONE) {
-      SetWaitForEventThread(state, basket.threadId);
+      state->SetWaitForEventThread(basket.threadId);
     }
     eventFinish(state, pReq);
 
     suspendByPolicy(state, suspendPolicy);
-    Dbg::ThreadContinuing(oldStatus);
+    Dbg::ThreadContinuing(old_state);
   }
 
   return matchCount != 0;
@@ -952,7 +934,7 @@
  *
  * Skips the usual "event token" stuff.
  */
-bool PostVMDeath(JdwpState* state) {
+bool JdwpState::PostVMDeath() {
   LOG(VERBOSE) << "EVENT: " << EK_VM_DEATH;
 
   ExpandBuf* pReq = eventPrep();
@@ -961,7 +943,7 @@
 
   expandBufAdd1(pReq, EK_VM_DEATH);
   expandBufAdd4BE(pReq, 0);
-  eventFinish(state, pReq);
+  eventFinish(this, pReq);
   return true;
 }
 
@@ -1054,15 +1036,15 @@
 
   /* send request and possibly suspend ourselves */
   if (pReq != NULL) {
-    int oldStatus = Dbg::ThreadWaiting();
+    int old_state = Dbg::ThreadWaiting();
     if (suspendPolicy != SP_NONE) {
-      SetWaitForEventThread(state, basket.threadId);
+      state->SetWaitForEventThread(basket.threadId);
     }
 
     eventFinish(state, pReq);
 
     suspendByPolicy(state, suspendPolicy);
-    Dbg::ThreadContinuing(oldStatus);
+    Dbg::ThreadContinuing(old_state);
   }
 
   free(nameAlloc);
@@ -1143,24 +1125,20 @@
 
   /* send request and possibly suspend ourselves */
   if (pReq != NULL) {
-    int oldStatus = Dbg::ThreadWaiting();
+    int old_state = Dbg::ThreadWaiting();
     if (suspendPolicy != SP_NONE) {
-      SetWaitForEventThread(state, basket.threadId);
+      state->SetWaitForEventThread(basket.threadId);
     }
     eventFinish(state, pReq);
 
     suspendByPolicy(state, suspendPolicy);
-    Dbg::ThreadContinuing(oldStatus);
+    Dbg::ThreadContinuing(old_state);
   }
 
   free(nameAlloc);
   return matchCount != 0;
 }
 
-bool SendBufferedRequest(JdwpState* state, const iovec* iov, int iovcnt) {
-  return (*state->transport->sendBufferedRequest)(state, iov, iovcnt);
-}
-
 /*
  * Send up a chunk of DDM data.
  *
@@ -1168,7 +1146,7 @@
  * other debugger traffic, and can't suspend the VM, so we skip all of
  * the fun event token gymnastics.
  */
-void DdmSendChunkV(JdwpState* state, int type, const iovec* iov, int iovcnt) {
+void JdwpState::DdmSendChunkV(int type, const iovec* iov, int iovcnt) {
   uint8_t header[kJDWPHeaderLen + 8];
   size_t dataLen = 0;
 
@@ -1188,7 +1166,7 @@
 
   /* form the header (JDWP plus DDMS) */
   set4BE(header, sizeof(header) + dataLen);
-  set4BE(header+4, NextRequestSerial(state));
+  set4BE(header+4, NextRequestSerial());
   set1(header+8, 0);     /* flags */
   set1(header+9, kJDWPDdmCmdSet);
   set1(header+10, kJDWPDdmCmd);
@@ -1201,9 +1179,9 @@
   /*
    * Make sure we're in VMWAIT in case the write blocks.
    */
-  int oldStatus = Dbg::ThreadWaiting();
-  SendBufferedRequest(state, wrapiov, iovcnt+1);
-  Dbg::ThreadContinuing(oldStatus);
+  int old_state = Dbg::ThreadWaiting();
+  (*transport->sendBufferedRequest)(this, wrapiov, iovcnt + 1);
+  Dbg::ThreadContinuing(old_state);
 }
 
 }  // namespace JDWP
diff --git a/src/jdwp/jdwp_event.h b/src/jdwp/jdwp_event.h
index 2b957fb..81a1eba 100644
--- a/src/jdwp/jdwp_event.h
+++ b/src/jdwp/jdwp_event.h
@@ -123,13 +123,6 @@
  */
 void UnregisterAll(JdwpState* state);
 
-/*
- * Send an event, formatted into "pReq", to the debugger.
- *
- * (Messages are sent asynchronously, and do not receive a reply.)
- */
-bool SendRequest(JdwpState* state, ExpandBuf* pReq);
-
 }  // namespace JDWP
 
 }  // namespace art
diff --git a/src/jdwp/jdwp_handler.cc b/src/jdwp/jdwp_handler.cc
index 8fe3c3f..5e566ae 100644
--- a/src/jdwp/jdwp_handler.cc
+++ b/src/jdwp/jdwp_handler.cc
@@ -1412,7 +1412,7 @@
   /*
    * We reply with an integer "requestID".
    */
-  uint32_t requestId = NextEventSerial(state);
+  uint32_t requestId = state->NextEventSerial();
   expandBufAdd4BE(pReply, requestId);
 
   pEvent->requestId = requestId;
@@ -1722,7 +1722,7 @@
  *
  * On entry, the JDWP thread is in VMWAIT.
  */
-void ProcessRequest(JdwpState* state, const JdwpReqHeader* pHeader, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
+void JdwpState::ProcessRequest(const JdwpReqHeader* pHeader, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
   JdwpError result = ERR_NONE;
   int i, respLen;
 
@@ -1733,7 +1733,7 @@
      * so waitForDebugger() doesn't return if we stall for a bit here.
      */
     Dbg::Active();
-    QuasiAtomicSwap64(0, &state->lastActivityWhen);
+    QuasiAtomicSwap64(0, &lastActivityWhen);
   }
 
   /*
@@ -1752,7 +1752,7 @@
    * thread up, or risk waiting for the thread to suspend after we've
    * told it to resume.
    */
-  SetWaitForEventThread(state, 0);
+  SetWaitForEventThread(0);
 
   /*
    * Tell the VM that we're running and shouldn't be interrupted by GC.
@@ -1765,7 +1765,7 @@
   for (i = 0; i < (int) arraysize(gHandlerMap); i++) {
     if (gHandlerMap[i].cmdSet == pHeader->cmdSet && gHandlerMap[i].cmd == pHeader->cmd) {
       LOG(VERBOSE) << StringPrintf("REQ: %s (cmd=%d/%d dataLen=%d id=0x%06x)", gHandlerMap[i].descr, pHeader->cmdSet, pHeader->cmd, dataLen, pHeader->id);
-      result = (*gHandlerMap[i].func)(state, buf, dataLen, pReply);
+      result = (*gHandlerMap[i].func)(this, buf, dataLen, pReply);
       break;
     }
   }
@@ -1806,7 +1806,7 @@
    * the initial setup.  Only update if this is a non-DDMS packet.
    */
   if (pHeader->cmdSet != kJDWPDdmCmdSet) {
-    QuasiAtomicSwap64(GetNowMsec(), &state->lastActivityWhen);
+    QuasiAtomicSwap64(GetNowMsec(), &lastActivityWhen);
   }
 
   /* tell the VM that GC is okay again */
diff --git a/src/jdwp/jdwp_handler.h b/src/jdwp/jdwp_handler.h
index 6fa75d7..0159701 100644
--- a/src/jdwp/jdwp_handler.h
+++ b/src/jdwp/jdwp_handler.h
@@ -35,15 +35,6 @@
   uint8_t cmd;
 };
 
-/*
- * Process a request from the debugger.
- *
- * "buf" points past the header, to the content of the message.  "dataLen"
- * can therefore be zero.
- */
-void ProcessRequest(JdwpState* state, const JdwpReqHeader* pHeader,
-    const uint8_t* buf, int dataLen, ExpandBuf* pReply);
-
 /* helper function */
 void AddLocation(ExpandBuf* pReply, const JdwpLocation* pLoc);
 
diff --git a/src/jdwp/jdwp_main.cc b/src/jdwp/jdwp_main.cc
index c9dac64f..31337fd 100644
--- a/src/jdwp/jdwp_main.cc
+++ b/src/jdwp/jdwp_main.cc
@@ -33,7 +33,7 @@
 
 namespace JDWP {
 
-static void* jdwpThreadStart(void* arg);
+static void* StartJdwpThread(void* arg);
 
 /*
  * JdwpNetStateBase class implementation
@@ -58,56 +58,35 @@
   return writev(clientSock, iov, iovcnt);
 }
 
-bool NetStartup(JdwpState* state, const JdwpStartupParams* pParams) {
-  return (*state->transport->startup)(state, pParams);
+bool JdwpState::IsConnected() {
+  return (*transport->isConnected)(this);
 }
 
-bool AcceptConnection(JdwpState* state) {
-  return (*state->transport->accept)(state);
+bool JdwpState::SendRequest(ExpandBuf* pReq) {
+  return (*transport->sendRequest)(this, pReq);
 }
 
-bool EstablishConnection(JdwpState* state) {
-  return (*state->transport->establish)(state);
+/*
+ * Get the next "request" serial number.  We use this when sending
+ * packets to the debugger.
+ */
+uint32_t JdwpState::NextRequestSerial() {
+  MutexLock mu(serial_lock_);
+  return requestSerial++;
 }
 
-void CloseConnection(JdwpState* state) {
-  (*state->transport->close)(state);
+/*
+ * Get the next "event" serial number.  We use this in the response to
+ * message type EventRequest.Set.
+ */
+uint32_t JdwpState::NextEventSerial() {
+  MutexLock mu(serial_lock_);
+  return eventSerial++;
 }
 
-void NetShutdown(JdwpState* state) {
-  (*state->transport->shutdown)(state);
-}
-
-void NetFree(JdwpState* state) {
-  (*state->transport->free)(state);
-}
-
-bool IsTransportDefined(JdwpState* state) {
-  return state != NULL && state->transport != NULL;
-}
-
-bool JdwpIsConnected(JdwpState* state) {
-  return state != NULL && (*state->transport->isConnected)(state);
-}
-
-bool AwaitingHandshake(JdwpState* state) {
-  return (*state->transport->awaitingHandshake)(state);
-}
-
-bool ProcessIncoming(JdwpState* state) {
-  return (*state->transport->processIncoming)(state);
-}
-
-bool SendRequest(JdwpState* state, ExpandBuf* pReq) {
-  return (*state->transport->sendRequest)(state, pReq);
-}
-
-static void CreateJdwpThread(JdwpState* state) {
-  CHECK_PTHREAD_CALL(pthread_create, (&state->debugThreadHandle, NULL, jdwpThreadStart, state), "JDWP thread");
-}
-
-JdwpState::JdwpState()
-    : thread_start_lock_("JDWP thread start lock"),
+JdwpState::JdwpState(const JdwpOptions* options)
+    : options_(options),
+      thread_start_lock_("JDWP thread start lock"),
       thread_start_cond_("JDWP thread start condition variable"),
       debug_thread_started_(false),
       debugThreadId(0),
@@ -135,15 +114,12 @@
  * Does not return until JDWP thread is running, but may return before
  * the thread is accepting network connections.
  */
-JdwpState* JdwpStartup(const JdwpStartupParams* pParams) {
+JdwpState* JdwpState::Create(const JdwpOptions* options) {
   /* comment this out when debugging JDWP itself */
   //android_setMinPriority(LOG_TAG, ANDROID_LOG_DEBUG);
 
-  JdwpState* state = new JdwpState;
-
-  state->params = *pParams;
-
-  switch (pParams->transport) {
+  JdwpState* state = new JdwpState(options);
+  switch (options->transport) {
   case kJdwpTransportSocket:
     // LOGD("prepping for JDWP over TCP");
     state->transport = SocketTransport();
@@ -155,10 +131,10 @@
     break;
 #endif
   default:
-    LOG(FATAL) << "Unknown transport: " << pParams->transport;
+    LOG(FATAL) << "Unknown transport: " << options->transport;
   }
 
-  if (!NetStartup(state, pParams)) {
+  if (!(*state->transport->startup)(state, options)) {
     goto fail;
   }
 
@@ -167,7 +143,7 @@
    * won't signal the cond var before we're waiting.
    */
   state->thread_start_lock_.Lock();
-  if (pParams->suspend) {
+  if (options->suspend) {
     state->attach_lock_.Lock();
   }
 
@@ -175,7 +151,7 @@
    * We have bound to a port, or are trying to connect outbound to a
    * debugger.  Create the JDWP thread and let it continue the mission.
    */
-  CreateJdwpThread(state);
+  CHECK_PTHREAD_CALL(pthread_create, (&state->debugThreadHandle, NULL, StartJdwpThread, state), "JDWP thread");
 
   /*
    * Wait until the thread finishes basic initialization.
@@ -192,7 +168,7 @@
    * times out (for timeout=xxx), so we have to check to see what happened
    * when we wake up.
    */
-  if (pParams->suspend) {
+  if (options->suspend) {
     {
       ScopedThreadStateChange tsc(Thread::Current(), Thread::kVmWait);
 
@@ -200,7 +176,7 @@
       state->attach_lock_.Unlock();
     }
 
-    if (!JdwpIsActive(state)) {
+    if (!state->IsActive()) {
       LOG(ERROR) << "JDWP connection failed";
       goto fail;
     }
@@ -217,7 +193,7 @@
   return state;
 
 fail:
-  JdwpShutdown(state);     // frees state
+  delete state;     // frees state
   return NULL;
 }
 
@@ -228,17 +204,17 @@
  *
  * This includes freeing up the debugger event list.
  */
-void ResetState(JdwpState* state) {
+void JdwpState::ResetState() {
   /* could reset the serial numbers, but no need to */
 
-  UnregisterAll(state);
-  CHECK(state->eventList == NULL);
+  UnregisterAll(this);
+  CHECK(eventList == NULL);
 
   /*
    * Should not have one of these in progress.  If the debugger went away
    * mid-request, though, we could see this.
    */
-  if (state->eventThreadId != 0) {
+  if (eventThreadId != 0) {
     LOG(WARNING) << "resetting state while event in progress";
     DCHECK(false);
   }
@@ -247,72 +223,71 @@
 /*
  * Tell the JDWP thread to shut down.  Frees "state".
  */
-void JdwpShutdown(JdwpState* state) {
-  void* threadReturn;
-
-  if (state == NULL) {
-    return;
-  }
-
-  if (IsTransportDefined(state)) {
-    if (JdwpIsConnected(state)) {
-      PostVMDeath(state);
+JdwpState::~JdwpState() {
+  if (transport != NULL) {
+    if (IsConnected()) {
+      PostVMDeath();
     }
 
     /*
      * Close down the network to inspire the thread to halt.
      */
     LOG(DEBUG) << "JDWP shutting down net...";
-    NetShutdown(state);
+    (*transport->shutdown)(this);
 
-    if (state->debug_thread_started_) {
-      state->run = false;
-      if (pthread_join(state->debugThreadHandle, &threadReturn) != 0) {
+    if (debug_thread_started_) {
+      run = false;
+      void* threadReturn;
+      if (pthread_join(debugThreadHandle, &threadReturn) != 0) {
         LOG(WARNING) << "JDWP thread join failed";
       }
     }
 
     LOG(DEBUG) << "JDWP freeing netstate...";
-    NetFree(state);
-    state->netState = NULL;
+    (*transport->free)(this);
+    netState = NULL;
   }
-  CHECK(state->netState == NULL);
+  CHECK(netState == NULL);
 
-  ResetState(state);
-  free(state);
+  ResetState();
 }
 
 /*
  * Are we talking to a debugger?
  */
-bool JdwpIsActive(JdwpState* state) {
-  return JdwpIsConnected(state);
+bool JdwpState::IsActive() {
+  return IsConnected();
 }
 
 /*
  * Entry point for JDWP thread.  The thread was created through the VM
  * mechanisms, so there is a java/lang/Thread associated with us.
  */
-static void* jdwpThreadStart(void* arg) {
+static void* StartJdwpThread(void* arg) {
   JdwpState* state = reinterpret_cast<JdwpState*>(arg);
   CHECK(state != NULL);
 
+  state->Run();
+  return NULL;
+}
+
+void JdwpState::Run() {
   Runtime* runtime = Runtime::Current();
   runtime->AttachCurrentThread("JDWP", true);
 
   LOG(VERBOSE) << "JDWP: thread running";
 
   /*
-   * Finish initializing "state", then notify the creating thread that
+   * Finish initializing, then notify the creating thread that
    * we're running.
    */
-  state->debugThreadHandle = pthread_self();
-  state->run = true;
-  android_atomic_release_store(true, &state->debug_thread_started_);
+  debugThreadHandle = pthread_self();
+  run = true;
+  android_atomic_release_store(true, &debug_thread_started_);
 
-  state->thread_start_lock_.Lock();
-  state->thread_start_cond_.Broadcast();
-  state->thread_start_lock_.Unlock();
+  thread_start_lock_.Lock();
+  thread_start_cond_.Broadcast();
+  thread_start_lock_.Unlock();
 
   /* set the thread state to VMWAIT so GCs don't wait for us */
   Dbg::ThreadWaiting();
@@ -325,15 +300,13 @@
    * We broadcast a notification when a debugger attaches, after we
    * successfully process the handshake.
    */
-  while (state->run) {
-    bool first;
-
-    if (state->params.server) {
+  while (run) {
+    if (options_->server) {
       /*
        * Block forever, waiting for a connection.  To support the
        * "timeout=xxx" option we'll need to tweak this.
        */
-      if (!AcceptConnection(state)) {
+      if (!(*transport->accept)(this)) {
         break;
       }
     } else {
@@ -343,10 +316,10 @@
        * have a timeout if the handshake reply isn't received in a
        * reasonable amount of time.
        */
-      if (!EstablishConnection(state)) {
+      if (!(*transport->establish)(this)) {
         /* wake anybody who was waiting for us to succeed */
-        MutexLock mu(state->attach_lock_);
-        state->attach_cond_.Broadcast();
+        MutexLock mu(attach_lock_);
+        attach_cond_.Broadcast();
         break;
       }
     }
@@ -355,7 +328,7 @@
     Dbg::Connected();
 
     /* process requests until the debugger drops */
-    first = true;
+    bool first = true;
     while (true) {
       // sanity check -- shouldn't happen?
       if (Thread::Current()->GetState() != Thread::kVmWait) {
@@ -363,28 +336,28 @@
         Dbg::ThreadWaiting();
       }
 
-      if (!ProcessIncoming(state)) {
+      if (!(*transport->processIncoming)(this)) {
         /* blocking read */
         break;
       }
 
-      if (first && !AwaitingHandshake(state)) {
+      if (first && !(*transport->awaitingHandshake)(this)) {
         /* handshake worked, tell the interpreter that we're active */
         first = false;
 
         /* set thread ID; requires object registry to be active */
-        state->debugThreadId = Dbg::GetThreadSelfId();
+        debugThreadId = Dbg::GetThreadSelfId();
 
         /* wake anybody who's waiting for us */
-        MutexLock mu(state->attach_lock_);
-        state->attach_cond_.Broadcast();
+        MutexLock mu(attach_lock_);
+        attach_cond_.Broadcast();
       }
     }
 
-    CloseConnection(state);
+    (*transport->close)(this);
 
-    if (state->ddmActive) {
-      state->ddmActive = false;
+    if (ddmActive) {
+      ddmActive = false;
 
       /* broadcast the disconnect; must be in RUNNING state */
       Dbg::ThreadRunning();
@@ -393,7 +366,7 @@
     }
 
     /* release session state, e.g. remove breakpoint instructions */
-    ResetState(state);
+    ResetState();
 
     /* tell the interpreter that the debugger is no longer around */
     Dbg::Disconnected();
@@ -402,8 +375,8 @@
     Dbg::UndoDebuggerSuspensions();
 
     /* if we connected out, this was a one-shot deal */
-    if (!state->params.server) {
-      state->run = false;
+    if (!options_->server) {
+      run = false;
     }
   }
 
@@ -411,18 +384,10 @@
   Dbg::ThreadRunning();
 
   LOG(VERBOSE) << "JDWP: thread exiting";
-  return NULL;
 }
 
-
-/*
- * Return the thread handle, or (pthread_t)0 if the debugger isn't running.
- */
-pthread_t GetDebugThread(JdwpState* state) {
-  if (state == NULL) {
-    return 0;
-  }
-  return state->debugThreadHandle;
+pthread_t JdwpState::GetDebugThread() {
+  return debugThreadHandle;
 }
 
 /*
@@ -466,13 +431,13 @@
  * Returns -1 if no debugger is attached, or 0 if we're in the middle of
  * processing a debugger request.
  */
-int64_t LastDebuggerActivity(JdwpState* state) {
+int64_t JdwpState::LastDebuggerActivity() {
   if (!Dbg::IsDebuggerConnected()) {
     LOG(DEBUG) << "no active debugger";
     return -1;
   }
 
-  int64_t last = QuasiAtomicRead64(&state->lastActivityWhen);
+  int64_t last = QuasiAtomicRead64(&lastActivityWhen);
 
   /* initializing or in the middle of something? */
   if (last == 0) {
diff --git a/src/jdwp/jdwp_priv.h b/src/jdwp/jdwp_priv.h
index 60169dd..46f79b8 100644
--- a/src/jdwp/jdwp_priv.h
+++ b/src/jdwp/jdwp_priv.h
@@ -24,7 +24,6 @@
 #include "debugger.h"
 #include "jdwp/jdwp.h"
 #include "jdwp/jdwp_event.h"
-#include "../mutex.h" // TODO: fix our include path!
 
 #include <pthread.h>
 #include <sys/uio.h>
@@ -53,7 +52,7 @@
  * Transport functions.
  */
 struct JdwpTransport {
-  bool (*startup)(JdwpState* state, const JdwpStartupParams* pParams);
+  bool (*startup)(JdwpState* state, const JdwpOptions* options);
   bool (*accept)(JdwpState* state);
   bool (*establish)(JdwpState* state);
   void (*close)(JdwpState* state);
@@ -69,60 +68,6 @@
 const JdwpTransport* SocketTransport();
 const JdwpTransport* AndroidAdbTransport();
 
-
-/*
- * State for JDWP functions.
- */
-struct JdwpState {
-  JdwpState();
-
-  JdwpStartupParams params;
-
-  /* wait for creation of the JDWP thread */
-  Mutex thread_start_lock_;
-  ConditionVariable thread_start_cond_;
-
-  volatile int32_t debug_thread_started_;
-  pthread_t debugThreadHandle;
-  ObjectId debugThreadId;
-  bool run;
-
-  const JdwpTransport* transport;
-  JdwpNetState* netState;
-
-  /* for wait-for-debugger */
-  Mutex attach_lock_;
-  ConditionVariable attach_cond_;
-
-  /* time of last debugger activity, in milliseconds */
-  int64_t lastActivityWhen;
-
-  /* global counters and a mutex to protect them */
-  uint32_t requestSerial;
-  uint32_t eventSerial;
-  Mutex serial_lock_;
-
-  /*
-   * Events requested by the debugger (breakpoints, class prep, etc).
-   */
-  int numEvents;      /* #of elements in eventList */
-  JdwpEvent* eventList;      /* linked list of events */
-  Mutex event_lock_;      /* guards numEvents/eventList */
-
-  /*
-   * Synchronize suspension of event thread (to avoid receiving "resume"
-   * events before the thread has finished suspending itself).
-   */
-  Mutex event_thread_lock_;
-  ConditionVariable event_thread_cond_;
-  ObjectId eventThreadId;
-
-  /*
-   * DDM support.
-   */
-  bool ddmActive;
-};
-
 /*
  * Base class for JdwpNetState
  */
@@ -138,14 +83,6 @@
   Mutex socket_lock_;
 };
 
-
-/* reset all session-specific data */
-void ResetState(JdwpState* state);
-
-/* atomic ops to get next serial number */
-uint32_t NextRequestSerial(JdwpState* state);
-uint32_t NextEventSerial(JdwpState* state);
-
 /* get current time, in msec */
 int64_t GetNowMsec();
 
diff --git a/src/jdwp/jdwp_socket.cc b/src/jdwp/jdwp_socket.cc
index 55bc1b4..28786ed 100644
--- a/src/jdwp/jdwp_socket.cc
+++ b/src/jdwp/jdwp_socket.cc
@@ -68,8 +68,7 @@
     unsigned char  inputBuffer[kInputBufferSize];
     int     inputCount;
 
-    JdwpNetState()
-    {
+    JdwpNetState() {
         listenPort  = 0;
         listenSock  = -1;
         wakePipe[0] = -1;
@@ -86,13 +85,13 @@
 /*
  * Set up some stuff for transport=dt_socket.
  */
-static bool prepareSocket(JdwpState* state, const JdwpStartupParams* pParams) {
+static bool prepareSocket(JdwpState* state, const JdwpOptions* options) {
   unsigned short port;
 
-  if (pParams->server) {
-    if (pParams->port != 0) {
+  if (options->server) {
+    if (options->port != 0) {
       /* try only the specified port */
-      port = pParams->port;
+      port = options->port;
       state->netState = netStartup(port);
     } else {
       /* scan through a range of ports, binding to the first available */
@@ -104,18 +103,18 @@
       }
     }
     if (state->netState == NULL) {
-      LOG(ERROR) << "JDWP net startup failed (req port=" << pParams->port << ")";
+      LOG(ERROR) << "JDWP net startup failed (req port=" << options->port << ")";
       return false;
     }
   } else {
-    port = pParams->port;   // used in a debug msg later
+    port = options->port;   // used in a debug msg later
     state->netState = netStartup(-1);
   }
 
-  if (pParams->suspend) {
+  if (options->suspend) {
     LOG(INFO) << "JDWP will wait for debugger on port " << port;
   } else {
-    LOG(INFO) << "JDWP will " << (pParams->server ? "listen" : "connect") << " on port " << port;
+    LOG(INFO) << "JDWP will " << (options->server ? "listen" : "connect") << " on port " << port;
   }
 
   return true;
@@ -394,9 +393,9 @@
   struct hostent* pEntry;
 
   CHECK(state != NULL && state->netState != NULL);
-  CHECK(!state->params.server);
-  CHECK_NE(state->params.host[0], '\0');
-  CHECK_NE(state->params.port, 0);
+  CHECK(!state->options_->server);
+  CHECK(!state->options_->host.empty());
+  CHECK_NE(state->options_->port, 0);
 
   /*
    * Start by resolving the host name.
@@ -407,16 +406,16 @@
   struct hostent he;
   char auxBuf[128];
   int error;
-  int cc = gethostbyname_r(state->params.host.c_str(), &he, auxBuf, sizeof(auxBuf), &pEntry, &error);
+  int cc = gethostbyname_r(state->options_->host.c_str(), &he, auxBuf, sizeof(auxBuf), &pEntry, &error);
   if (cc != 0) {
-    LOG(WARNING) << "gethostbyname_r('" << state->params.host << "') failed: " << hstrerror(error);
+    LOG(WARNING) << "gethostbyname_r('" << state->options_->host << "') failed: " << hstrerror(error);
     return false;
   }
 #else
   h_errno = 0;
-  pEntry = gethostbyname(state->params.host.c_str());
+  pEntry = gethostbyname(state->options_->host.c_str());
   if (pEntry == NULL) {
-    PLOG(WARNING) << "gethostbyname('" << state->params.host << "') failed";
+    PLOG(WARNING) << "gethostbyname('" << state->options_->host << "') failed";
     return false;
   }
 #endif
@@ -425,7 +424,7 @@
   memcpy(&addr.addrInet.sin_addr, pEntry->h_addr, pEntry->h_length);
   addr.addrInet.sin_family = pEntry->h_addrtype;
 
-  addr.addrInet.sin_port = htons(state->params.port);
+  addr.addrInet.sin_port = htons(state->options_->port);
 
   LOG(INFO) << "Connecting out to " << inet_ntoa(addr.addrInet.sin_addr) << ":" << ntohs(addr.addrInet.sin_port);
 
@@ -450,7 +449,7 @@
     return false;
   }
 
-  LOG(INFO) << "Connection established to " << state->params.host << " (" << inet_ntoa(addr.addrInet.sin_addr) << ":" << ntohs(addr.addrInet.sin_port) << ")";
+  LOG(INFO) << "Connection established to " << state->options_->host << " (" << inet_ntoa(addr.addrInet.sin_addr) << ":" << ntohs(addr.addrInet.sin_port) << ")";
   netState->awaitingHandshake = true;
   netState->inputCount = 0;
 
@@ -522,102 +521,99 @@
  * Dump the contents of a packet to stdout.
  */
 #if 0
-static void dumpPacket(const unsigned char* packetBuf)
-{
-    const unsigned char* buf = packetBuf;
-    uint32_t length, id;
-    uint8_t flags, cmdSet, cmd;
-    uint16_t error;
-    bool reply;
-    int dataLen;
+static void dumpPacket(const unsigned char* packetBuf) {
+  const unsigned char* buf = packetBuf;
+  uint32_t length, id;
+  uint8_t flags, cmdSet, cmd;
+  uint16_t error;
+  bool reply;
+  int dataLen;
 
-    cmd = cmdSet = 0xcc;
+  cmd = cmdSet = 0xcc;
 
-    length = read4BE(&buf);
-    id = read4BE(&buf);
-    flags = read1(&buf);
-    if ((flags & kJDWPFlagReply) != 0) {
-        reply = true;
-        error = read2BE(&buf);
-    } else {
-        reply = false;
-        cmdSet = read1(&buf);
-        cmd = read1(&buf);
-    }
+  length = read4BE(&buf);
+  id = read4BE(&buf);
+  flags = read1(&buf);
+  if ((flags & kJDWPFlagReply) != 0) {
+    reply = true;
+    error = read2BE(&buf);
+  } else {
+    reply = false;
+    cmdSet = read1(&buf);
+    cmd = read1(&buf);
+  }
 
-    dataLen = length - (buf - packetBuf);
+  dataLen = length - (buf - packetBuf);
 
-    LOG(VERBOSE) << StringPrintf("--- %s: dataLen=%u id=0x%08x flags=0x%02x cmd=%d/%d",
-        reply ? "reply" : "req",
-        dataLen, id, flags, cmdSet, cmd);
-    if (dataLen > 0) {
-      HexDump(buf, dataLen);
-    }
+  LOG(VERBOSE) << StringPrintf("--- %s: dataLen=%u id=0x%08x flags=0x%02x cmd=%d/%d",
+      reply ? "reply" : "req", dataLen, id, flags, cmdSet, cmd);
+  if (dataLen > 0) {
+    HexDump(buf, dataLen);
+  }
 }
 #endif
 
 /*
  * Handle a packet.  Returns "false" if we encounter a connection-fatal error.
  */
-static bool handlePacket(JdwpState* state)
-{
-    JdwpNetState* netState = state->netState;
-    const unsigned char* buf = netState->inputBuffer;
-    JdwpReqHeader hdr;
-    uint32_t length, id;
-    uint8_t flags, cmdSet, cmd;
-    uint16_t error;
-    bool reply;
-    int dataLen;
+static bool handlePacket(JdwpState* state) {
+  JdwpNetState* netState = state->netState;
+  const unsigned char* buf = netState->inputBuffer;
+  JdwpReqHeader hdr;
+  uint32_t length, id;
+  uint8_t flags, cmdSet, cmd;
+  uint16_t error;
+  bool reply;
+  int dataLen;
 
-    cmd = cmdSet = 0;       // shut up gcc
+  cmd = cmdSet = 0;       // shut up gcc
 
-    /*dumpPacket(netState->inputBuffer);*/
+  /*dumpPacket(netState->inputBuffer);*/
 
-    length = read4BE(&buf);
-    id = read4BE(&buf);
-    flags = read1(&buf);
-    if ((flags & kJDWPFlagReply) != 0) {
-        reply = true;
-        error = read2BE(&buf);
-    } else {
-        reply = false;
-        cmdSet = read1(&buf);
-        cmd = read1(&buf);
-    }
+  length = read4BE(&buf);
+  id = read4BE(&buf);
+  flags = read1(&buf);
+  if ((flags & kJDWPFlagReply) != 0) {
+    reply = true;
+    error = read2BE(&buf);
+  } else {
+    reply = false;
+    cmdSet = read1(&buf);
+    cmd = read1(&buf);
+  }
 
-    CHECK_LE((int) length, netState->inputCount);
-    dataLen = length - (buf - netState->inputBuffer);
+  CHECK_LE((int) length, netState->inputCount);
+  dataLen = length - (buf - netState->inputBuffer);
 
-    if (!reply) {
-        ExpandBuf* pReply = expandBufAlloc();
+  if (!reply) {
+    ExpandBuf* pReply = expandBufAlloc();
 
-        hdr.length = length;
-        hdr.id = id;
-        hdr.cmdSet = cmdSet;
-        hdr.cmd = cmd;
-        ProcessRequest(state, &hdr, buf, dataLen, pReply);
-        if (expandBufGetLength(pReply) > 0) {
-            ssize_t cc = netState->writePacket(pReply);
+    hdr.length = length;
+    hdr.id = id;
+    hdr.cmdSet = cmdSet;
+    hdr.cmd = cmd;
+    state->ProcessRequest(&hdr, buf, dataLen, pReply);
+    if (expandBufGetLength(pReply) > 0) {
+      ssize_t cc = netState->writePacket(pReply);
 
-            if (cc != (ssize_t) expandBufGetLength(pReply)) {
-              PLOG(ERROR) << "Failed sending reply to debugger";
-              expandBufFree(pReply);
-              return false;
-            }
-        } else {
-          LOG(WARNING) << "No reply created for set=" << cmdSet << " cmd=" << cmd;
-        }
+      if (cc != (ssize_t) expandBufGetLength(pReply)) {
+        PLOG(ERROR) << "Failed sending reply to debugger";
         expandBufFree(pReply);
+        return false;
+      }
     } else {
-      LOG(ERROR) << "reply?!";
-      DCHECK(false);
+      LOG(WARNING) << "No reply created for set=" << cmdSet << " cmd=" << cmd;
     }
+    expandBufFree(pReply);
+  } else {
+    LOG(ERROR) << "reply?!";
+    DCHECK(false);
+  }
 
-    LOG(VERBOSE) << "----------";
+  LOG(VERBOSE) << "----------";
 
-    consumeBytes(netState, length);
-    return true;
+  consumeBytes(netState, length);
+  return true;
 }
 
 /*