Suggestion: allow accessible reflection on protected methods of exported types.

Rafael Winterhalter rafael.wth at gmail.com
Thu Dec 29 16:24:55 UTC 2016


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


More information about the jigsaw-dev mailing list