OSDN Git Service

MethodHandles: Better detail message for WrongMethodTypeExceptions
authorNarayan Kamath <narayan@google.com>
Mon, 31 Oct 2016 13:55:55 +0000 (13:55 +0000)
committerNarayan Kamath <narayan@google.com>
Mon, 31 Oct 2016 14:10:53 +0000 (14:10 +0000)
We now include the type of the callee and the callsite.

This change also fixes a call to ThrowWrongMethodTypeException that
passed arguments in the wrong order.

Test: make test-art-host

Change-Id: I3ced2e331cb49b616a8374f5a604dafa37330059

runtime/common_throws.cc
runtime/interpreter/interpreter_common.cc
runtime/mirror/method_type.cc
runtime/mirror/method_type.h
test/956-methodhandles/expected.txt
test/956-methodhandles/src/Main.java

index 0251776..9f0dbbb 100644 (file)
@@ -813,13 +813,11 @@ void ThrowVerifyError(ObjPtr<mirror::Class> referrer, const char* fmt, ...) {
 
 void ThrowWrongMethodTypeException(mirror::MethodType* callee_type,
                                    mirror::MethodType* callsite_type) {
-  // TODO(narayan): Should we provide more detail here ? The RI doesn't bother.
-  UNUSED(callee_type);
-  UNUSED(callsite_type);
-
   ThrowException("Ljava/lang/invoke/WrongMethodTypeException;",
                  nullptr,
-                 "Invalid method type for signature polymorphic call");
+                 StringPrintf("Expected %s but was %s",
+                              callee_type->PrettyDescriptor().c_str(),
+                              callsite_type->PrettyDescriptor().c_str()).c_str());
 }
 
 }  // namespace art
index 179e48b..4fc92a3 100644 (file)
@@ -836,7 +836,7 @@ inline bool DoInvokePolymorphic(Thread* self,
   Handle<mirror::MethodType> handle_type(hs.NewHandle(method_handle->GetMethodType()));
   CHECK(handle_type.Get() != nullptr);
   if (UNLIKELY(is_invoke_exact && !callsite_type->IsExactMatch(handle_type.Get()))) {
-    ThrowWrongMethodTypeException(callsite_type.Get(), handle_type.Get());
+    ThrowWrongMethodTypeException(handle_type.Get(), callsite_type.Get());
     return false;
   }
 
index 0b52931..9b0f872 100644 (file)
@@ -65,6 +65,25 @@ bool MethodType::IsExactMatch(mirror::MethodType* other) REQUIRES_SHARED(Locks::
   return true;
 }
 
+std::string MethodType::PrettyDescriptor() REQUIRES_SHARED(Locks::mutator_lock_) {
+  std::ostringstream ss;
+  ss << "(";
+
+  mirror::ObjectArray<Class>* const p_types = GetPTypes();
+  const int32_t params_length = p_types->GetLength();
+  for (int32_t i = 0; i < params_length; ++i) {
+    ss << p_types->GetWithoutChecks(i)->PrettyDescriptor();
+    if (i != (params_length - 1)) {
+      ss << ", ";
+    }
+  }
+
+  ss << ")";
+  ss << GetRType()->PrettyDescriptor();
+
+  return ss.str();
+}
+
 void MethodType::SetClass(Class* klass) {
   CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass;
   CHECK(klass != nullptr);
index 5b50409..fa700b6 100644 (file)
@@ -56,6 +56,10 @@ class MANAGED MethodType : public Object {
   // iff. they have the same return types and parameter types.
   bool IsExactMatch(mirror::MethodType* other) REQUIRES_SHARED(Locks::mutator_lock_);
 
+  // Returns the pretty descriptor for this method type, suitable for display in
+  // exception messages and the like.
+  std::string PrettyDescriptor() REQUIRES_SHARED(Locks::mutator_lock_);
+
  private:
   static MemberOffset FormOffset() {
     return MemberOffset(OFFSETOF_MEMBER(MethodType, form_));
index ddc1cb0..ad1c43c 100644 (file)
@@ -3,3 +3,4 @@ foo_A
 foo_A
 foo_B
 privateRyan_D
+Received exception: Expected (java.lang.String, java.lang.String)java.lang.String but was (java.lang.String, java.lang.Object)void
index 2802dfa..72ed6b5 100644 (file)
@@ -57,6 +57,7 @@ public class Main {
   public static void main(String[] args) throws Throwable {
     testfindSpecial_invokeSuperBehaviour();
     testfindSpecial_invokeDirectBehaviour();
+    testExceptionDetailMessages();
   }
 
   public static void testfindSpecial_invokeSuperBehaviour() throws Throwable {
@@ -131,6 +132,18 @@ public class Main {
     } catch (IllegalAccessException expected) {
     }
   }
+
+  public static void testExceptionDetailMessages() throws Throwable {
+    MethodHandle handle = MethodHandles.lookup().findVirtual(String.class, "concat",
+        MethodType.methodType(String.class, String.class));
+
+    try {
+      handle.invokeExact("a", new Object());
+      System.out.println("invokeExact(\"a\", new Object()) unexpectedly succeeded.");
+    } catch (WrongMethodTypeException ex) {
+      System.out.println("Received exception: " + ex.getMessage());
+    }
+  }
 }