[Nestmates] Add a core reflection API to get nestmate information

David Holmes david.holmes at oracle.com
Thu Nov 16 21:52:51 UTC 2017


Hi Peter,

On 16/11/2017 9:37 PM, Peter Levart wrote:
> Hi,
> 
> I saw the proposal for a core reflection API to get nestmate information 
> and here are my thoughts about the decision to filter out class 
> resolution errors in some methods, discussed below...
> 
> On 11/08/2017 01:19 AM, David Holmes wrote:
>> Hi Dan,
>>
>> Thanks for taking a look at this.
>>
>> On 8/11/2017 9:21 AM, Dan Smith wrote:
>>> I would be careful to match the behavior of 'isNestmateOf' to JVMS 
>>> 5.4.4, rather than define it in terms of 'getNestHost'. In 
>>> particular, 'c.isNestmateOf(c)' shouldn't need to perform any class 
>>> loading.
>>
>> I could short-circuit that case, but why special case this instead of 
>> just retrieving the nest host (which may need to be loaded)? This is 
>> not an access-check (for which we bail out very early for the same 
>> class) but a simple query, so the access-check process per JVMS 5.4.4 
>> don't directly need to apply.
>>
>>> For other cases, if class loading errors occur, is the proposal to 
>>> swallow them and return 'false'? That seems okay, I guess, but is a 
>>> different conclusion than what we came up with in JVMS.
>>
>> This was recently discussed on this list under "nestmates spec open 
>> issues".
>>
>> http://mail.openjdk.java.net/pipermail/valhalla-spec-experts/2017-October/000386.html 
>>
>>
>> John prefers to minimize exceptions for the Java API. :)
> 
> Suppose that this is basic reflection API to get nestmate information 
> and that it will also be used for reflective access checks. For example 
> in jdk.internal.reflect.Reflection#verifyMemberAccess, which is used 

It isn't. The reflection API is purely for "external" use. Real access 
checks are performed in the same way as the VM access checks - as 
required - and will report the same exceptions in the same way.

David
-----

> from Method.invoke, Fileld.[get|set], Constructor.newInstance. The most 
> appropriate method for this check is Class.isNestmateOf(Class). For 
> example:
> 
>      /**
>       * Verify access to a member and return {@code true} if it is granted.
>       *
>       * @param currentClass the class performing the access
>       * @param memberClass the declaring class of the member being accessed
>       * @param targetClass the class of target object if accessing instance
>       *                    field or method;
>       *                    or the declaring class if accessing constructor;
>       *                    or null if accessing static field or method
>       * @param modifiers the member's access modifiers
>       * @return {@code true} if access to member is granted
>       */
>      public static boolean verifyMemberAccess(Class<?> currentClass,
>                                               Class<?> memberClass,
>                                               Class<?> targetClass,
>                                               int modifiers)
>      {
>          if (currentClass.isNestmateOf(memberClass)) {
>              // Always succeeds
>              return true;
>          }
>          ...
> 
> If there is a nest-host class resolution error and isNestmateOf() 
> returns false for two actual nest-mates that have lost their host, 
> reflective access is going to throw IllegalAccessException(s) and the 
> real cause of failure will be hidden. That doesn't help to diagnose the 
> problem.
> 
> If the reasoning behind the decision to hide resolution exceptions is 
> the desire to mimic OLD behavior, it is not successful, because the OLD 
> behavior allows private access between two nested classes when "top" 
> class is missing while then NEW behavior disallows it.
> 
> Enter symmetric scheme: instead of one nest-host with a list of 
> nets-matest + N-1 nest-mates that reference just the nest-host, there 
> would be N nest-mates with equal status where each lists all others. 
> With symmetric scheme there would be no need to hide resolution errors 
> that happen now when access checks are performed between two nest-mates 
> where neither of them is a nest-host.
> 
> If I remember correctly, the symmetric scheme was not considered, 
> because it would be complicated to resolve inconsistencies and spoofing.
> 
> Is it really that important to have a notion of nest-host? Is it really 
> that important to be able to (consistently) enumerate members of nest? 
> What problem are nest-mates solving? If the answer is just "access 
> checking", then the notion of nest-host and nest-mates enumeration are 
> only artificial implementation details. If those two concepts are really 
> not necessary ingredients, then a symmetric scheme is a simple 
> alternative for access checking. The only method needed is this:
> 
> Class.isNestmateOf(Class<?> c);
> 
> A method that returns true if (this == c || <this and c have each other 
> in their lists of nest-mates>).
> 
> Spoofing is not possible, because both parties must agree and resolution 
> errors don't need to be hidden, because only resolution of involved 
> parties is necessary.
> 
> You still have reflexive and symmetric, but you loose transitive 
> property: if A may access B.private and B may access C.private that 
> doesn't imply that A may access C.private, because the nest-lists of 
> classes may be:
> 
> A: [B]
> B: [A, C]
> C: [B]
> 
> But such cases may only arise as a consequence of faulty assembly. 
> Compilation (even partial/incremental) can always verify the consistency 
> of the whole nest and bail-out if needed.
> 
> If you really needed to enumerate the members of the nest, the result 
> would be dependent on the member that was given as an anchor point. A 
> good-enough algorithm is this:
> 
> x.getNestMembers() returns a list composed of x and all classes listed 
> in x's nest-list that also have x listed in their nest-list(s). For 
> above inconsistent example that would mean:
> 
> A.class.getNestMembers() = [A, B];
> B.class.getNestMembers() = [A, B, C];
> C.class.getNestMembers() = [B, C];
> 
> But then again, if you are asking a trusted class for the list of nest 
> members, no-one can spoof and add additional members to the list that 
> was established when that trusted class was compiled.
> 
> To wrap-up: symmetric scheme has pros and cons. The question is what is 
> more important - the consistent view (no matter who you ask, you always 
> get the same answer) but with potential resolution troubles when 
> nest-host is not resolvable, or a semi-consistent view (depends on who 
> you ask, but if you ask a trusted class, you get a trusted answer) but 
> never need for resolving any additional classes.
> 
> Regards, Peter
> 


More information about the valhalla-spec-observers mailing list