Hi Peter, Nice work here.
PublicMethods — I would be inclined to change PublicMethods to encapsulate an instance of LinkedHashMap, since it’s only the consolidate/toArray methods that really matter, and no need for the key/value types to be exposed, then no need to declare serialVersionUID, and also it can be final. The JavaDoc on consolidate would need to be tweaked. 29 * existing methods with same signature if they are less specific then added s/then/than 89 if (o == null || getClass() != o.getClass()) return false; Could be simplified to if (!(o instanceof Key)) return false Paul. > On 4 Oct 2016, at 06:40, Peter Levart <peter.lev...@gmail.com> wrote: > > Hi, > > I have a fix for conformance (P2) bug (8062389 > <https://bugs.openjdk.java.net/browse/JDK-8062389>) that also fixes a > conformance (P3) bug (8029459 > <https://bugs.openjdk.java.net/browse/JDK-8029459>) and a performance issue > (8061950 <https://bugs.openjdk.java.net/browse/JDK-8061950>): > > http://cr.openjdk.java.net/~plevart/jdk9-dev/Class.getMethods.new/webrev.04/ > > As Daniel Smith writes in 8029459 > <https://bugs.openjdk.java.net/browse/JDK-8029459>, the following situation > is as expected: > > interface I { void m(); } > interface J extends I { void m(); } > interface K extends J {} > K.class.getMethods() = [ J.m ] > > But the following has a different result although it should probably have the > same: > > interface I { void m(); } > interface J extends I { void m(); } > interface K extends I, J {} > K.class.getMethods() = [ I.m, J.m ] > > He then suggests the following algorithm: > > An implementation of getMethods consistent with JLS 8 would include the > following (see Lambda Spec, Part H, 9.4.1 and 8.4.8): > 1) The class's/interface's declared (public) methods > 2) The getMethods() of the superclass (if this is a class), minus any that > have a match in (1) > 3) The getMethods() of each superinterface, minus any that have a match in > (1) or a _concrete_ match in (2) or a match from a more-specific > class/interface in (2) or (3) > > But even that is not sufficient for the following situation: > > interface E { void m(); } > interface F extends E { void m(); } > abstract class G implements E {} > abstract class H extends G implements F {} > H.class.getMethods() = [ E.m, F.m ] > > The desired result of H.class.getMethods() = [ F.m ] > > So a more precise definition is required which is implemented in the fix. > > The getMethods() implementation partitions the union of the following methods: > > 1) The class's/interface's declared public methods > 2) The getMethods() of the superclass (if this is a class) > 3) The non-static getMethods() of each direct superinterface > > ...into equivalence classes (sets) of methods with same signature (return > type, name, parameter types). Within each such set, only the "most specific" > methods are kept and others are discarded. The union of the kept methods is > the result. > > The "more specific" is defined as a partial order within a set of methods of > same signature: > > Method A is more specific than method B if: > - A is declared by a class and B is declared by an interface; or > - A is declared by the same type as or a subtype of B's declaring type and > both are either declared by classes or both by interfaces (clearly if A and B > are declared by the same type and have the same signature, they are the same > method) > > If A and B are distinct elements from the set of methods with same signature, > then either: > - A is more specific than B; or > - B is more specific than A; or > - A and B are incomparable > > A sub-set of "most specific" methods are the methods from the set where for > each such method M, there is no method N != M such that N is "more specific" > than M. > > There can be more than one "most specific" method for a particular signature > as they can be inherited from multiple unrelated interfaces, but: > - javac prevents compilation when among multiply inherited methods with same > signature there is at least one default method, so in practice, getMethods() > will only return multiple methods with same signature if they are abstract > interface methods. With one exception: bridge methods that are created by > javac for co-variant overrides are default methods in interfaces. For example: > > interface I { Object m(); } > interface J1 extends I { Map m(); } > interface J2 extends I { HashMap m(); } > interface K extends J1, J2 {} > > K.class.getMethods() = [ default Object j1.m, abstract Map j1.m, default > Object j2.m, abstract HashMap j2.m ] > > But this is an extreme case where one can still expect multiple non-abstract > methods with same signature, but different declaring type, returned from > getMethods(). > > In order to also fix 8062389 > <https://bugs.openjdk.java.net/browse/JDK-8062389>, getMethod() and > getMethods() share the same consolidation logic that results in a set of > "most specific" methods. The partitioning in getMethods() is partially > performed by collecting Methods into a HashMap where the keys are (name, > parameter types) tuples and values are linked lists of Method objects with > possibly varying return and declaring types. The consolidation, i.e. keeping > only the set of most specific methods as new methods are encountered, is > performed only among methods in the list that share same return type and also > removes duplicates. getMethod() uses only one such list, consolidates methods > that match given name and parameter types and returns the 1st method from the > resulting list that has the most specific return type. > > That's it for algorithms used. As partitioning partially happens using > HashMap with (name, parameter types) keys, lists of methods that form values > are typically kept short with most of them containing only a single method, > so this fix also fixes performance issue 8061950 > <https://bugs.openjdk.java.net/browse/JDK-8061950>. > > The patch also contains some optimizations around redundant copying of arrays > and reflective objects. > > The FilterNotMostSpecific jtreg test has been updated to accommodate for > changed behavior. Both of the above extreme cases have been added to the test. > > So, comments, please. > > Regards, Peter >