changeset 5173:915cc4f3fb15

8020489: VM crash when non-existent interface called by invokespecial Reviewed-by: kamg, coleenp
author acorn
date Wed, 28 Aug 2013 08:15:01 -0400
parents c26d57fa08aa
children cc56f122f3f7 522d69638aa8
files src/share/vm/classfile/defaultMethods.cpp
diffstat 1 files changed, 33 insertions(+), 29 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/classfile/defaultMethods.cpp	Tue Aug 27 16:02:59 2013 -0400
+++ b/src/share/vm/classfile/defaultMethods.cpp	Wed Aug 28 08:15:01 2013 -0400
@@ -870,7 +870,6 @@
     : ShadowChecker(thread, name, holder, target) {}
 };
 
-
 // Find the unique qualified candidate from the perspective of the super_class
 // which is the resolved_klass, which must be an immediate superinterface
 // of klass
@@ -884,43 +883,48 @@
 
   if (family != NULL) {
     family->determine_target(current_class, CHECK_NULL);  // get target from current_class
-  }
 
-  if (family->has_target()) {
-    Method* target = family->get_selected_target();
-    InstanceKlass* holder = InstanceKlass::cast(target->method_holder());
+    if (family->has_target()) {
+      Method* target = family->get_selected_target();
+      InstanceKlass* holder = InstanceKlass::cast(target->method_holder());
 
-    // Verify that the identified method is valid from the context of
-    // the current class, which is the caller class for invokespecial
-    // link resolution, i.e. ensure there it is not shadowed.
-    // You can use invokespecial to disambiguate interface methods, but
-    // you can not use it to skip over an interface method that would shadow it.
-    ErasedShadowChecker checker(THREAD, target->name(), holder, super_class);
-    checker.run(current_class);
+      // Verify that the identified method is valid from the context of
+      // the current class, which is the caller class for invokespecial
+      // link resolution, i.e. ensure there it is not shadowed.
+      // You can use invokespecial to disambiguate interface methods, but
+      // you can not use it to skip over an interface method that would shadow it.
+      ErasedShadowChecker checker(THREAD, target->name(), holder, super_class);
+      checker.run(current_class);
 
-    if (checker.found_shadow()) {
+      if (checker.found_shadow()) {
 #ifndef PRODUCT
-      if (TraceDefaultMethods) {
-        tty->print_cr("    Only candidate found was shadowed.");
+        if (TraceDefaultMethods) {
+          tty->print_cr("    Only candidate found was shadowed.");
+        }
+#endif // ndef PRODUCT
+        THROW_MSG_(vmSymbols::java_lang_AbstractMethodError(),
+                   "Accessible default method not found", NULL);
+      } else {
+#ifndef PRODUCT
+        if (TraceDefaultMethods) {
+          family->print_sig_on(tty, target->signature(), 1);
+        }
+#endif // ndef PRODUCT
+        return target;
       }
-#endif // ndef PRODUCT
+    } else {
+      assert(family->throws_exception(), "must have target or throw");
       THROW_MSG_(vmSymbols::java_lang_AbstractMethodError(),
-                 "Accessible default method not found", NULL);
-    } else {
-#ifndef PRODUCT
-      if (TraceDefaultMethods) {
-        family->print_sig_on(tty, target->signature(), 1);
-      }
-#endif // ndef PRODUCT
-      return target;
-    }
+                 family->get_exception_message()->as_C_string(), NULL);
+   }
   } else {
-    assert(family->throws_exception(), "must have target or throw");
-    THROW_MSG_(vmSymbols::java_lang_AbstractMethodError(),
-               family->get_exception_message()->as_C_string(), NULL);
+    // no method found
+    ResourceMark rm(THREAD);
+    THROW_MSG_(vmSymbols::java_lang_NoSuchMethodError(),
+              Method::name_and_sig_as_C_string(current_class,
+                                               method_name, sig), NULL);
   }
 }
-
 // This is called during linktime when we find an invokespecial call that
 // refers to a direct superinterface.  It indicates that we should find the
 // default method in the hierarchy of that superinterface, and if that method