[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