On 09/21/2016 12:50 AM, Jochen Theodorou wrote:
On 12.09.2016 17:08, Mark Reinhold wrote:
Issue summary
-------------

   #ReflectiveAccessToNonExportedTypes --- Some kinds of framework
   libraries require reflective access to members of the non-exported
   types of other modules; examples include dependency injection (Guice),
   persistence (JPA), debugging tools, code-automation tools, and
   serialization (XStream).  In some cases the particular library to be
   used is not known until run time (e.g., Hibernate and EclipseLink both
   implement JPA).  This capability is also sometimes used to work around
   bugs in unchangeable code.  Access to non-exported packages can, at
   present, only be done via command-line flags, which is extremely
   awkward.  Provide an easier way for reflective code to access such
   non-exported types. [1]

   #AwkwardStrongEncapsulation --- A non-public element of an exported
   package can still be accessed via the
`AccessibleObject::setAccessible`
   method of the core reflection API.  The only way to strongly
   encapsulate such an element is to move it to a non-exported package.
   This makes it awkward, at best, to encapsulate the internals of a
   package that defines a public API. [2]
[...]

I´d like to give some feedback on this. Our situation was this, that we
finally managed to get the Groovy build running on JDK9 with the jigsaw
version before this change here came live. The situation now is, that
gradle broke and we are not even starting compilation anymore. Well, can
happen with a change like this. But the issue at hand was about using
setAccessible (without exporting private) to get access to a protected
method in java.base. When this proposal mentioned non-public I was
actually automatically thinking private, but of course there are at
least two more visibility options to think of.

So I find another awkward point in #AwkwardStrongEncapsulation in that
you have exported API and you have a protected method in it. You can
write a class in your own module, that will overwrite or use that method
given that it is in a subclass. But if I want to use setAccessible to
invoke the method I cannot do that? This is awkward to me, because it
degrades the former (and often misused) swiss-army-knife setAccessible
to something that is even less capable than what I can do by subclassing
- unless special action are taken. I can understand the idea for private
methods or package private - but protected is for me always part of the
API to program against and as such it makes not sense to me to prevent
setAccessible accessing it here.

It turns out that you don't actually need setAccessible to access a superclass protected method from a subclass.

If you have an instance of a subclass of the type containing the protected method, any class in the _same package_ as the _subclass_ can call invoke() on a Method without first making it accessible, as long as you pass in that subclass instance (even if the method is static, which is a little weird but necessary to make the check work!).

As to whether this makes sense in 100% of cases... that's a different discussion (and a fairly complex one at that - the code for checking protected access is (AFAICT) the most complex part of access checking in the JDK and the JVM).
--
- DML

Reply via email to