Hi Peter,

I’m not entirely convinced this is a bug.

The lookup order for getMethod has for a long time been walk up superclasses 
and return what you find there first without even looking at interfaces. It 
might be desirable to change that but I’m not sure.

cheers
/Joel

On 29 okt 2014, at 12:26, Peter Levart <peter.lev...@gmail.com> wrote:

> Hi Joel,
> 
> I found an inconsistency between getMethod() and getMethods() results that is 
> present in current JDK8/9 code and in my latest webrev.02. The following 
> program:
> 
> import java.util.stream.Collectors;
> import java.util.stream.Stream;
> 
> public class GetMethodTest {
> 
>    static void test(Class<?> clazz) throws Exception {
> 
>        System.out.println(clazz.getName() + ".class.getMethods():  " +
>                           Stream
>                               .of(clazz.getMethods())
>                               .filter(m -> m.getDeclaringClass() != 
> Object.class)
>                               .collect(Collectors.toList()));
> 
>        System.out.println(clazz.getName() + ".class.getMethod(\"m\"): " +
>                           clazz.getMethod("m"));
> 
>        System.out.println();
>    }
> 
>    public static void main(String[] args) throws Exception {
>        test(I.class);
>        test(J.class);
>        test(A.class);
>        test(B.class);
>    }
> }
> 
> interface I {
>    void m();
> }
> 
> interface J extends I {
>    default void m() {}
> }
> 
> abstract class A implements I {}
> 
> abstract class B extends A implements J {}
> 
> 
> prints:
> 
> I.class.getMethods():  [public abstract void I.m()]
> I.class.getMethod("m"): public abstract void I.m()
> 
> J.class.getMethods():  [public default void J.m()]
> J.class.getMethod("m"): public default void J.m()
> 
> A.class.getMethods():  [public abstract void I.m()]
> A.class.getMethod("m"): public abstract void I.m()
> 
> B.class.getMethods():  [public default void J.m()]
> B.class.getMethod("m"): public abstract void I.m()
> 
> B.class.getMethods() reports default method J.m() (which I think is correct), 
> but B.class.getMethod("m") reports the abstract I.m() inherited from A, 
> because here the getMethod0() algorithm stops searching for and consolidating 
> any methods in (super)interfaces. Do you agree that this is a bug?
> 
> 
> Regards, Peter
> 
> On 10/27/2014 02:45 PM, Joel Borggrén-Franck wrote:
>> Hi Peter,
>> 
>> As always, thanks for doing this! It has been on my todolist for a while but 
>> never quite bubbling up to the top.
>> 
>> I don’t have time to look att his right now, but I expect to have some free 
>> time next week, but i have two short comments
>> 
>> First, I have been thinking about moving MethodArray to its’s own top-level 
>> class, isn’t it about time?
>> 
>> Second I would expect testing for the missing cases you uncovered (good 
>> catch!).
>> 
>> I’ll try to get back to you asap.
>> 
>> cheers
>> /Joel
>> 
>> 
>> On 26 okt 2014, at 23:53, Peter Levart <peter.lev...@gmail.com> wrote:
>> 
>>> On 10/26/2014 09:25 PM, Peter Levart wrote:
>>>> 19657 classes loaded in 1.987373401 seconds.
>>>> 494141 methods obtained in 1.02493941 seconds.
>>>> 
>>>> vs.
>>>> 
>>>> 19657 classes loaded in 2.084409717 seconds.
>>>> 494124 methods obtained in 0.915928578 seconds.
>>> Hi,
>>> 
>>> As you might have noticed, the number of methods obtained from patched code 
>>> differed from original code. I have investigated this and found that 
>>> original code treats abstract class methods the same as abstract interface 
>>> methods as far as multiple inheritance is concerned (it keeps them together 
>>> in the returned array). So I fixed this and here's new webrev which behaves 
>>> the same as original code:
>>> 
>>> http://cr.openjdk.java.net/~plevart/jdk9-dev/Class.getMethods/webrev.02/
>>> 
>>> Comparing original vs. patched code still shows speed-up:
>>> 
>>> Original:
>>> 
>>> 19657 classes loaded in 1.980493029 seconds.
>>> 494141 methods obtained in 0.976318927 seconds.
>>> 494141 methods obtained in 0.886504437 seconds.
>>> 494141 methods obtained in 0.911153722 seconds.
>>> 494141 methods obtained in 0.880550509 seconds.
>>> 494141 methods obtained in 0.875526704 seconds.
>>> 494141 methods obtained in 0.877258894 seconds.
>>> 494141 methods obtained in 0.871794344 seconds.
>>> 494141 methods obtained in 0.884159644 seconds.
>>> 494141 methods obtained in 0.892648522 seconds.
>>> 494141 methods obtained in 0.884581841 seconds.
>>> 
>>> Patched:
>>> 
>>> 19657 classes loaded in 2.055697675 seconds.
>>> 494141 methods obtained in 0.853922188 seconds.
>>> 494141 methods obtained in 0.776203794 seconds.
>>> 494141 methods obtained in 0.858774803 seconds.
>>> 494141 methods obtained in 0.778178867 seconds.
>>> 494141 methods obtained in 0.760043997 seconds.
>>> 494141 methods obtained in 0.756352444 seconds.
>>> 494141 methods obtained in 0.740826372 seconds.
>>> 494141 methods obtained in 0.744264782 seconds.
>>> 494141 methods obtained in 0.73805894 seconds.
>>> 494141 methods obtained in 0.746852752 seconds.
>>> 
>>> 
>>> 55 java/lang/reflect jtreg tests still pass. As they did before, which 
>>> means that we don't have a coverage for such cases. I'll see where I can 
>>> add such a case (EnumSet for example, which inherits from Set interface and 
>>> AbstractColection class via two different paths, so Set.size()/iterator() 
>>> and AbstractCollection.size()/iterator() are both returned from 
>>> getMethods())...
>>> 
>>> 
>>> Regards, Peter
>>> 
> 

Reply via email to