Hello everybody, I did another round of testing a recent build of Java 9 with some applications and framework that I work with or maintain. I ran into an issue that I consider rather severe and I want to make a suggestion on how to potentially solve this problem.
Some libraries entertain utilities that access protected methods of exported types to enhance their functionality without requiring a user to provide a specific subclass of such an instance but to allow them to use “their“ implementation. To access these protected methods, reflection is used in combination with AccessibleObject::setAccessible. For example, this approach is used by code generation libraries to invoke the ClassLoader::defineClass method which allows the injection of proxy types into the class loader of the proxied class. With the new constraints enforced by Jigsaw, attempting to make ClassLoader::defineClass accessible fails with: java.lang.reflect.InaccessibleObjectException: Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to unnamed module @4cbd6df7 I argue that this module system should not be responsible to assert the usage of such protected methods on exported types. Such methods are not really encapsulated as they are considered official API by subclasses. Accessing such classes could of course be a security thread but preventing such breaches should be the job of the security manager rather than the module system. This problem is currently breaking all consumers of code generation libraries which is about every single enterprise application as this strategy is quite popular. During my tests, I ran into this issue with any application using Spring, Hibernate or Mockito where at least one of those are used by any enterprise application. To overcome this, I have now added a fallback to Unsafe::defineClass to my library Byte Buddy to reenable injection in Hibernate and Mockito. I plan to add the same fallback to cglib in the next days which is used by Spring and many others as this is currently a real problem that can only be overcome by adding the export on the command line what is a solution I try to avoid for its additional complexity. I also argue that there exist many more such access patterns of protected methods on exported types and it would be quite a regression to no longer be able to access these methods using reflection. Therefore, I really hope that my suggestion is considered. Also, it would be too bad if this change would result in the additional usage of sun.misc.Unsafe by Java end-users as this is currently the only fallback usable by code generation libraries which otherwise need to break their API. I managed to avoid introducing a dependency to sun.misc.Unsafe for 8 years now, it would really be a shame if I needed to start using it now. Thank you for considering this and best regards, Rafael