< prev index next >

src/share/vm/prims/methodHandles.cpp

Print this page
rev 11572 : 8161588: MemberName::resolveOrNull cause and hide NoSuchMethodErrors
Reviewed-by: mhaupt

@@ -637,11 +637,11 @@
 
 
 // An unresolved member name is a mere symbolic reference.
 // Resolving it plants a vmtarget/vmindex in it,
 // which refers directly to JVM internals.
-Handle MethodHandles::resolve_MemberName(Handle mname, KlassHandle caller, TRAPS) {
+Handle MethodHandles::resolve_MemberName(Handle mname, KlassHandle caller, bool clear_pending, TRAPS) {
   Handle empty;
   assert(java_lang_invoke_MemberName::is_instance(mname()), "");
 
   if (java_lang_invoke_MemberName::vmtarget(mname()) != NULL) {
     // Already resolved.

@@ -736,10 +736,11 @@
                         link_info, false, THREAD);
         } else {
           assert(false, "ref_kind=%d", ref_kind);
         }
         if (HAS_PENDING_EXCEPTION) {
+          if (clear_pending) CLEAR_PENDING_EXCEPTION;
           return empty;
         }
       }
       if (result.resolved_appendix().not_null()) {
         // The resolved MemberName must not be accompanied by an appendix argument,

@@ -760,10 +761,11 @@
           LinkResolver::resolve_special_call(result, link_info, THREAD);
         } else {
           break;                // will throw after end of switch
         }
         if (HAS_PENDING_EXCEPTION) {
+          if (clear_pending) CLEAR_PENDING_EXCEPTION;
           return empty;
         }
       }
       assert(result.is_statically_bound(), "");
       oop mname2 = init_method_MemberName(mname, result);

@@ -775,10 +777,11 @@
       {
         assert(!HAS_PENDING_EXCEPTION, "");
         LinkInfo link_info(defc, name, type, caller, LinkInfo::skip_access_check);
         LinkResolver::resolve_field(result, link_info, Bytecodes::_nop, false, THREAD);
         if (HAS_PENDING_EXCEPTION) {
+          if (clear_pending) CLEAR_PENDING_EXCEPTION;
           return empty;
         }
       }
       oop mname2 = init_field_MemberName(mname, result, ref_kind_is_setter(ref_kind));
       return Handle(THREAD, mname2);

@@ -1211,17 +1214,13 @@
   Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh));
   MethodHandles::expand_MemberName(mname, 0, CHECK);
 }
 JVM_END
 
-// void resolve(MemberName self, Class<?> caller)
-JVM_ENTRY(jobject, MHN_resolve_Mem(JNIEnv *env, jobject igcls, jobject mname_jh, jclass caller_jh)) {
-  if (mname_jh == NULL) { THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "mname is null"); }
-  Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh));
-
-  // The trusted Java code that calls this method should already have performed
-  // access checks on behalf of the given caller.  But, we can verify this.
+// The trusted Java code that calls this method should already have performed
+// access checks on behalf of the given caller.  But, we can verify this.
+static void verify_method_handle(Handle mname, jclass caller_jh, TRAPS) {
   if (VerifyMethodHandles && caller_jh != NULL &&
       java_lang_invoke_MemberName::clazz(mname()) != NULL) {
     Klass* reference_klass = java_lang_Class::as_Klass(java_lang_invoke_MemberName::clazz(mname()));
     if (reference_klass != NULL && reference_klass->is_objArray_klass()) {
       reference_klass = ObjArrayKlass::cast(reference_klass)->bottom_klass();

@@ -1232,19 +1231,27 @@
       // Emulate LinkResolver::check_klass_accessability.
       Klass* caller = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(caller_jh));
       if (Reflection::verify_class_access(caller,
                                           reference_klass,
                                           true) != Reflection::ACCESS_OK) {
-        THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), reference_klass->external_name());
+        THROW_MSG(vmSymbols::java_lang_InternalError(), reference_klass->external_name());
       }
     }
   }
+}
+
+// void resolve(MemberName self, Class<?> caller)
+JVM_ENTRY(jobject, MHN_resolve_Mem(JNIEnv *env, jobject igcls, jobject mname_jh, jclass caller_jh)) {
+  if (mname_jh == NULL) { THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "mname is null"); }
+  Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh));
+
+  verify_method_handle(mname, caller_jh, CHECK_NULL);
 
   KlassHandle caller(THREAD,
                      caller_jh == NULL ? (Klass*) NULL :
                      java_lang_Class::as_Klass(JNIHandles::resolve_non_null(caller_jh)));
-  Handle resolved = MethodHandles::resolve_MemberName(mname, caller, CHECK_NULL);
+  Handle resolved = MethodHandles::resolve_MemberName(mname, caller, /* !clear_pending */false, CHECK_NULL);
 
   if (resolved.is_null()) {
     int flags = java_lang_invoke_MemberName::flags(mname());
     int ref_kind = (flags >> REFERENCE_KIND_SHIFT) & REFERENCE_KIND_MASK;
     if (!MethodHandles::ref_kind_is_valid(ref_kind)) {

@@ -1262,10 +1269,26 @@
 
   return JNIHandles::make_local(THREAD, resolved());
 }
 JVM_END
 
+// void resolveOrNull(MemberName self, Class<?> caller)
+JVM_ENTRY(jobject, MHN_resolve_or_null_Mem(JNIEnv *env, jobject igcls, jobject mname_jh, jclass caller_jh)) {
+  if (mname_jh == NULL) { THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "mname is null"); }
+  Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh));
+
+  verify_method_handle(mname, caller_jh, CHECK_NULL);
+
+  KlassHandle caller(THREAD,
+                     caller_jh == NULL ? (Klass*) NULL :
+                     java_lang_Class::as_Klass(JNIHandles::resolve_non_null(caller_jh)));
+  Handle resolved = MethodHandles::resolve_MemberName(mname, caller, /* clear_pending */true, CHECK_NULL);
+
+  return JNIHandles::make_local(THREAD, resolved());
+}
+JVM_END
+
 static jlong find_member_field_offset(oop mname, bool must_be_static, TRAPS) {
   if (mname == NULL ||
       java_lang_invoke_MemberName::vmtarget(mname) == NULL) {
     THROW_MSG_0(vmSymbols::java_lang_InternalError(), "mname not resolved");
   } else {

@@ -1459,10 +1482,11 @@
 // These are the native methods on java.lang.invoke.MethodHandleNatives.
 static JNINativeMethod MHN_methods[] = {
   {CC "init",                      CC "(" MEM "" OBJ ")V",                   FN_PTR(MHN_init_Mem)},
   {CC "expand",                    CC "(" MEM ")V",                          FN_PTR(MHN_expand_Mem)},
   {CC "resolve",                   CC "(" MEM "" CLS ")" MEM,                FN_PTR(MHN_resolve_Mem)},
+  {CC "resolveOrNull",             CC "(" MEM "" CLS ")" MEM,                FN_PTR(MHN_resolve_or_null_Mem)},
   //  static native int getNamedCon(int which, Object[] name)
   {CC "getNamedCon",               CC "(I[" OBJ ")I",                        FN_PTR(MHN_getNamedCon)},
   //  static native int getMembers(Class<?> defc, String matchName, String matchSig,
   //          int matchFlags, Class<?> caller, int skip, MemberName[] results);
   {CC "getMembers",                CC "(" CLS "" STRG "" STRG "I" CLS "I[" MEM ")I", FN_PTR(MHN_getMembers)},
< prev index next >