On Sep 13, 2013, at 3:18 PM, Peter Levart <peter.lev...@gmail.com> wrote:

> On 09/13/2013 02:55 PM, Joel Borggrén-Franck wrote:
>> Hi Peter,
>> 
>> Interesting case, thanks for the testing.
>> 
>> On Sep 13, 2013, at 1:15 PM, Peter Levart <peter.lev...@gmail.com> wrote:
>> 
>>> On 09/13/2013 12:18 PM, Peter Levart wrote:
>>>> The C.class.getMethods() returns a 1 element array containing A.m(), but 
>>>> C.class.getMethod("m") throws NoSuchMethodException.
>>>> 
>>>> This seems inconsistent, but it's a corner case that can only happen with 
>>>> separate compilation.
>>> Sorry Joel, I must have tested the unpatched code for C.class.getMethods(). 
>>> In is in fact consistent with C.calss.getMethod("m"). Both calls don't 
>>> return the A.m() method. in getMethod("m") case the recursion is stoped 
>>> when B.m() static method is encountered and in getMethods() case the 
>>> inherited method A.m() is removed from inheritedMethods array by the 
>>> following in privateGetPublicMethods():
>>> 
>>>        // Filter out all local methods from inherited ones
>>>        for (int i = 0; i < methods.length(); i++) {
>>>            Method m = methods.get(i);
>>>            inheritedMethods.removeByNameAndSignature(m);
>>>        }
>>> 
>>> ...when collecting B's methods...
>>> 
>>> But the question remains whether A.m() should be seen by invokeinterface 
>>> C.m() in spite of the fact that there is static B.m() in between and 
>>> whether reflection should follow that.
>> I can't see any reason why an invokeinterface C.m() should not find a 
>> default method just because there is a static method with the same name and 
>> sig "in between". However the separate compilation setup required to arrange 
>> this is non-trivial in itself :)
> 
> It is non-trivial to arrange in a unit test. See the following for one 
> possible trick:
> 
> http://cr.openjdk.java.net/~plevart/jdk8-tl/AnnotationType/webrev.05/test/java/lang/annotation/AnnotationType/AnnotationTypeRuntimeAssumptionTest.java.html
> 
> It's expectable that such situations will arise in practice. interface A can 
> be a part of a vendor X library that's adding default methods in a new 
> release, for example, and B & C can be part of a vendor Y app that is using 
> the library...

I fully agree this will most probably occur in practice. But the situation is 
more complicated for an invoke, since there must have been a A.m() present when 
C was compiled in order to have an invokeinterface to be there in the first 
place. Just adding a default to A won't trigger this since there won't be an 
invokeinterface C.m().

Something like this might do:

Compile A { void m(); }, B {} and C {} together.
Compile A { } B { static m()} together
Compile A { default m(); }

Do you have a preference for how we should do this?

cheers
/Joel

Reply via email to