Search code examples
reflectionclassloaderjava-9

How can I use reflection with Java 9 on the Java internals?


We use this type of Reflection only in our test framework and not in production. We want add some jar files to the app classloader depending of our test code. Is there any workaround for it? How can we get access to not exported classes?

java.lang.reflect.InaccessibleObjectException: Unable to make member of class jdk.internal.loader.ClassLoaders$AppClassLoader accessible:  module java.base does not export jdk.internal.loader to unnamed module @9f73a2
    at jdk.internal.reflect.Reflection.throwInaccessibleObjectException(Reflection.java:414)
    at java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:174)
    at java.lang.reflect.Method.checkCanSetAccessible(Method.java:191)
    at java.lang.reflect.Method.setAccessible(Method.java:185)

Solution

  • Accessing module-internal classes can not be done from code. This is on purpose. But there is a workaround from the command line - a non-standardized option on java that does what you want:

    --add-exports <module>/<package>=<target-module>(,<target-module>)*
                      updates <module> to export <package> to <target-module>,
                      regardless of module declaration.
                      <target-module> can be ALL-UNNAMED to export to all
                      unnamed modules.
    

    Note

    Java 9 is a moving target and the exact syntax has been changed a couple of times - as was this answer. This means (a) some of the comments below may seem outdated and (b) the flag might not work exactly like that. Please leave a comment and it will get fixed.