Fix/improve exception detail messages for unboxing.

This fixes libcore/luni/src/test/java/libcore/java/lang/reflect/MethodTest.java
failures.

Change-Id: Idf6aae169bd72f0534d4094170536e6b2515ca07
diff --git a/src/java_lang_reflect_Field.cc b/src/java_lang_reflect_Field.cc
index eb56edb..fc1ea4e 100644
--- a/src/java_lang_reflect_Field.cc
+++ b/src/java_lang_reflect_Field.cc
@@ -208,7 +208,7 @@
   // Unbox the value, if necessary.
   Object* boxed_value = Decode<Object*>(env, javaValue);
   JValue unboxed_value;
-  if (!UnboxPrimitive(env, boxed_value, FieldHelper(f).GetType(), unboxed_value)) {
+  if (!UnboxPrimitive(env, boxed_value, FieldHelper(f).GetType(), unboxed_value, "field")) {
     return;
   }
 
diff --git a/src/reflection.cc b/src/reflection.cc
index 46b2ff3..c317be0 100644
--- a/src/reflection.cc
+++ b/src/reflection.cc
@@ -91,7 +91,8 @@
     Object* arg = objects->Get(i);
     Class* dst_class = mh.GetClassFromTypeIdx(classes->GetTypeItem(i).type_idx_);
     if (dst_class->IsPrimitive()) {
-      if (!UnboxPrimitive(env, arg, dst_class, decoded_args[i])) {
+      std::string what(StringPrintf("argument %d", i + 1)); // Humans count from 1.
+      if (!UnboxPrimitive(env, arg, dst_class, decoded_args[i], what.c_str())) {
         return NULL;
       }
     } else {
@@ -119,16 +120,17 @@
 }
 
 bool VerifyObjectInClass(JNIEnv* env, Object* o, Class* c) {
+  const char* exception = NULL;
   if (o == NULL) {
-    jniThrowNullPointerException(env, "receiver for non-static field access was null");
-    return false;
+    exception = "java/lang/NullPointerException";
+  } else if (!o->InstanceOf(c)) {
+    exception = "java/lang/IllegalArgumentException";
   }
-  if (!o->InstanceOf(c)) {
-    std::string expectedClassName(PrettyDescriptor(c));
-    std::string actualClassName(PrettyTypeOf(o));
-    jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
-        "expected receiver of type %s, but got %s",
-        expectedClassName.c_str(), actualClassName.c_str());
+  if (exception != NULL) {
+    std::string expected_class_name(PrettyDescriptor(c));
+    std::string actual_class_name(PrettyTypeOf(o));
+    jniThrowExceptionFmt(env, exception, "expected receiver of type %s, but got %s",
+                         expected_class_name.c_str(), actual_class_name.c_str());
     return false;
   }
   return true;
@@ -281,26 +283,30 @@
   m->Invoke(self, NULL, args.get(), &value);
 }
 
-bool UnboxPrimitive(JNIEnv* env, Object* o, Class* dst_class, JValue& unboxed_value) {
+bool UnboxPrimitive(JNIEnv* env, Object* o, Class* dst_class, JValue& unboxed_value, const char* what) {
   if (!dst_class->IsPrimitive()) {
     if (o != NULL && !o->InstanceOf(dst_class)) {
-      jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
-          "expected object of type %s, but got %s",
-          PrettyDescriptor(dst_class).c_str(),
-          PrettyTypeOf(o).c_str());
+      Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalArgumentException;",
+                                            "boxed object for %s should have type %s, but got %s",
+                                            what,
+                                            PrettyDescriptor(dst_class).c_str(),
+                                            PrettyTypeOf(o).c_str());
       return false;
     }
     unboxed_value.l = o;
     return true;
   } else if (dst_class->GetPrimitiveType() == Primitive::kPrimVoid) {
-    Thread::Current()->ThrowNewException("Ljava/lang/IllegalArgumentException;",
-        "can't unbox to void");
+    Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalArgumentException;",
+                                          "can't unbox %s to void",
+                                          what);
     return false;
   }
 
   if (o == NULL) {
-    Thread::Current()->ThrowNewException("Ljava/lang/IllegalArgumentException;",
-        "null passed for boxed primitive type");
+    Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalArgumentException;",
+                                          "%s should have type %s, got null",
+                                          what,
+                                          PrettyDescriptor(dst_class).c_str());
     return false;
   }
 
@@ -335,7 +341,10 @@
     boxed_value.i = primitive_field->GetShort(o);  // and extend read value to 32bits
   } else {
     Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalArgumentException;",
-        "%s is not a boxed primitive type", PrettyDescriptor(src_descriptor.c_str()).c_str());
+                                          "%s should have type %s, got %s",
+                                          what,
+                                          PrettyDescriptor(dst_class).c_str(),
+                                          PrettyDescriptor(src_descriptor.c_str()).c_str());
     return false;
   }
 
diff --git a/src/reflection.h b/src/reflection.h
index e832c3d..a286a57 100644
--- a/src/reflection.h
+++ b/src/reflection.h
@@ -28,7 +28,7 @@
 
 void InitBoxingMethods();
 void BoxPrimitive(JNIEnv* env, Primitive::Type src_class, JValue& value);
-bool UnboxPrimitive(JNIEnv* env, Object* o, Class* dst_class, JValue& unboxed_value);
+bool UnboxPrimitive(JNIEnv* env, Object* o, Class* dst_class, JValue& unboxed_value, const char* what);
 
 bool ConvertPrimitiveValue(Primitive::Type src_class, Primitive::Type dst_class, const JValue& src, JValue& dst);
 
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index 8dc518e..f5edebf 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -1147,7 +1147,8 @@
     Object* result_ref = self->DecodeJObject(result);
     if (result_ref != NULL) {
       JValue result_unboxed;
-      UnboxPrimitive(env, result_ref, proxy_mh.GetReturnType(), result_unboxed);
+      bool unboxed_okay = UnboxPrimitive(env, result_ref, proxy_mh.GetReturnType(), result_unboxed, "result");
+      CHECK(unboxed_okay);
       *reinterpret_cast<JValue*>(stack_args) = result_unboxed;
     } else {
       *reinterpret_cast<jobject*>(stack_args) = NULL;