Question ad #AwkwardStrongEncapsulation (Re: Moving the changes in jake to jdk9/dev
David Holmes
david.holmes at oracle.com
Wed Dec 14 06:17:57 UTC 2016
On 14/12/2016 8:17 AM, Peter Levart wrote:
> Hi Jochen,
>
>
> On 12/13/2016 06:32 PM, Jochen Theodorou wrote:
>>
>>
>> On 12.12.2016 20:56, Alex Buckley wrote:
>> [...]
>>> 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.
>>
>> why does it have to be checked? why not just allow it? I mean that is
>> why I use setAccessible in the first place. I have much less use of
>> making something accessible for which I already have access rights
>>
>> bye Jochen
>
> You might have access to a protected method, but you can not delegate
> that access to a 3rd party unless you make the Method object
> .setAccessible(true) and pass it to the 3rd party as a capability. (I
> recommend using MethodHandle(s) for such delegation of rights instead of
> reflection though).
>
> But let me explain why .setAccessible(true) can't be allowed for
> protected members in general.
I'm confused as to what is being argued for/against here.
setAccessible(true) simply says to disable access checks when the member
is used. At the time of use you have all the necessary information
available:
- current class
- member defining class
- receiver class (target class??)
> Jigsaw establishes strong encapsulation. What that means is that even
> without a SecurityManager present, code should not be allowed to gain
> access to a member beyond what is allowed by accessibility rules of Java
> language unless that member is in a class in an open package or such
> access is willingly delegated to code by some other code. For core
> reflection that means the following check is performed each time a
> reflective access is performed:
>
> /**
> * Verify access to a member, returning {@code false} if no access
> */
> public static boolean verifyMemberAccess(Class<?> currentClass,
> Class<?> memberClass,
> Class<?> targetClass,
> int modifiers)
> {
Where does this method exist?
Thanks,
David
-----
> // Verify that currentClass can access a field, method, or
> // constructor of memberClass, where that member's access bits are
> // "modifiers".
>
> boolean gotIsSameClassPackage = false;
> boolean isSameClassPackage = false;
>
> if (currentClass == memberClass) {
> // Always succeeds
> return true;
> }
>
> if (!verifyModuleAccess(currentClass, memberClass)) {
> return false;
> }
>
> if (!Modifier.isPublic(getClassAccessFlags(memberClass))) {
> isSameClassPackage = isSameClassPackage(currentClass,
> memberClass);
> gotIsSameClassPackage = true;
> if (!isSameClassPackage) {
> return false;
> }
> }
>
> // At this point we know that currentClass can access memberClass.
>
> if (Modifier.isPublic(modifiers)) {
> return true;
> }
>
> boolean successSoFar = false;
>
> if (Modifier.isProtected(modifiers)) {
> // See if currentClass is a subclass of memberClass
> if (isSubclassOf(currentClass, memberClass)) {
> successSoFar = true;
> }
> }
>
> if (!successSoFar && !Modifier.isPrivate(modifiers)) {
> if (!gotIsSameClassPackage) {
> isSameClassPackage = isSameClassPackage(currentClass,
> memberClass);
> gotIsSameClassPackage = true;
> }
>
> if (isSameClassPackage) {
> successSoFar = true;
> }
> }
>
> if (!successSoFar) {
> return false;
> }
>
> // Additional test for protected instance members
> // and protected constructors: JLS 6.6.2
> if (targetClass != null && Modifier.isProtected(modifiers) &&
> targetClass != currentClass)
> {
> if (!gotIsSameClassPackage) {
> isSameClassPackage = isSameClassPackage(currentClass,
> memberClass);
> gotIsSameClassPackage = true;
> }
> if (!isSameClassPackage) {
> if (!isSubclassOf(targetClass, currentClass)) {
> return false;
> }
> }
> }
>
> return true;
> }
>
>
> The interesting part is at the end - the additional test for protected
> instance members. You can't perform the access check for a protected
> instance member without knowing the 'targetClass' (the runtime class of
> the target instance). The protected member must be declared by the same
> class (memberClass) or a superclass of the class from where you are
> accessing it (currentClass), but to allow access to the protected
> instance member, the runtime class of the target instance (targetClass)
> must also be the same as or a subclass of the class from where you are
> accessing the member (currentClass).
>
> You don't know in advance what target instance will be used when
> deciding whether to allow .setAccessible(true) for an instance member.
>
> Regards, Peter
>
More information about the jigsaw-dev
mailing list