Proposal: #ReflectiveAccessToNonExportedTypes (revised) & #AwkwardStrongEncapsulation: Weak modules & private exports

David M. Lloyd david.lloyd at redhat.com
Wed Sep 21 11:53:42 UTC 2016


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


More information about the jigsaw-dev mailing list