-
Bug
-
Resolution: Fixed
-
P4
-
8
Method handle resolution as specified in JVMS 5.4.3.5 and java.lang.invoke's javadoc does not duplicate the verification-time checks for protected members in invokespecial, invokevirtual, getfield, and putfield. However, Hotspot does duplicate the checks, as follows:
- For REF_newInvokeSpecial: If C.<init> is protected then C must be declared in the same run-time package as the current class. (This mirrors JLS 6.6.2.2.)
Example (full code is attached - ProtectedCheckNewInvokeSpecial.jasm):
// unrelated class in the same package
// public <init> - no error
ldc MethodHandle REF_newInvokeSpecial:C."<init>":"()V";
// protected <init> - no error
ldc MethodHandle REF_newInvokeSpecial:C."<init>":"(I)V";
// unrelated class in another package
// public <init> - no error
ldc MethodHandle REF_newInvokeSpecial:pkg/C."<init>":"()V";
// protected <init> - IllegalAccessError (from access control check done by method resolution)
ldc MethodHandle REF_newInvokeSpecial:pkg/C."<init>":"(I)V";
// superclass in another package
// public <init> - no error
ldc MethodHandle REF_newInvokeSpecial:pkg/Super."<init>":"()V";
// protected <init> - IllegalAccessError (from MH resolution check akin to the verifier protected check)
ldc MethodHandle REF_newInvokeSpecial:pkg/Super."<init>":"(I)V";
- For REF_invokeVirtual, REF_getField, REF_putField: If C.x is protected and C is in a different run-time package than the current class, then the receiver must be assignable to the current class. Consequently, MH's type descriptor is (CurrentClass,A*)T for REF_invokeVirtual, (CurrentClass)T for REF_getField, and (CurrentClass,T)V for REF_putField.
Example (full code is attached - ProtectedCheckMH.jasm):
// C.i is protected
// this code prints
// (Lpkg/Current;I)V
// REF_getField and REF_invokeVirtual behavior is similar
getstatic Field java/lang/System.out:"Ljava/io/PrintStream;";
ldc MethodHandle REF_putField:anotherpkg/C."i":"I";
dup_x1;
invokevirtual Method java/lang/invoke/MethodHandle.type:"()Ljava/lang/invoke/MethodType;";
invokevirtual Method java/lang/invoke/MethodType.toMethodDescriptorString:"()Ljava/lang/String;";
invokevirtual Method java/io/PrintStream.println:"(Ljava/lang/String;)V";
// C.<init> is protected
// this code throws IllegalAccessError
ldc MethodHandle REF_newInvokeSpecial:anotherpkg/C."<init>":"()V";
- For REF_newInvokeSpecial: If C.<init> is protected then C must be declared in the same run-time package as the current class. (This mirrors JLS 6.6.2.2.)
Example (full code is attached - ProtectedCheckNewInvokeSpecial.jasm):
// unrelated class in the same package
// public <init> - no error
ldc MethodHandle REF_newInvokeSpecial:C."<init>":"()V";
// protected <init> - no error
ldc MethodHandle REF_newInvokeSpecial:C."<init>":"(I)V";
// unrelated class in another package
// public <init> - no error
ldc MethodHandle REF_newInvokeSpecial:pkg/C."<init>":"()V";
// protected <init> - IllegalAccessError (from access control check done by method resolution)
ldc MethodHandle REF_newInvokeSpecial:pkg/C."<init>":"(I)V";
// superclass in another package
// public <init> - no error
ldc MethodHandle REF_newInvokeSpecial:pkg/Super."<init>":"()V";
// protected <init> - IllegalAccessError (from MH resolution check akin to the verifier protected check)
ldc MethodHandle REF_newInvokeSpecial:pkg/Super."<init>":"(I)V";
- For REF_invokeVirtual, REF_getField, REF_putField: If C.x is protected and C is in a different run-time package than the current class, then the receiver must be assignable to the current class. Consequently, MH's type descriptor is (CurrentClass,A*)T for REF_invokeVirtual, (CurrentClass)T for REF_getField, and (CurrentClass,T)V for REF_putField.
Example (full code is attached - ProtectedCheckMH.jasm):
// C.i is protected
// this code prints
// (Lpkg/Current;I)V
// REF_getField and REF_invokeVirtual behavior is similar
getstatic Field java/lang/System.out:"Ljava/io/PrintStream;";
ldc MethodHandle REF_putField:anotherpkg/C."i":"I";
dup_x1;
invokevirtual Method java/lang/invoke/MethodHandle.type:"()Ljava/lang/invoke/MethodType;";
invokevirtual Method java/lang/invoke/MethodType.toMethodDescriptorString:"()Ljava/lang/String;";
invokevirtual Method java/io/PrintStream.println:"(Ljava/lang/String;)V";
// C.<init> is protected
// this code throws IllegalAccessError
ldc MethodHandle REF_newInvokeSpecial:anotherpkg/C."<init>":"()V";
- relates to
-
JDK-8080790 5.4.3.5: REF_invokeSpecial behavior should enforce sender/receiver relationship
-
- Closed
-
-
JDK-8138569 5.4.3.5: Clarify that method handle resolution is static-aware
-
- Closed
-
-
JDK-8138883 5.4.3.5: Clarify that method handle resolution of REF_invokeInterface is private-aware
-
- Closed
-