Question ad #AwkwardStrongEncapsulation (Re: Moving the changes in jake to jdk9/dev

Rony G. Flatscher Rony.Flatscher at wu.ac.at
Tue Dec 13 15:47:54 UTC 2016



On 12.12.2016 22:42, Peter Levart wrote:
>
>
> On 12/12/2016 08:56 PM, Alex Buckley wrote:
>> On 12/11/2016 8:16 AM, Rony G. Flatscher wrote:
>>> On 23.11.2016 12:55, Alan Bateman wrote:
>>>> As people on this mailing list know, jake has the changes for #AwkwardStrongEncapsulation [1]
>>>> where setAccessible has been changed so it can't be used to break into non-public members/types in
>>>> exported packages of JDK modules. It was changed more than a year ago to fail when attempting to
>>>> use it to break into non-exported packages. Dialing it up further is a disruptive change that will
>>>> expose a lot of hacks and issues with existing code that is used to accessing non-public
>>>> fields/methods in JDK classes. It will take some libraries and tools a bit of time to digest this
>>>> change, even with the --add-opens command line option and Add-Opens manifest in application JAR
>>>> files to keep existing code going. I plan to send mail to jdk9-dev in advance of this integration
>>>> to create wider awareness of this change.
>>>>
>>>> -Alan
>>>>
>>>> [1] http://openjdk.java.net/projects/jigsaw/spec/issues/#AwkwardStrongEncapsulation
>>> Would #AwkwardStrongEncapsulation inhibit setAccessible to work on protected methods (in
>>> addition to
>>> private and package private members) as well?
>>>
>>> As subclasses are allowed to access protected members in their superclasses, setAccessible should
>>> work for protected methods in classes that are invoked for objects that are instances of their
>>> subclasses?
>>
>> The ability of protected members to be accessed from outside their package means they are
>> essentially public members for the purposes of inheritance and reflection. So, setAccessible
>> should work for protected members of exported packages. I know what you mean about the receiver
>> object being of the correct class, but that's outside the capability of setAccessible to check,
>> so I don't believe it is checked.
>>
>> Alex
>
> That's right, currently setAccessible is allowed only within a module, for any members of any
> classes in unnamed module(s), for public members of public classes in exported packages of named
> module(s) and for any members of any classes of open packages. Here's the actual code used to
> check the ability to make a member setAccessible(true):
>
>     void checkCanSetAccessible(Class<?> caller, Class<?> declaringClass) {
>         Module callerModule = caller.getModule();
>         Module declaringModule = declaringClass.getModule();
>
>         if (callerModule == declaringModule) return;
>         if (callerModule == Object.class.getModule()) return;
>         if (!declaringModule.isNamed()) return;
>
>         // package is open to caller
>         String pn = packageName(declaringClass);
>         if (declaringModule.isOpen(pn, callerModule))
>             return;
>
>         // package is exported to caller and class/member is public
>         boolean isExported = declaringModule.isExported(pn, callerModule);
>         boolean isClassPublic = Modifier.isPublic(declaringClass.getModifiers());
>         int modifiers;
>         if (this instanceof Executable) {
>             modifiers = ((Executable) this).getModifiers();
>         } else {
>             modifiers = ((Field) this).getModifiers();
>         }
>         boolean isMemberPublic = Modifier.isPublic(modifiers);
>         if (isExported && isClassPublic && isMemberPublic)
>             return;
>
>         // not accessible
>         String msg = "Unable to make ";
>         if (this instanceof Field)
>             msg += "field ";
>         msg += this + " accessible: " + declaringModule + " does not \"";
>         if (isClassPublic && isMemberPublic)
>             msg += "exports";
>         else
>             msg += "opens";
>         msg += " " + pn + "\" to " + callerModule;
>         Reflection.throwInaccessibleObjectException(msg);
>     }
>
>
> This could be relaxed a bit for protected static fields/methods and for protected constructors,
> but can't be for instance members, because there is no target object to check against when
> setAccessible() is called...
So the current code does not take protected members into account. If protected members (cf. Alex'
comment)  get added, wouldn't e.g. java.lang.reflect.Method.invoke(...)  or
java.lang.reflect.Field.get(...) be the place to check in the next step, throwing an
IllegalAccessException if the object is not instantiated from a subclass of the class the protected
method to invoke or protected Field to get is defined?

---rony





More information about the jigsaw-dev mailing list