Proposal: Allow illegal reflective access by default in JDK 9

Peter Levart peter.levart at gmail.com
Fri May 19 11:28:10 UTC 2017



On 05/19/2017 12:58 PM, Peter Levart wrote:
>
> It's easy. Take this example:
>
> public class Test {
>     public static void main(String[] args) throws Exception {
>         Object theUnsafe = Class.forName("jdk.internal.misc.Unsafe")
>                                 .getMethod("getUnsafe")
>                                 .invoke(null);
>     }
> }
>
> Running this on classpath without any additional JVM options produces:
>
> Exception in thread "main" java.lang.IllegalAccessException: class 
> Test cannot access class jdk.internal.misc.Unsafe (in module 
> java.base) because module java.base does not export jdk.internal.misc 
> to unnamed module @63d4e2ba
>     at 
> java.base/jdk.internal.reflect.Reflection.throwIllegalAccessException(Reflection.java:445)
>     at 
> java.base/jdk.internal.reflect.Reflection.throwIllegalAccessException(Reflection.java:436)
>     at 
> java.base/jdk.internal.reflect.Reflection.ensureMemberAccess(Reflection.java:112)
>     at 
> java.base/java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:407)
>     at 
> java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:399)
>     at java.base/java.lang.reflect.Method.invoke(Method.java:535)
>     at Test.main(Test.java:9)
>
> (note that the exception is thrown from Method.invoke)
>
> When run with:
>
>      --add-exports java.base/jdk.internal.misc=ALL-UNNAMED
>
> ...the example works (does not throw exception), but when run with:
>
>     --add-opens java.base/jdk.internal.misc=ALL-UNNAMED
>
> ...the example still works!!!! OOOPS - this is a bug!!! This is 
> definitely a bug.
>
>
> If --illegal-access=permit is an alias for opening all modules to 
> ALL-UNNAMED, then we definitely have a problem as above example can be 
> successfully executed even with SecurityManager enabled!!!
>

...Ok, there's still a SecurityManager.checkPackageAccess() performed 
when some app class "loads" the jdk.internal.misc.Unsafe class and the 
caller needs to have a "accessClassInPackage.jdk.internal.misc" runtime 
permission. So this throws exception with SecurityManager enabled (from 
Class.forName("...") this time), but this permission should not be 
sufficient. I think "opens" should not imply "exports" - not even for 
reflection.

Conceptually "exports" should fall in the same category of access 
controls as "private", "package-private", "protected" and "public" 
modifiers on members/classes. If a member is not accessible to a caller 
due to access modifiers on the member or enclosing class or module 
lacking "exports", then such member should not be allowed to be accessed:
- during compilation
- during runtime by bytecode instruction
- during runtime by reflection
- during runtime by MethodHandles.Lookup methods

Opening a package to the caller module should only allow the caller to 
suppress these access checks, but the caller should still be required to 
request this explicitly either by using 
AccessibleObject.setAccessible(true) when reflecting; or by using 
MethodHandles.Lookup.privateLookupIn() when looking up members to get 
MethodHandles or VarHandles. Those two methods require special 
"suppressAccessChecks" runtime permission.

Regards, Peter



More information about the jigsaw-dev mailing list