RFR (S): 8196022: java.lang.VerifyError is thrown instead of java.lang.IllegalAccessError
david.holmes at oracle.com
Sun Jan 28 21:42:48 UTC 2018
On 27/01/2018 5:10 PM, Vladimir Ivanov wrote:
> Thanks for looking into it, David!
> On 1/26/18 10:33 PM, David Holmes wrote:
>> Hi Vladimir,
>> On 26/01/2018 10:49 AM, Vladimir Ivanov wrote:
>>> It's a followup on JDK-8188145  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  there's no upcall
>>> anymore when resolution fails, so exceptions are reported as is which
>>> is the right thing.
>> The "right thing" is determined by the spec. If we've been doing the
>> "wrong thing" all this time then that is a problem and the fix may be
>> to the spec rather than the code. Can you clarify please what part of
>> the spec we are following here such that we know what exceptions
>> should be thrown, from where? If these are calls from Java MH code
>> then we need to examine the specs for those methods too.
> I'm reading JVMS-184.108.40.206 . It states the following:
> "Each method handle resolved by the Java Virtual Machine has an
> equivalent instruction sequence called its bytecode behavior, indicated
> by the method handle's kind."
> So, by the "right thing" I mean aligning behavior with equivalent
> bytecode behavior.
> Before JDK-8188145 , CONSTANT_MethodHandle resolution reported
> IllegalAccessError while equivalent bytecode behavior threw VerifyError.
Okay. I'm quite concerned that 8188145 has been fixed so late in the JDK
10 release cycle. Aligning the implementation with the spec is generally
the intention, but you have to evaluate the impact of the change in
behaviour. How long have we been doing the wrong thing? How much code
might depend on us doing the wrong thing? This could have unexpected
consequences - as per the current issue!
>>> The fix cleans JDK part to behave the same way.
>> I'm unclear how this fix changes the JDK side. Is it because it
>> tranforms LinkageErrors, and you no longer allow LinkageErrors to pass
>> through? (Does that make the JDK code "dead"?).
> Almost, but there are some important checks on JDK side which can fail
> (e.g., see MemberName.Factory.resolve() ). So, I decided to leave
> them as is for now.
This is unclear. Have we introduced new failure modes via 8188145, or
are these existing failure modes?
>> Also the CR talks about VerifyError being thrown, but I didn't spot
>> anything that would be dealing with that case ?? Is VerifyError the
>> correct/expected exception now?
> Are you asking about JDK part?
> The confusion comes from the fact that MemberName resolution can be
> triggered both from bytecode (through an upcall) and reflectively
> (through proper MethodHandles.Lookup call).
> Reflective case doesn't want to see Errors, so everything is converted
> to ReflectiveOperationException. But if resolution is initiated by the
> JVM, ReflectiveOperationException is unwrapped back to proper Error .
> To sum up, JDK part doesn't want to see LinkageErrors, so all "unknown"
> errors are wrapped into IllegalAccessExceptions, but requests from JVM
> should behave according to "equivalent bytecode behavior".
Has this fix altered the behaviour of calls initiated from Java? Or is
it only adjusting the exceptions the VM may see if the sequence is:
VM -> Java -> VM
> That's why I decided to eliminate ClassNotFoundException for now - it
> complicates with Error <-> Exception mappings.
Shouldn't you have just unwrapped the original NCDFE instead of wrapping
the CNFE (which wraps the original NCDFE) with another NCDFE?
> Best regards,
> Vladimir Ivanov
>  https://bugs.openjdk.java.net/browse/JDK-8188145
More information about the hotspot-runtime-dev