[10] RFR (S): 8196022: java.lang.VerifyError is thrown instead of java.lang.IllegalAccessError

Vladimir Ivanov vladimir.x.ivanov at oracle.com
Fri Jan 26 18:34:19 UTC 2018

Thanks for review, Paul.

> This is quite a subtle and confusing area. I believe you have the mapping correct with a cleaner correspondence between reflective exceptions and errors. +1

FTR I don't insist on pushing it into 10. The missing checks for corner 
cases in SystemDictionary::link_method_handle_constant() is covered 
later during down call, so the only risk is that JDK-8188145 [1] fix 
won't work for those corner cases, which is very low.

So, if anybody doesn't feel comfortable pushing it into 10, I'm fine 
with delaying the fix till 11.

> I am having a hard time understanding how a ClassNotFoundException can originate when resolving a member name from symbolic information (and when resolving in Java via a lookup Class objects are required).
> Perhaps it’s due to logic in SystemDictionary::handle_resolution_exception:

Yes, exactly. I had hard time proving 
SystemDictionary::handle_resolution_exception isn't called with 
throw_error = false during method/field resolution, so decided to play 
it safe and cover it on JVM side to avoid dealing with that on JDK side.

Best regards,
Vladimir Ivanov

[1] https://bugs.openjdk.java.net/browse/JDK-8188145

> Klass* SystemDictionary::handle_resolution_exception(Symbol* class_name,
>                                                       bool throw_error,
>                                                       Klass* klass, TRAPS) {
>      // If we have a pending exception we forward it to the caller, unless throw_error is true,
>      // in which case we have to check whether the pending exception is a ClassNotFoundException,
>      // and if so convert it to a NoClassDefFoundError
>      // And chain the original ClassNotFoundException
>      if (throw_error && PENDING_EXCEPTION->is_a(SystemDictionary::ClassNotFoundException_klass())) {
>        ResourceMark rm(THREAD);
>        assert(klass == NULL, "Should not have result with exception pending");
>        THROW_MSG_CAUSE_NULL(vmSymbols::java_lang_NoClassDefFoundError(), class_name->as_C_string(), e);
>      } else {
>        return NULL;
>      }
>    }
>    // Class not found, throw appropriate error or exception depending on value of throw_error
>    if (klass == NULL) {
>      ResourceMark rm(THREAD);
>      if (throw_error) {
>        THROW_MSG_NULL(vmSymbols::java_lang_NoClassDefFoundError(), class_name->as_C_string());
>      } else {
>        THROW_MSG_NULL(vmSymbols::java_lang_ClassNotFoundException(), class_name->as_C_string());
>      }
>    }
>    return klass;
> }
> Paul.
>> On Jan 25, 2018, at 4:49 PM, Vladimir Ivanov <vladimir.x.ivanov at oracle.com> wrote:
>> http://cr.openjdk.java.net/~vlivanov/8196022/webrev.00/index.html
>> https://bugs.openjdk.java.net/browse/JDK-8196022
>> It's a followup on JDK-8188145 [1] which fixed what exceptions are thrown. It (unexpectedly :-)) fixed inaccuracy there: MemberName resolution code on JDK side converted most of LinkageErrors into IllegalAccessErrors, but after JDK-8188145 [1] there's no upcall anymore when resolution fails, so exceptions are reported as is which is the right thing.
>> The fix cleans JDK part to behave the same way.
>> Also, fixed MethodHandles::resolve_MemberName() to handle corner cases when empty handle is returned, but no exception is thrown. An exception should be thrown in that case as it is in MHN_resolve_Mem.
>> As a simplifying change, converting ClassNotFoundException to NoClassDefFoundError was added to avoid dealing with it on JDK side.
>> Testing: hs-tier1, hs-tier2, vm.defmeth, jck-runtime-10, jdk/java/lang/invoke/, hotspot/runtime/invokedynamic/
>> Thanks!
>> Best regards,
>> Vladimir Ivanov
>> [1] https://bugs.openjdk.java.net/browse/JDK-8188145

More information about the hotspot-runtime-dev mailing list