[10] RFR (S): 8196022: java.lang.VerifyError is thrown instead of java.lang.IllegalAccessError
Vladimir Ivanov
vladimir.x.ivanov at oracle.com
Sat Jan 27 07:10:47 UTC 2018
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:
>> 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 "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-5.4.3.5 [1]. 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 [2], CONSTANT_MethodHandle resolution reported
IllegalAccessError while equivalent bytecode behavior threw VerifyError.
>> 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() [3]). So, I decided to leave
them as is for now.
>
> 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 [4].
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".
That's why I decided to eliminate ClassNotFoundException for now - it
complicates with Error <-> Exception mappings.
Best regards,
Vladimir Ivanov
[1]
https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-5.html#jvms-5.4.3.5
[2] https://bugs.openjdk.java.net/browse/JDK-8188145
[3]
http://hg.openjdk.java.net/jdk/jdk10/file/f8d9bedbacf2/src/java.base/share/classes/java/lang/invoke/MemberName.java#l1050
[4]
http://hg.openjdk.java.net/jdk/jdk10/file/f8d9bedbacf2/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java#l509
More information about the hotspot-runtime-dev
mailing list