More JDWP robustness.

We pass a lot more JDWP tests with this (fewer total failures than dalvik,
because although dalvik implements more requests, it assumes that the debuggers
only send it valid input).

I've also added some of the missing constants (there are tests of modifier 12,
SourceNameMatch, which was added in Java 6).

Change-Id: I502e87b50fb305c5c8b061421339c8ceab104640
diff --git a/jdwpspy/Net.cpp b/jdwpspy/Net.cpp
index 54d7730..eea21c8 100644
--- a/jdwpspy/Net.cpp
+++ b/jdwpspy/Net.cpp
@@ -230,7 +230,7 @@
 NetState* jdwpNetStartup(unsigned short listenPort, const char* connectHost,
     unsigned short connectPort)
 {
-    NetState* netState = (NetState*) malloc(sizeof(*netState));
+    NetState* netState = new NetState;
     memset(netState, 0, sizeof(*netState));
     netState->listenSock = -1;
     netState->dbg.sock = netState->vm.sock = -1;
@@ -342,7 +342,7 @@
         return;
 
     jdwpNetShutdown(netState);
-    free(netState);
+    delete netState;
 }
 
 /*
diff --git a/src/debugger.cc b/src/debugger.cc
index b2ea527..eede552 100644
--- a/src/debugger.cc
+++ b/src/debugger.cc
@@ -447,18 +447,29 @@
 }
 
 std::string Dbg::GetClassDescriptor(JDWP::RefTypeId classId) {
-  Class* c = gRegistry->Get<Class*>(classId);
-  return ClassHelper(c).GetDescriptor();
+  Object* o = gRegistry->Get<Object*>(classId);
+  if (o == NULL || !o->IsClass()) {
+    return StringPrintf("non-class %p", o); // This is only used for debugging output anyway.
+  }
+  return ClassHelper(o->AsClass()).GetDescriptor();
 }
 
-JDWP::ObjectId Dbg::GetClassObject(JDWP::RefTypeId id) {
-  UNIMPLEMENTED(FATAL);
-  return 0;
+bool Dbg::GetClassObject(JDWP::RefTypeId id, JDWP::ObjectId& classObjectId) {
+  Object* o = gRegistry->Get<Object*>(id);
+  if (o == NULL || !o->IsClass()) {
+    return false;
+  }
+  classObjectId = gRegistry->Add(o);
+  return true;
 }
 
-JDWP::RefTypeId Dbg::GetSuperclass(JDWP::RefTypeId id) {
-  Class* c = gRegistry->Get<Class*>(id);
-  return gRegistry->Add(c->GetSuperClass());
+bool Dbg::GetSuperclass(JDWP::RefTypeId id, JDWP::RefTypeId& superclassId) {
+  Object* o = gRegistry->Get<Object*>(id);
+  if (o == NULL || !o->IsClass()) {
+    return false;
+  }
+  superclassId = gRegistry->Add(o->AsClass()->GetSuperClass());
+  return true;
 }
 
 JDWP::ObjectId Dbg::GetClassLoader(JDWP::RefTypeId id) {
@@ -466,21 +477,32 @@
   return gRegistry->Add(o->GetClass()->GetClassLoader());
 }
 
-uint32_t Dbg::GetAccessFlags(JDWP::RefTypeId id) {
-  Class* c = gRegistry->Get<Class*>(id);
-  return c->GetAccessFlags() & kAccJavaFlagsMask;
+bool Dbg::GetAccessFlags(JDWP::RefTypeId id, uint32_t& access_flags) {
+  Object* o = gRegistry->Get<Object*>(id);
+  if (o == NULL || !o->IsClass()) {
+    return false;
+  }
+  access_flags = o->AsClass()->GetAccessFlags() & kAccJavaFlagsMask;
+  return true;
 }
 
-bool Dbg::IsInterface(JDWP::RefTypeId classId) {
-  Class* c = gRegistry->Get<Class*>(classId);
-  return c->IsInterface();
+bool Dbg::IsInterface(JDWP::RefTypeId classId, bool& is_interface) {
+  Object* o = gRegistry->Get<Object*>(classId);
+  if (o == NULL || !o->IsClass()) {
+    return false;
+  }
+  is_interface = o->AsClass()->IsInterface();
+  return true;
 }
 
-void Dbg::GetClassList(uint32_t* pClassCount, JDWP::RefTypeId** pClasses) {
+void Dbg::GetClassList(std::vector<JDWP::RefTypeId>& classes) {
   // Get the complete list of reference classes (i.e. all classes except
   // the primitive types).
   // Returns a newly-allocated buffer full of RefTypeId values.
   struct ClassListCreator {
+    ClassListCreator(std::vector<JDWP::RefTypeId>& classes) : classes(classes) {
+    }
+
     static bool Visit(Class* c, void* arg) {
       return reinterpret_cast<ClassListCreator*>(arg)->Visit(c);
     }
@@ -492,24 +514,24 @@
       return true;
     }
 
-    std::vector<JDWP::RefTypeId> classes;
+    std::vector<JDWP::RefTypeId>& classes;
   };
 
-  ClassListCreator clc;
+  ClassListCreator clc(classes);
   Runtime::Current()->GetClassLinker()->VisitClasses(ClassListCreator::Visit, &clc);
-  *pClassCount = clc.classes.size();
-  *pClasses = new JDWP::RefTypeId[clc.classes.size()];
-  for (size_t i = 0; i < clc.classes.size(); ++i) {
-    (*pClasses)[i] = clc.classes[i];
-  }
 }
 
 void Dbg::GetVisibleClassList(JDWP::ObjectId classLoaderId, uint32_t* pNumClasses, JDWP::RefTypeId** pClassRefBuf) {
   UNIMPLEMENTED(FATAL);
 }
 
-void Dbg::GetClassInfo(JDWP::RefTypeId classId, JDWP::JdwpTypeTag* pTypeTag, uint32_t* pStatus, std::string* pDescriptor) {
-  Class* c = gRegistry->Get<Class*>(classId);
+bool Dbg::GetClassInfo(JDWP::RefTypeId classId, JDWP::JdwpTypeTag* pTypeTag, uint32_t* pStatus, std::string* pDescriptor) {
+  Object* o = gRegistry->Get<Object*>(classId);
+  if (o == NULL || !o->IsClass()) {
+    return false;
+  }
+
+  Class* c = o->AsClass();
   if (c->IsArrayClass()) {
     *pStatus = JDWP::CS_VERIFIED | JDWP::CS_PREPARED;
     *pTypeTag = JDWP::TT_ARRAY;
@@ -525,9 +547,10 @@
   if (pDescriptor != NULL) {
     *pDescriptor = ClassHelper(c).GetDescriptor();
   }
+  return true;
 }
 
-void Dbg::FindLoadedClassBySignature(const char* descriptor, std::vector<JDWP::RefTypeId>& ids) {
+void Dbg::FindLoadedClassBySignature(const std::string& descriptor, std::vector<JDWP::RefTypeId>& ids) {
   std::vector<Class*> classes;
   Runtime::Current()->GetClassLinker()->LookupClasses(descriptor, classes);
   ids.clear();
@@ -553,17 +576,22 @@
   return 0;
 }
 
-std::string Dbg::GetSignature(JDWP::RefTypeId refTypeId) {
-  Class* c = gRegistry->Get<Class*>(refTypeId);
-  CHECK(c != NULL);
-  return ClassHelper(c).GetDescriptor();
+bool Dbg::GetSignature(JDWP::RefTypeId refTypeId, std::string& signature) {
+  Object* o = gRegistry->Get<Object*>(refTypeId);
+  if (o == NULL || !o->IsClass()) {
+    return false;
+  }
+  signature = ClassHelper(o->AsClass()).GetDescriptor();
+  return true;
 }
 
 bool Dbg::GetSourceFile(JDWP::RefTypeId refTypeId, std::string& result) {
-  Class* c = gRegistry->Get<Class*>(refTypeId);
-  CHECK(c != NULL);
-  result = ClassHelper(c).GetSourceFile();
-  return result == NULL;
+  Object* o = gRegistry->Get<Object*>(refTypeId);
+  if (o == NULL || !o->IsClass()) {
+    return false;
+  }
+  result = ClassHelper(o->AsClass()).GetSourceFile();
+  return result != NULL;
 }
 
 uint8_t Dbg::GetObjectTag(JDWP::ObjectId objectId) {
@@ -700,25 +728,33 @@
   return true;
 }
 
-JDWP::ObjectId Dbg::CreateString(const char* str) {
-  return gRegistry->Add(String::AllocFromModifiedUtf8(str));
+JDWP::ObjectId Dbg::CreateString(const std::string& str) {
+  return gRegistry->Add(String::AllocFromModifiedUtf8(str.c_str()));
 }
 
-JDWP::ObjectId Dbg::CreateObject(JDWP::RefTypeId classId) {
-  Class* c = gRegistry->Get<Class*>(classId);
-  return gRegistry->Add(c->AllocObject());
+bool Dbg::CreateObject(JDWP::RefTypeId classId, JDWP::ObjectId& new_object) {
+  Object* o = gRegistry->Get<Object*>(classId);
+  if (o == NULL || !o->IsClass()) {
+    return false;
+  }
+  new_object = gRegistry->Add(o->AsClass()->AllocObject());
+  return true;
 }
 
 /*
  * Used by Eclipse's "Display" view to evaluate "new byte[5]" to get "(byte[]) [0, 0, 0, 0, 0]".
  */
-JDWP::ObjectId Dbg::CreateArrayObject(JDWP::RefTypeId arrayTypeId, uint32_t length) {
-  Class* array_class = gRegistry->Get<Class*>(arrayTypeId);
-  CHECK(array_class->IsArrayClass()) << PrettyClass(array_class);
-  return gRegistry->Add(Array::Alloc(array_class, length));
+bool Dbg::CreateArrayObject(JDWP::RefTypeId arrayTypeId, uint32_t length, JDWP::ObjectId& new_array) {
+  Object* o = gRegistry->Get<Object*>(arrayTypeId);
+  if (o == NULL || !o->IsClass()) {
+    return false;
+  }
+  new_array = gRegistry->Add(Array::Alloc(o->AsClass(), length));
+  return true;
 }
 
 bool Dbg::MatchType(JDWP::RefTypeId instClassId, JDWP::RefTypeId classId) {
+  // TODO: error handling if the RefTypeIds aren't actually Class*s.
   return gRegistry->Get<Class*>(instClassId)->InstanceOf(gRegistry->Get<Class*>(classId));
 }
 
@@ -815,10 +851,13 @@
   return slot;
 }
 
-void Dbg::OutputDeclaredFields(JDWP::RefTypeId refTypeId, bool with_generic, JDWP::ExpandBuf* pReply) {
-  Class* c = gRegistry->Get<Class*>(refTypeId);
-  CHECK(c != NULL);
+bool Dbg::OutputDeclaredFields(JDWP::RefTypeId refTypeId, bool with_generic, JDWP::ExpandBuf* pReply) {
+  Object* o = gRegistry->Get<Object*>(refTypeId);
+  if (o == NULL || !o->IsClass()) {
+    return false;
+  }
 
+  Class* c = o->AsClass();
   size_t instance_field_count = c->NumInstanceFields();
   size_t static_field_count = c->NumStaticFields();
 
@@ -836,12 +875,16 @@
     }
     expandBufAdd4BE(pReply, MangleAccessFlags(f->GetAccessFlags()));
   }
+  return true;
 }
 
-void Dbg::OutputDeclaredMethods(JDWP::RefTypeId refTypeId, bool with_generic, JDWP::ExpandBuf* pReply) {
-  Class* c = gRegistry->Get<Class*>(refTypeId);
-  CHECK(c != NULL);
+bool Dbg::OutputDeclaredMethods(JDWP::RefTypeId refTypeId, bool with_generic, JDWP::ExpandBuf* pReply) {
+  Object* o = gRegistry->Get<Object*>(refTypeId);
+  if (o == NULL || !o->IsClass()) {
+    return false;
+  }
 
+  Class* c = o->AsClass();
   size_t direct_method_count = c->NumDirectMethods();
   size_t virtual_method_count = c->NumVirtualMethods();
 
@@ -859,17 +902,21 @@
     }
     expandBufAdd4BE(pReply, MangleAccessFlags(m->GetAccessFlags()));
   }
+  return true;
 }
 
-void Dbg::OutputDeclaredInterfaces(JDWP::RefTypeId refTypeId, JDWP::ExpandBuf* pReply) {
-  Class* c = gRegistry->Get<Class*>(refTypeId);
-  CHECK(c != NULL);
-  ClassHelper kh(c);
+bool Dbg::OutputDeclaredInterfaces(JDWP::RefTypeId refTypeId, JDWP::ExpandBuf* pReply) {
+  Object* o = gRegistry->Get<Object*>(refTypeId);
+  if (o == NULL || !o->IsClass()) {
+    return false;
+  }
+  ClassHelper kh(o->AsClass());
   size_t interface_count = kh.NumInterfaces();
   expandBufAdd4BE(pReply, interface_count);
   for (size_t i = 0; i < interface_count; ++i) {
     expandBufAddRefTypeId(pReply, gRegistry->Add(kh.GetInterface(i)));
   }
+  return true;
 }
 
 void Dbg::OutputLineTable(JDWP::RefTypeId refTypeId, JDWP::MethodId methodId, JDWP::ExpandBuf* pReply) {
@@ -1621,11 +1668,12 @@
 
   // Translate the method through the vtable, unless the debugger wants to suppress it.
   Method* m = pReq->method_;
+  LOG(VERBOSE) << "ExecuteMethod " << PrettyMethod(m);
   if ((pReq->options_ & JDWP::INVOKE_NONVIRTUAL) == 0 && pReq->receiver_ != NULL) {
     m = pReq->class_->FindVirtualMethodForVirtualOrInterface(pReq->method_);
+    LOG(VERBOSE) << "ExecuteMethod " << PrettyMethod(m);
   }
   CHECK(m != NULL);
-  LOG(VERBOSE) << "ExecuteMethod " << PrettyMethod(m);
 
   CHECK_EQ(sizeof(jvalue), sizeof(uint64_t));
 
diff --git a/src/debugger.h b/src/debugger.h
index 0798635..bcc5d79 100644
--- a/src/debugger.h
+++ b/src/debugger.h
@@ -37,7 +37,10 @@
  * Invoke-during-breakpoint support.
  */
 struct DebugInvokeReq {
-  DebugInvokeReq() : lock_("a DebugInvokeReq lock"), cond_("a DebugInvokeReq condition variable") {
+  DebugInvokeReq()
+      : invoke_needed_(false),
+        lock_("a DebugInvokeReq lock"),
+        cond_("a DebugInvokeReq condition variable") {
   }
 
   /* boolean; only set when we're in the tail end of an event handler */
@@ -126,18 +129,18 @@
    * Class, Object, Array
    */
   static std::string GetClassDescriptor(JDWP::RefTypeId id);
-  static JDWP::ObjectId GetClassObject(JDWP::RefTypeId id);
-  static JDWP::RefTypeId GetSuperclass(JDWP::RefTypeId id);
+  static bool GetClassObject(JDWP::RefTypeId id, JDWP::ObjectId& classObjectId);
+  static bool GetSuperclass(JDWP::RefTypeId id, JDWP::RefTypeId& superclassId);
   static JDWP::ObjectId GetClassLoader(JDWP::RefTypeId id);
-  static uint32_t GetAccessFlags(JDWP::RefTypeId id);
-  static bool IsInterface(JDWP::RefTypeId id);
-  static void GetClassList(uint32_t* pNumClasses, JDWP::RefTypeId** pClassRefBuf);
+  static bool GetAccessFlags(JDWP::RefTypeId id, uint32_t& access_flags);
+  static bool IsInterface(JDWP::RefTypeId classId, bool& is_interface);
+  static void GetClassList(std::vector<JDWP::RefTypeId>& classes);
   static void GetVisibleClassList(JDWP::ObjectId classLoaderId, uint32_t* pNumClasses, JDWP::RefTypeId** pClassRefBuf);
-  static void GetClassInfo(JDWP::RefTypeId classId, JDWP::JdwpTypeTag* pTypeTag, uint32_t* pStatus, std::string* pDescriptor);
-  static void FindLoadedClassBySignature(const char* descriptor, std::vector<JDWP::RefTypeId>& ids);
+  static bool GetClassInfo(JDWP::RefTypeId classId, JDWP::JdwpTypeTag* pTypeTag, uint32_t* pStatus, std::string* pDescriptor);
+  static void FindLoadedClassBySignature(const std::string& descriptor, std::vector<JDWP::RefTypeId>& ids);
   static void GetObjectType(JDWP::ObjectId objectId, JDWP::JdwpTypeTag* pRefTypeTag, JDWP::RefTypeId* pRefTypeId);
   static uint8_t GetClassObjectType(JDWP::RefTypeId refTypeId);
-  static std::string GetSignature(JDWP::RefTypeId refTypeId);
+  static bool GetSignature(JDWP::RefTypeId refTypeId, std::string& signature);
   static bool GetSourceFile(JDWP::RefTypeId refTypeId, std::string& source_file);
   static uint8_t GetObjectTag(JDWP::ObjectId objectId);
   static size_t GetTagWidth(JDWP::JdwpTag tag);
@@ -147,9 +150,9 @@
   static bool OutputArray(JDWP::ObjectId arrayId, int firstIndex, int count, JDWP::ExpandBuf* pReply);
   static bool SetArrayElements(JDWP::ObjectId arrayId, int firstIndex, int count, const uint8_t* buf);
 
-  static JDWP::ObjectId CreateString(const char* str);
-  static JDWP::ObjectId CreateObject(JDWP::RefTypeId classId);
-  static JDWP::ObjectId CreateArrayObject(JDWP::RefTypeId arrayTypeId, uint32_t length);
+  static JDWP::ObjectId CreateString(const std::string& str);
+  static bool CreateObject(JDWP::RefTypeId classId, JDWP::ObjectId& new_object);
+  static bool CreateArrayObject(JDWP::RefTypeId arrayTypeId, uint32_t length, JDWP::ObjectId& new_array);
 
   static bool MatchType(JDWP::RefTypeId instClassId, JDWP::RefTypeId classId);
 
@@ -157,9 +160,9 @@
    * Method and Field
    */
   static std::string GetMethodName(JDWP::RefTypeId refTypeId, JDWP::MethodId id);
-  static void OutputDeclaredFields(JDWP::RefTypeId refTypeId, bool withGeneric, JDWP::ExpandBuf* pReply);
-  static void OutputDeclaredMethods(JDWP::RefTypeId refTypeId, bool withGeneric, JDWP::ExpandBuf* pReply);
-  static void OutputDeclaredInterfaces(JDWP::RefTypeId refTypeId, JDWP::ExpandBuf* pReply);
+  static bool OutputDeclaredFields(JDWP::RefTypeId refTypeId, bool withGeneric, JDWP::ExpandBuf* pReply);
+  static bool OutputDeclaredMethods(JDWP::RefTypeId refTypeId, bool withGeneric, JDWP::ExpandBuf* pReply);
+  static bool OutputDeclaredInterfaces(JDWP::RefTypeId refTypeId, JDWP::ExpandBuf* pReply);
   static void OutputLineTable(JDWP::RefTypeId refTypeId, JDWP::MethodId methodId, JDWP::ExpandBuf* pReply);
   static void OutputVariableTable(JDWP::RefTypeId refTypeId, JDWP::MethodId id, bool withGeneric, JDWP::ExpandBuf* pReply);
 
diff --git a/src/hprof/hprof.cc b/src/hprof/hprof.cc
index d2134e0..8dadfdf 100644
--- a/src/hprof/hprof.cc
+++ b/src/hprof/hprof.cc
@@ -59,7 +59,7 @@
       current_heap_(HPROF_HEAP_DEFAULT),
       objects_in_segment_(0),
       direct_to_ddms_(0),
-      file_name_(NULL),
+      file_name_(outputFileName),
       file_data_ptr_(NULL),
       file_data_size_(0),
       mem_fp_(NULL),
@@ -76,7 +76,6 @@
   }
 
   direct_to_ddms_ = directToDdms;
-  file_name_ = strdup(outputFileName);
   mem_fp_ = fp;
   fd_ = fd;
 
@@ -535,11 +534,11 @@
   FlushCurrentRecord();
 
   // create a new Hprof for the start of the file (as opposed to this, which is the tail)
-  Hprof headCtx(file_name_, fd_, true, direct_to_ddms_);
+  Hprof headCtx(file_name_.c_str(), fd_, true, direct_to_ddms_);
   headCtx.classes_ = classes_;
   headCtx.strings_ = strings_;
 
-  LOG(INFO) << StringPrintf("hprof: dumping heap strings to \"%s\".", file_name_);
+  LOG(INFO) << StringPrintf("hprof: dumping heap strings to \"%s\".", file_name_.c_str());
   headCtx.DumpStrings();
   headCtx.DumpClasses();
 
@@ -575,9 +574,9 @@
         // continue to fail-handler below
       }
     } else {
-      outFd = open(file_name_, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+      outFd = open(file_name_.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0644);
       if (outFd < 0) {
-        LOG(ERROR) << StringPrintf("can't open %s: %s", headCtx.file_name_, strerror(errno));
+        LOG(ERROR) << StringPrintf("can't open %s: %s", headCtx.file_name_.c_str(), strerror(errno));
         // continue to fail-handler below
       }
     }
@@ -607,7 +606,6 @@
     fclose(mem_fp_);
   }
   free(current_record_.body_);
-  free(file_name_);
   free(file_data_ptr_);
 }
 
diff --git a/src/hprof/hprof.h b/src/hprof/hprof.h
index e999dce..7c1180e 100644
--- a/src/hprof/hprof.h
+++ b/src/hprof/hprof.h
@@ -212,7 +212,7 @@
   // Otherwise, "file_name_" must be valid, though if "fd" >= 0 it will
   // only be used for debug messages.
   bool direct_to_ddms_;
-  char* file_name_;
+  std::string file_name_;
   char* file_data_ptr_;   // for open_memstream
   size_t file_data_size_; // for open_memstream
   FILE *mem_fp_;
diff --git a/src/jdwp/jdwp_bits.h b/src/jdwp/jdwp_bits.h
index 344d2de9..5536c52 100644
--- a/src/jdwp/jdwp_bits.h
+++ b/src/jdwp/jdwp_bits.h
@@ -67,19 +67,15 @@
 }
 
 /*
- * Read a UTF-8 string into newly-allocated storage, and null-terminate it.
- *
- * Returns the string and its length.  (The latter is probably unnecessary
- * for the way we're using UTF8.)
+ * Reads a UTF-8 string into a std::string.
  */
-static inline char* ReadNewUtf8String(unsigned char const** ppSrc, size_t* pLength) {
+static inline std::string ReadNewUtf8String(unsigned char const** ppSrc) {
   uint32_t length = Read4BE(ppSrc);
-  char* buf = (char*) malloc(length+1);
-  memcpy(buf, *ppSrc, length);
-  buf[length] = '\0';
+  std::string s;
+  s.resize(length);
+  memcpy(&s[0], *ppSrc, length);
   (*ppSrc) += length;
-  *pLength = length;
-  return buf;
+  return s;
 }
 
 static inline void Append1BE(std::vector<uint8_t>& bytes, uint8_t value) {
diff --git a/src/jdwp/jdwp_constants.cc b/src/jdwp/jdwp_constants.cc
index 7110eed..ab4e841 100644
--- a/src/jdwp/jdwp_constants.cc
+++ b/src/jdwp/jdwp_constants.cc
@@ -40,6 +40,8 @@
     return "THREAD_NOT_SUSPENDED";
   case ERR_THREAD_SUSPENDED:
     return "THREAD_SUSPENDED";
+  case ERR_THREAD_NOT_ALIVE:
+    return "THREAD_NOT_ALIVE";
   case ERR_INVALID_OBJECT:
     return "INVALID_OBJEC";
   case ERR_INVALID_CLASS:
@@ -157,7 +159,7 @@
   case EK_EXCEPTION:          return "EXCEPTION";
   case EK_USER_DEFINED:       return "USER_DEFINED";
   case EK_THREAD_START:       return "THREAD_START";
-  /*case EK_THREAD_END:         return "THREAD_END";*/
+  case EK_THREAD_DEATH:       return "THREAD_DEATH";
   case EK_CLASS_PREPARE:      return "CLASS_PREPARE";
   case EK_CLASS_UNLOAD:       return "CLASS_UNLOAD";
   case EK_CLASS_LOAD:         return "CLASS_LOAD";
@@ -166,11 +168,14 @@
   case EK_EXCEPTION_CATCH:    return "EXCEPTION_CATCH";
   case EK_METHOD_ENTRY:       return "METHOD_ENTRY";
   case EK_METHOD_EXIT:        return "METHOD_EXIT";
-  case EK_VM_INIT:            return "VM_INIT";
+  case EK_METHOD_EXIT_WITH_RETURN_VALUE: return "METHOD_EXIT_WITH_RETURN_VALUE";
+  case EK_MONITOR_CONTENDED_ENTER:       return "MONITOR_CONTENDED_ENTER";
+  case EK_MONITOR_CONTENDED_ENTERED:     return "MONITOR_CONTENDED_ENTERED";
+  case EK_MONITOR_WAIT:       return "MONITOR_WAIT";
+  case EK_MONITOR_WAITED:     return "MONITOR_WAITED";
+  case EK_VM_START:           return "VM_START";
   case EK_VM_DEATH:           return "VM_DEATH";
   case EK_VM_DISCONNECTED:    return "VM_DISCONNECTED";
-  /*case EK_VM_START:           return "VM_START";*/
-  case EK_THREAD_DEATH:       return "THREAD_DEATH";
   default:                    return "?UNKNOWN?";
   }
 }
@@ -179,24 +184,24 @@
   return os;
 }
 
-const char* ModKindStr(JdwpModKind kind) {
-  switch (kind) {
-  case MK_COUNT:              return "COUNT";
-  case MK_CONDITIONAL:        return "CONDITIONAL";
-  case MK_THREAD_ONLY:        return "THREAD_ONLY";
-  case MK_CLASS_ONLY:         return "CLASS_ONLY";
-  case MK_CLASS_MATCH:        return "CLASS_MATCH";
-  case MK_CLASS_EXCLUDE:      return "CLASS_EXCLUDE";
-  case MK_LOCATION_ONLY:      return "LOCATION_ONLY";
-  case MK_EXCEPTION_ONLY:     return "EXCEPTION_ONLY";
-  case MK_FIELD_ONLY:         return "FIELD_ONLY";
-  case MK_STEP:               return "STEP";
-  case MK_INSTANCE_ONLY:      return "INSTANCE_ONLY";
-  default:                    return "?UNKNOWN?";
-  }
-}
 std::ostream& operator<<(std::ostream& os, const JdwpModKind& value) {
-  os << ModKindStr(value);
+  switch (value) {
+  case MK_COUNT:             os << "COUNT"; break;
+  case MK_CONDITIONAL:       os << "CONDITIONAL"; break;
+  case MK_THREAD_ONLY:       os << "THREAD_ONLY"; break;
+  case MK_CLASS_ONLY:        os << "CLASS_ONLY"; break;
+  case MK_CLASS_MATCH:       os << "CLASS_MATCH"; break;
+  case MK_CLASS_EXCLUDE:     os << "CLASS_EXCLUDE"; break;
+  case MK_LOCATION_ONLY:     os << "LOCATION_ONLY"; break;
+  case MK_EXCEPTION_ONLY:    os << "EXCEPTION_ONLY"; break;
+  case MK_FIELD_ONLY:        os << "FIELD_ONLY"; break;
+  case MK_STEP:              os << "STEP"; break;
+  case MK_INSTANCE_ONLY:     os << "INSTANCE_ONLY"; break;
+  case MK_SOURCE_NAME_MATCH: os << "SOURCE_NAME_MATCH"; break;
+  default:
+    os << "JdwpModKind[" << static_cast<int>(value) << "]";
+    break;
+  }
   return os;
 }
 
diff --git a/src/jdwp/jdwp_constants.h b/src/jdwp/jdwp_constants.h
index 6d550f2..14dc6cf 100644
--- a/src/jdwp/jdwp_constants.h
+++ b/src/jdwp/jdwp_constants.h
@@ -35,6 +35,7 @@
   ERR_INVALID_PRIORITY                            = 12,
   ERR_THREAD_NOT_SUSPENDED                        = 13,
   ERR_THREAD_SUSPENDED                            = 14,
+  ERR_THREAD_NOT_ALIVE                            = 15,
   ERR_INVALID_OBJECT                              = 20,
   ERR_INVALID_CLASS                               = 21,
   ERR_CLASS_NOT_PREPARED                          = 22,
@@ -110,7 +111,7 @@
   EK_EXCEPTION            = 4,
   EK_USER_DEFINED         = 5,
   EK_THREAD_START         = 6,
-  EK_THREAD_END           = 7,
+  EK_THREAD_DEATH         = 7, // Formerly known as THREAD_END.
   EK_CLASS_PREPARE        = 8,
   EK_CLASS_UNLOAD         = 9,
   EK_CLASS_LOAD           = 10,
@@ -119,11 +120,14 @@
   EK_EXCEPTION_CATCH      = 30,
   EK_METHOD_ENTRY         = 40,
   EK_METHOD_EXIT          = 41,
-  EK_VM_INIT              = 90,
+  EK_METHOD_EXIT_WITH_RETURN_VALUE = 42,
+  EK_MONITOR_CONTENDED_ENTER       = 43,
+  EK_MONITOR_CONTENDED_ENTERED     = 44,
+  EK_MONITOR_WAIT         = 45,
+  EK_MONITOR_WAITED       = 46,
+  EK_VM_START             = 90, // Formerly known as VM_INIT.
   EK_VM_DEATH             = 99,
-  EK_VM_DISCONNECTED      = 100,  /* "Never sent across JDWP */
-  EK_VM_START             = EK_VM_INIT,
-  EK_THREAD_DEATH         = EK_THREAD_END,
+  EK_VM_DISCONNECTED      = 100, // "Never sent across JDWP".
 };
 std::ostream& operator<<(std::ostream& os, const JdwpEventKind& value);
 
@@ -142,6 +146,7 @@
   MK_FIELD_ONLY           = 9,
   MK_STEP                 = 10,
   MK_INSTANCE_ONLY        = 11,
+  MK_SOURCE_NAME_MATCH    = 12, // Since Java 6.
 };
 std::ostream& operator<<(std::ostream& os, const JdwpModKind& value);
 
diff --git a/src/jdwp/jdwp_event.cc b/src/jdwp/jdwp_event.cc
index 22d3c24..a405c9b 100644
--- a/src/jdwp/jdwp_event.cc
+++ b/src/jdwp/jdwp_event.cc
@@ -128,7 +128,7 @@
 
   for (int i = 0; i < pEvent->modCount; i++) {
     const JdwpEventMod* pMod = &pEvent->mods[i];
-    LOG(INFO) << "  " << static_cast<JdwpModKind>(pMod->modKind);
+    LOG(INFO) << "  " << pMod->modKind;
     /* TODO - show details */
   }
 }
@@ -451,8 +451,7 @@
       }
       break;
     default:
-      LOG(ERROR) << "unhandled mod kind " << pMod->modKind;
-      CHECK(false);
+      LOG(FATAL) << "unknown mod kind " << pMod->modKind;
       break;
     }
   }
@@ -544,7 +543,6 @@
     SetWaitForEventThread(Dbg::GetThreadSelfId());
 
     /* leave pReq->invoke_needed_ raised so we can check reentrancy */
-    LOG(VERBOSE) << "invoking method...";
     Dbg::ExecuteMethod(pReq);
 
     pReq->error = ERR_NONE;
diff --git a/src/jdwp/jdwp_event.h b/src/jdwp/jdwp_event.h
index 5f18595..e8f633f 100644
--- a/src/jdwp/jdwp_event.h
+++ b/src/jdwp/jdwp_event.h
@@ -30,54 +30,54 @@
  * Event modifiers.  A JdwpEvent may have zero or more of these.
  */
 union JdwpEventMod {
-  uint8_t      modKind;                /* JdwpModKind */
+  JdwpModKind modKind;
   struct {
-    uint8_t          modKind;
+    JdwpModKind modKind;
     int         count;
   } count;
   struct {
-    uint8_t          modKind;
+    JdwpModKind modKind;
     uint32_t          exprId;
   } conditional;
   struct {
-    uint8_t          modKind;
+    JdwpModKind modKind;
     ObjectId    threadId;
   } threadOnly;
   struct {
-    uint8_t          modKind;
+    JdwpModKind modKind;
     RefTypeId   refTypeId;
   } classOnly;
   struct {
-    uint8_t          modKind;
+    JdwpModKind modKind;
     char*       classPattern;
   } classMatch;
   struct {
-    uint8_t          modKind;
+    JdwpModKind modKind;
     char*       classPattern;
   } classExclude;
   struct {
-    uint8_t          modKind;
+    JdwpModKind modKind;
     JdwpLocation loc;
   } locationOnly;
   struct {
-    uint8_t          modKind;
+    JdwpModKind modKind;
     uint8_t          caught;
     uint8_t          uncaught;
     RefTypeId   refTypeId;
   } exceptionOnly;
   struct {
-    uint8_t          modKind;
+    JdwpModKind modKind;
     RefTypeId   refTypeId;
     FieldId     fieldId;
   } fieldOnly;
   struct {
-    uint8_t          modKind;
+    JdwpModKind modKind;
     ObjectId    threadId;
     int         size;           /* JdwpStepSize */
     int         depth;          /* JdwpStepDepth */
   } step;
   struct {
-    uint8_t          modKind;
+    JdwpModKind modKind;
     ObjectId    objectId;
   } instanceOnly;
 };
diff --git a/src/jdwp/jdwp_handler.cc b/src/jdwp/jdwp_handler.cc
index a11c805..9f23af1 100644
--- a/src/jdwp/jdwp_handler.cc
+++ b/src/jdwp/jdwp_handler.cc
@@ -194,8 +194,7 @@
  * been loaded by multiple class loaders.
  */
 static JdwpError handleVM_ClassesBySignature(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
-  size_t strLen;
-  char* classDescriptor = ReadNewUtf8String(&buf, &strLen);
+  std::string classDescriptor(ReadNewUtf8String(&buf));
   LOG(VERBOSE) << "  Req for class by signature '" << classDescriptor << "'";
 
   std::vector<RefTypeId> ids;
@@ -207,15 +206,15 @@
     // Get class vs. interface and status flags.
     JDWP::JdwpTypeTag typeTag;
     uint32_t status;
-    Dbg::GetClassInfo(ids[i], &typeTag, &status, NULL);
+    if (!Dbg::GetClassInfo(ids[i], &typeTag, &status, NULL)) {
+      return ERR_INVALID_CLASS;
+    }
 
     expandBufAdd1(pReply, typeTag);
     expandBufAddRefTypeId(pReply, ids[i]);
     expandBufAdd4BE(pReply, status);
   }
 
-  free(classDescriptor);
-
   return ERR_NONE;
 }
 
@@ -324,16 +323,12 @@
  * string "java.util.Arrays".)
  */
 static JdwpError handleVM_CreateString(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
-  size_t strLen;
-  char* str = ReadNewUtf8String(&buf, &strLen);
-
+  std::string str(ReadNewUtf8String(&buf));
   LOG(VERBOSE) << "  Req to create string '" << str << "'";
-
   ObjectId stringId = Dbg::CreateString(str);
   if (stringId == 0) {
     return ERR_OUT_OF_MEMORY;
   }
-
   expandBufAddObjectId(pReply, stringId);
   return ERR_NONE;
 }
@@ -425,30 +420,27 @@
  * Cough up the complete list of classes.
  */
 static JdwpError handleVM_AllClassesWithGeneric(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
-  uint32_t numClasses = 0;
-  RefTypeId* classRefBuf = NULL;
+  std::vector<JDWP::RefTypeId> classes;
+  Dbg::GetClassList(classes);
 
-  Dbg::GetClassList(&numClasses, &classRefBuf);
+  expandBufAdd4BE(pReply, classes.size());
 
-  expandBufAdd4BE(pReply, numClasses);
-
-  for (uint32_t i = 0; i < numClasses; i++) {
+  for (size_t i = 0; i < classes.size(); ++i) {
     static const char genericSignature[1] = "";
     JDWP::JdwpTypeTag refTypeTag;
     std::string descriptor;
     uint32_t status;
-
-    Dbg::GetClassInfo(classRefBuf[i], &refTypeTag, &status, &descriptor);
+    if (!Dbg::GetClassInfo(classes[i], &refTypeTag, &status, &descriptor)) {
+      return ERR_INVALID_CLASS;
+    }
 
     expandBufAdd1(pReply, refTypeTag);
-    expandBufAddRefTypeId(pReply, classRefBuf[i]);
+    expandBufAddRefTypeId(pReply, classes[i]);
     expandBufAddUtf8String(pReply, descriptor);
     expandBufAddUtf8String(pReply, genericSignature);
     expandBufAdd4BE(pReply, status);
   }
 
-  free(classRefBuf);
-
   return ERR_NONE;
 }
 
@@ -460,9 +452,11 @@
   RefTypeId refTypeId = ReadRefTypeId(&buf);
 
   LOG(VERBOSE) << StringPrintf("  Req for signature of refTypeId=0x%llx", refTypeId);
-  std::string signature(Dbg::GetSignature(refTypeId));
+  std::string signature;
+  if (!Dbg::GetSignature(refTypeId, signature)) {
+    return ERR_INVALID_CLASS;
+  }
   expandBufAddUtf8String(pReply, signature);
-
   return ERR_NONE;
 }
 
@@ -471,8 +465,11 @@
  */
 static JdwpError handleRT_Modifiers(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
   RefTypeId refTypeId = ReadRefTypeId(&buf);
-  uint32_t modBits = Dbg::GetAccessFlags(refTypeId);
-  expandBufAdd4BE(pReply, modBits);
+  uint32_t access_flags;
+  if (!Dbg::GetAccessFlags(refTypeId, access_flags)) {
+    return ERR_INVALID_CLASS;
+  }
+  expandBufAdd4BE(pReply, access_flags);
   return ERR_NONE;
 }
 
@@ -512,11 +509,11 @@
  */
 static JdwpError handleRT_Status(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
   RefTypeId refTypeId = ReadRefTypeId(&buf);
-
-  /* get status flags */
   JDWP::JdwpTypeTag typeTag;
   uint32_t status;
-  Dbg::GetClassInfo(refTypeId, &typeTag, &status, NULL);
+  if (!Dbg::GetClassInfo(refTypeId, &typeTag, &status, NULL)) {
+    return ERR_INVALID_CLASS;
+  }
   expandBufAdd4BE(pReply, status);
   return ERR_NONE;
 }
@@ -526,12 +523,8 @@
  */
 static JdwpError handleRT_Interfaces(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
   RefTypeId refTypeId = ReadRefTypeId(&buf);
-
   LOG(VERBOSE) << StringPrintf("  Req for interfaces in %llx (%s)", refTypeId, Dbg::GetClassDescriptor(refTypeId).c_str());
-
-  Dbg::OutputDeclaredInterfaces(refTypeId, pReply);
-
-  return ERR_NONE;
+  return Dbg::OutputDeclaredInterfaces(refTypeId, pReply) ? ERR_NONE : ERR_INVALID_CLASS;
 }
 
 /*
@@ -539,12 +532,12 @@
  */
 static JdwpError handleRT_ClassObject(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
   RefTypeId refTypeId = ReadRefTypeId(&buf);
-  ObjectId classObjId = Dbg::GetClassObject(refTypeId);
-
-  LOG(VERBOSE) << StringPrintf("  RefTypeId %llx -> ObjectId %llx", refTypeId, classObjId);
-
-  expandBufAddObjectId(pReply, classObjId);
-
+  ObjectId classObjectId;
+  if (!Dbg::GetClassObject(refTypeId, classObjectId)) {
+    return ERR_INVALID_CLASS;
+  }
+  LOG(VERBOSE) << StringPrintf("  RefTypeId %llx -> ObjectId %llx", refTypeId, classObjectId);
+  expandBufAddObjectId(pReply, classObjectId);
   return ERR_NONE;
 }
 
@@ -567,8 +560,8 @@
   RefTypeId refTypeId = ReadRefTypeId(&buf);
 
   LOG(VERBOSE) << StringPrintf("  Req for signature of refTypeId=0x%llx", refTypeId);
-  std::string signature(Dbg::GetSignature(refTypeId));
-  if (signature != NULL) {
+  std::string signature;
+  if (Dbg::GetSignature(refTypeId, signature)) {
     expandBufAddUtf8String(pReply, signature);
   } else {
     LOG(WARNING) << StringPrintf("No signature for refTypeId=0x%llx", refTypeId);
@@ -591,16 +584,27 @@
   return ERR_NONE;
 }
 
+static std::string Describe(const RefTypeId& refTypeId) {
+  std::string signature("unknown");
+  Dbg::GetSignature(refTypeId, signature);
+  return StringPrintf("refTypeId=0x%llx (%s)", refTypeId, signature.c_str());
+}
+
 /*
  * Given a referenceTypeId, return a block of stuff that describes the
  * fields declared by a class.
  */
 static JdwpError handleRT_FieldsWithGeneric(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
   RefTypeId refTypeId = ReadRefTypeId(&buf);
-  LOG(VERBOSE) << StringPrintf("  Req for fields in refTypeId=0x%llx", refTypeId);
-  LOG(VERBOSE) << StringPrintf("  --> '%s'", Dbg::GetSignature(refTypeId).c_str());
-  Dbg::OutputDeclaredFields(refTypeId, true, pReply);
-  return ERR_NONE;
+  LOG(VERBOSE) << "  Req for fields in " << Describe(refTypeId);
+  return Dbg::OutputDeclaredFields(refTypeId, true, pReply) ? ERR_NONE : ERR_INVALID_CLASS;
+}
+
+// Obsolete equivalent of FieldsWithGeneric, without the generic type information.
+static JdwpError handleRT_Fields(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
+  RefTypeId refTypeId = ReadRefTypeId(&buf);
+  LOG(VERBOSE) << "  Req for fields in " << Describe(refTypeId);
+  return Dbg::OutputDeclaredFields(refTypeId, false, pReply) ? ERR_NONE : ERR_INVALID_CLASS;
 }
 
 /*
@@ -609,13 +613,15 @@
  */
 static JdwpError handleRT_MethodsWithGeneric(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
   RefTypeId refTypeId = ReadRefTypeId(&buf);
+  LOG(VERBOSE) << "  Req for methods in " << Describe(refTypeId);
+  return Dbg::OutputDeclaredMethods(refTypeId, true, pReply) ? ERR_NONE : ERR_INVALID_CLASS;
+}
 
-  LOG(VERBOSE) << StringPrintf("  Req for methods in refTypeId=0x%llx", refTypeId);
-  LOG(VERBOSE) << StringPrintf("  --> '%s'", Dbg::GetSignature(refTypeId).c_str());
-
-  Dbg::OutputDeclaredMethods(refTypeId, true, pReply);
-
-  return ERR_NONE;
+// Obsolete equivalent of MethodsWithGeneric, without the generic type information.
+static JdwpError handleRT_Methods(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
+  RefTypeId refTypeId = ReadRefTypeId(&buf);
+  LOG(VERBOSE) << "  Req for methods in " << Describe(refTypeId);
+  return Dbg::OutputDeclaredMethods(refTypeId, false, pReply) ? ERR_NONE : ERR_INVALID_CLASS;
 }
 
 /*
@@ -623,11 +629,11 @@
  */
 static JdwpError handleCT_Superclass(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
   RefTypeId classId = ReadRefTypeId(&buf);
-
-  RefTypeId superClassId = Dbg::GetSuperclass(classId);
-
+  RefTypeId superClassId;
+  if (!Dbg::GetSuperclass(classId, superClassId)) {
+    return ERR_INVALID_CLASS;
+  }
   expandBufAddRefTypeId(pReply, superClassId);
-
   return ERR_NONE;
 }
 
@@ -680,7 +686,10 @@
   MethodId methodId = ReadMethodId(&buf);
 
   LOG(VERBOSE) << "Creating instance of " << Dbg::GetClassDescriptor(classId);
-  ObjectId objectId = Dbg::CreateObject(classId);
+  ObjectId objectId;
+  if (!Dbg::CreateObject(classId, objectId)) {
+    return ERR_INVALID_CLASS;
+  }
   if (objectId == 0) {
     return ERR_OUT_OF_MEMORY;
   }
@@ -695,7 +704,10 @@
   uint32_t length = Read4BE(&buf);
 
   LOG(VERBOSE) << StringPrintf("Creating array %s[%u]", Dbg::GetClassDescriptor(arrayTypeId).c_str(), length);
-  ObjectId objectId = Dbg::CreateArrayObject(arrayTypeId, length);
+  ObjectId objectId;
+  if (!Dbg::CreateArrayObject(arrayTypeId, length, objectId)) {
+    return ERR_INVALID_CLASS;
+  }
   if (objectId == 0) {
     return ERR_OUT_OF_MEMORY;
   }
@@ -860,7 +872,7 @@
   ObjectId stringObject = ReadObjectId(&buf);
   std::string str(Dbg::StringToUtf8(stringObject));
 
-  LOG(VERBOSE) << StringPrintf("  Req for str %llx --> '%s'", stringObject, str.c_str());
+  LOG(VERBOSE) << StringPrintf("  Req for str %llx --> '%s'", stringObject, PrintableString(str).c_str());
 
   expandBufAddUtf8String(pReply, str);
 
@@ -1248,7 +1260,7 @@
    * mods in JDWP doc).
    */
   for (uint32_t idx = 0; idx < modifierCount; idx++) {
-    uint8_t modKind = Read1(&buf);
+    JdwpModKind modKind = static_cast<JdwpModKind>(Read1(&buf));
 
     pEvent->mods[idx].modKind = modKind;
 
@@ -1286,25 +1298,17 @@
       break;
     case MK_CLASS_MATCH:    /* restrict events to matching classes */
       {
-        char* pattern;
-        size_t strLen;
-
-        pattern = ReadNewUtf8String(&buf, &strLen);
-        LOG(VERBOSE) << StringPrintf("    ClassMatch: '%s'", pattern);
+        std::string pattern(ReadNewUtf8String(&buf));
+        LOG(VERBOSE) << StringPrintf("    ClassMatch: '%s'", pattern.c_str());
         /* pattern is "java.foo.*", we want "java/foo/ *" */
-        pEvent->mods[idx].classMatch.classPattern = dvmDotToSlash(pattern);
-        free(pattern);
+        pEvent->mods[idx].classMatch.classPattern = dvmDotToSlash(pattern.c_str());
       }
       break;
     case MK_CLASS_EXCLUDE:  /* restrict events to non-matching classes */
       {
-        char* pattern;
-        size_t strLen;
-
-        pattern = ReadNewUtf8String(&buf, &strLen);
-        LOG(VERBOSE) << StringPrintf("    ClassExclude: '%s'", pattern);
-        pEvent->mods[idx].classExclude.classPattern = dvmDotToSlash(pattern);
-        free(pattern);
+        std::string pattern(ReadNewUtf8String(&buf));
+        LOG(VERBOSE) << StringPrintf("    ClassExclude: '%s'", pattern.c_str());
+        pEvent->mods[idx].classExclude.classPattern = dvmDotToSlash(pattern.c_str());
       }
       break;
     case MK_LOCATION_ONLY:  /* restrict certain events based on loc */
@@ -1496,12 +1500,12 @@
 
   LOG(VERBOSE) << StringPrintf("  Req for refTypeId for class=%llx (%s)", classObjectId, Dbg::GetClassDescriptor(classObjectId).c_str());
 
-  /* just hand the type back to them */
-  if (Dbg::IsInterface(classObjectId)) {
-    expandBufAdd1(pReply, TT_INTERFACE);
-  } else {
-    expandBufAdd1(pReply, TT_CLASS);
+  bool is_interface;
+  if (!Dbg::IsInterface(classObjectId, is_interface)) {
+    return ERR_INVALID_CLASS;
   }
+
+  expandBufAdd1(pReply, is_interface ? TT_INTERFACE : TT_CLASS);
   expandBufAddRefTypeId(pReply, classObjectId);
 
   return ERR_NONE;
@@ -1587,8 +1591,8 @@
   { 2,    1,  handleRT_Signature,     "ReferenceType.Signature" },
   { 2,    2,  handleRT_ClassLoader,   "ReferenceType.ClassLoader" },
   { 2,    3,  handleRT_Modifiers,     "ReferenceType.Modifiers" },
-  { 2,    4,  NULL, "ReferenceType.Fields" },
-  { 2,    5,  NULL, "ReferenceType.Methods" },
+  { 2,    4,  handleRT_Fields,        "ReferenceType.Fields" },
+  { 2,    5,  handleRT_Methods,       "ReferenceType.Methods" },
   { 2,    6,  handleRT_GetValues,     "ReferenceType.GetValues" },
   { 2,    7,  handleRT_SourceFile,    "ReferenceType.SourceFile" },
   { 2,    8,  NULL, "ReferenceType.NestedTypes" },
diff --git a/src/object.h b/src/object.h
index ddba9db..eb37987 100644
--- a/src/object.h
+++ b/src/object.h
@@ -1370,7 +1370,7 @@
   Class* GetSuperClass() const {
     // Can only get super class for loaded classes (hack for when runtime is
     // initializing)
-    DCHECK(IsLoaded() || !Runtime::Current()->IsStarted());
+    DCHECK(IsLoaded() || !Runtime::Current()->IsStarted()) << IsLoaded();
     return GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(Class, super_class_), false);
   }
 
@@ -1908,8 +1908,8 @@
 
 inline Class* Method::GetDeclaringClass() const {
   Class* result = GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(Method, declaring_class_), false);
-  DCHECK(result != NULL);
-  DCHECK(result->IsIdxLoaded() || result->IsErroneous());
+  DCHECK(result != NULL) << this;
+  DCHECK(result->IsIdxLoaded() || result->IsErroneous()) << this;
   return result;
 }