1 /*
2  * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 /*
25  * @test
26  *
27  * @modules java.base/jdk.internal.org.objectweb.asm:+open java.base/jdk.internal.org.objectweb.asm.util:+open
28  * @library /vmTestbase /test/lib
29  *
30  * @comment build retransform.jar in current dir
31  * @run driver vm.runtime.defmeth.shared.BuildJar
32  *
33  * @run driver jdk.test.lib.FileInstaller . .
34  * @run main/othervm/native
35  *      -agentlib:redefineClasses
36  *      -javaagent:retransform.jar
37  *      vm.runtime.defmeth.MethodResolutionTest
38  */
39 package vm.runtime.defmeth;
40 
41 import java.util.Set;
42 
43 import vm.runtime.defmeth.shared.data.*;
44 import vm.runtime.defmeth.shared.data.method.param.*;
45 import vm.runtime.defmeth.shared.DefMethTest;
46 import vm.runtime.defmeth.shared.builder.TestBuilder;
47 
48 import static jdk.internal.org.objectweb.asm.Opcodes.*;
49 import static vm.runtime.defmeth.shared.ExecutionMode.*;
50 
51 /**
52  * Tests on method resolution in presence of default methods in the hierarchy.
53  *
54  * Because default methods reside in interfaces, and interfaces do not have
55  * the constraint of being single-inheritance, it is possible to inherit
56  * multiple conflicting default methods, or even inherit the same default method
57  * from many different inheritance paths.
58  *
59  * There is an algorithm to select which method to use in the case that a
60  * concrete class does not provide an implementation. Informally, the algorithm
61  * works as follows:
62  *
63  * (1) If there is a adequate implementation in the class itself or in a
64  *     superclass (not an interface), then that implementation should be used
65  *     (i.e., class methods always "win").
66  *
67  * (2) Failing that, create the set of methods consisting of all methods in the
68  *     type hierarchy which satisfy the slot to be filled, where in this case
69  *     'satisfy' means that the methods have the same name, the same language-
70  *     level representation of the parameters, and covariant return values. Both
71  *     default methods and abstract methods will be part of this set.
72  *
73  * (3) Remove from this set, any method which has a "more specific" version
74  *     anywhere in the hierarchy.  That is, if C implements I,J and I extends J,
75  *     then if both I and J have a suitable methods, J's method is eliminated
76  *     from the set since I is a subtype of J -- there exist a more specific
77  *     method than J's method, so that is eliminated.
78  *
79  * (4) If the remaining set contains only a single entry, then that method is
80  *     selected. Note that the method may be abstract, in which case an
81  *     IncompatibleClassChangeError is thrown when/if the method is called. If there are
82  *     multiple entries in the set, or no entries, then this also results in an
83  *     IncompatibleClassChangeError when called.
84  */
85 public class MethodResolutionTest extends DefMethTest {
86 
main(String[] args)87     public static void main(String[] args) {
88         DefMethTest.runTest(MethodResolutionTest.class,
89                 /* majorVer */ Set.of(MIN_MAJOR_VER, MAX_MAJOR_VER),
90                 /* flags    */ Set.of(0, ACC_SYNCHRONIZED),
91                 /* redefine */ Set.of(false, true),
92                 /* execMode */ Set.of(DIRECT, REFLECTION, INVOKE_EXACT, INVOKE_GENERIC, INVOKE_WITH_ARGS, INDY));
93     }
94 
95     /*
96      * Basic
97      *
98      * interface I { int m(); }
99      * class C implements I { public int m() { return 1; } }
100      *
101      * TEST: C c = new C(); c.m() == 1;
102      * TEST: I i = new C(); i.m() == 1;
103      */
testBasic(TestBuilder b)104     public void testBasic(TestBuilder b) {
105         Interface I =
106             b.intf("I")
107                 .abstractMethod("m", "()I").build()
108              .build();
109 
110         ConcreteClass C =
111              b.clazz("C").implement(I)
112                 .concreteMethod("m", "()I").returns(1).build()
113               .build();
114 
115         b.test()
116                 .callSite(I, C, "m", "()I")
117                 .returns(1)
118             .done()
119         .test()
120                 .callSite(C, C, "m", "()I")
121                 .returns(1)
122             .done();
123     }
124 
125     /*
126      * Basic Default
127      *
128      * interface I { int m() default { return 1; } }
129      * class C implements I {}
130      *
131      * TEST: C c = new C(); c.m() == 1;
132      * TEST: I i = new C(); i.m() == 1;
133      */
testBasicDefault(TestBuilder b)134     public void testBasicDefault(TestBuilder b) {
135         Interface I =
136             b.intf("I")
137                 .defaultMethod("m", "()I").returns(1)
138                 .build()
139              .build();
140 
141         ConcreteClass C =
142              b.clazz("C").implement(I)
143               .build();
144 
145         b.test()
146                 .callSite(I, C, "m", "()I")
147                 .returns(1)
148             .done()
149         .test().callSite(C, C, "m", "()I")
150                 .returns(1)
151             .done();
152     }
153 
154     /*
155      * Far Default
156      *
157      * interface I { int m() default { return 1; } }
158      * interface J extends I {}
159      * interface K extends J {}
160      * class C implements K {}
161      *
162      * TEST: [I|J|K|C] i = new C(); i.m() == 1;
163      */
testFarDefault(TestBuilder b)164     public void testFarDefault(TestBuilder b) {
165         Interface I =
166             b.intf("I")
167                 .defaultMethod("m", "()I").returns(1)
168                 .build()
169              .build();
170 
171         Interface J = b.intf("J").extend(I).build();
172         Interface K = b.intf("K").extend(J).build();
173 
174         ConcreteClass C =
175              b.clazz("C").implement(K)
176               .build();
177 
178         b.test()
179                 .callSite(I, C, "m", "()I")
180                 .returns(1)
181             .done()
182         .test().callSite(J, C, "m", "()I")
183                 .returns(1)
184             .done()
185         .test().callSite(K, C, "m", "()I")
186                 .returns(1)
187             .done()
188         .test().callSite(C, C, "m", "()I")
189                 .returns(1)
190             .done();
191     }
192 
193     /*
194      * Override Abstract
195      *
196      * interface I { int m(); }
197      * interface J extends I { int m() default { return 1; } }
198      * interface K extends J {}
199      * class C implements K {}
200      *
201      * TEST: C c = new C(); c.m() == 1;
202      * TEST: K k = new C(); k.m() == 1;
203      */
testOverrideAbstract(TestBuilder b)204     public void testOverrideAbstract(TestBuilder b) {
205         Interface I = b.intf("I")
206                 .abstractMethod("m", "()I").build()
207             .build();
208 
209         Interface J = b.intf("J").extend(I)
210                 .defaultMethod("m", "()I").returns(1).build()
211             .build();
212 
213         Interface K = b.intf("K").extend(J).build();
214 
215         ConcreteClass C = b.clazz("C").implement(K).build();
216 
217         b.test()
218                 .callSite(I, C, "m", "()I")
219                 .returns(1)
220             .done()
221         .test()
222                 .callSite(J, C, "m", "()I")
223                 .returns(1)
224             .done()
225         .test()
226                 .callSite(K, C, "m", "()I")
227                 .returns(1)
228             .done()
229         .test()
230                 .callSite(C, C, "m", "()I")
231                 .returns(1)
232             .done();
233     }
234 
235     /*
236      * Default vs Concrete
237      *
238      * interface I { int m() default { return 1; } }
239      * class C implements I { public int m() { return 2; } }
240      *
241      * TEST: [C|I] c = new C(); c.m() == 2;
242      */
testDefaultVsConcrete(TestBuilder b)243     public void testDefaultVsConcrete(TestBuilder b) {
244         Interface I = b.intf("I")
245                 .defaultMethod("m", "()I").returns(1).build()
246             .build();
247 
248         ConcreteClass C = b.clazz("C").implement(I)
249                 .concreteMethod("m", "()I").returns(2).build()
250             .build();
251 
252         b.test()
253                 .callSite(I, C, "m", "()I")
254                 .returns(2)
255             .done()
256         .test()
257                 .callSite(C, C, "m", "()I")
258                 .returns(2)
259             .done();
260     }
261 
262     /*
263      * InheritedDefault
264      *
265      * interface I { int m() default { return 1; } }
266      * class B implements I {}
267      * class C extends B {}
268      *
269      * TEST: [I|B|C] v = new C(); v.m() == 1;
270      */
testInheritedDefault(TestBuilder b)271     public void testInheritedDefault(TestBuilder b) {
272         Interface I = b.intf("I")
273                 .defaultMethod("m", "()I").returns(1).build()
274             .build();
275 
276         ConcreteClass B = b.clazz("B").implement(I).build();
277         ConcreteClass C = b.clazz("C").extend(B).build();
278 
279         b.test()
280                 .callSite(I, C, "m","()I")
281                 .returns(1)
282             .done()
283         .test()
284                 .callSite(B, C, "m","()I")
285                 .returns(1)
286             .done()
287         .test()
288                 .callSite(C, C, "m","()I")
289                 .returns(1)
290             .done();
291     }
292 
293     /*
294      * ExistingInherited
295      *
296      * interface I { int m() default { return 1; } }
297      * class B { public int m() { return 2; } }
298      * class C extends B implements I {}
299      *
300      * TEST: [I|B|C] v = new C(); v.m() == 2;
301      */
testExistingInherited(TestBuilder b)302     public void testExistingInherited(TestBuilder b) {
303         Interface I = b.intf("I")
304                 .defaultMethod("m", "()I").returns(1).build()
305             .build();
306 
307         ConcreteClass B = b.clazz("B")
308                 .concreteMethod("m", "()I").returns(2).build()
309                 .build();
310 
311         ConcreteClass C = b.clazz("C").extend(B).implement(I).build();
312 
313         b.test()
314                 .callSite(I, C, "m","()I")
315                 .returns(2)
316             .done()
317         .test()
318                 .callSite(B, C, "m","()I")
319                 .returns(2)
320             .done()
321         .test()
322                 .callSite(C, C, "m","()I")
323                 .returns(2)
324             .done();
325     }
326 
327     /*
328      * ExistingInheritedOverride
329      *
330      * interface I { int m() default { return 1; } }
331      * class B implements I { public int m() { return 2; } }
332      * class C extends B { public int m() { return 3; } }
333      *
334      * TEST: [I|B|D] v = new C(); v.m() == 3;
335      */
testExistingInheritedOverride(TestBuilder b)336     public void testExistingInheritedOverride(TestBuilder b) {
337         Interface I = b.intf("I")
338                 .defaultMethod("m", "()I").returns(1).build()
339             .build();
340 
341         ConcreteClass B = b.clazz("B").implement(I)
342                 .concreteMethod("m", "()I").returns(2).build()
343                 .build();
344 
345         ConcreteClass C = b.clazz("C").extend(B)
346                 .concreteMethod("m", "()I").returns(3).build()
347                 .build();
348 
349         b.test()
350                 .callSite(I, C, "m","()I")
351                 .returns(3)
352             .done()
353         .test()
354                 .callSite(B, C, "m","()I")
355                 .returns(3)
356             .done()
357         .test()
358                 .callSite(C, C, "m","()I")
359                 .returns(3)
360             .done();
361     }
362 
363     /*
364      * ExistingInheritedPlusDefault
365      *
366      * interface I { int m() default { return 11; } }
367      * interface J { int m() default { return 12; } }
368      * class C implements I { public int m() { return 21; } }
369      * class D extends C { public int m() { return 22; } }
370      * class E extends D implements J {}
371      *
372      * TEST: [I|J|C|D|J] v = new E(); v.m() == 22;
373      */
testExistingInheritedPlusDefault(TestBuilder b)374     public void testExistingInheritedPlusDefault(TestBuilder b) {
375         Interface I = b.intf("I")
376                 .defaultMethod("m", "()I").returns(11).build()
377             .build();
378 
379         Interface J = b.intf("J")
380                 .defaultMethod("m", "()I").returns(12).build()
381             .build();
382 
383         ConcreteClass C = b.clazz("C").implement(I)
384                 .concreteMethod("m","()I").returns(21).build()
385             .build();
386 
387         ConcreteClass D = b.clazz("D").extend(C)
388                 .concreteMethod("m", "()I").returns(22).build()
389             .build();
390 
391         ConcreteClass E = b.clazz("E").extend(D).implement(J)
392                 .build();
393 
394         b.test()
395                 .callSite(I, E, "m","()I")
396                 .returns(22)
397             .done()
398         .test()
399                 .callSite(J, E, "m","()I")
400                 .returns(22)
401             .done()
402         .test()
403                 .callSite(C, E, "m","()I")
404                 .returns(22)
405             .done()
406         .test()
407                 .callSite(D, E, "m","()I")
408                 .returns(22)
409             .done()
410         .test()
411                 .callSite(E, E, "m","()I")
412                 .returns(22)
413             .done();
414     }
415 
416     /*
417      * InheritedWithConcrete
418      *
419      * interface I { int m() default { return 1; } }
420      * class B implements I {}
421      * class C extends B { public int m() { return 2; } }
422      *
423      * TEST: [I|B|C] v = new C(); v.m() == 2;
424      */
testInheritedWithConcrete(TestBuilder b)425     public void testInheritedWithConcrete(TestBuilder b) {
426         Interface I = b.intf("I")
427                 .defaultMethod("m", "()I").returns(1).build()
428             .build();
429 
430         ConcreteClass B = b.clazz("B").implement(I).build();
431 
432         ConcreteClass C = b.clazz("C").extend(B)
433                 .concreteMethod("m", "()I").returns(2).build()
434                 .build();
435 
436         b.test()
437                 .callSite(I, C, "m","()I")
438                 .returns(2)
439             .done()
440         .test()
441                 .callSite(B, C, "m","()I")
442                 .returns(2)
443             .done()
444         .test()
445                 .callSite(C, C, "m","()I")
446                 .returns(2)
447             .done();
448     }
449 
450     /*
451      * InheritedWithConcreteAndImpl
452      *
453      * interface I { int m() default { return 1; } }
454      * class B implements I {}
455      * class C extends B implements I { public int m() { return 2; } }
456      *
457      * TEST: [I|B|C] v = new C(); v.m() == 2;
458      */
testInheritedWithConcreteAndImpl(TestBuilder b)459     public void testInheritedWithConcreteAndImpl(TestBuilder b) {
460         Interface I = b.intf("I")
461                 .defaultMethod("m", "()I").returns(1).build()
462             .build();
463 
464         ConcreteClass B = b.clazz("B").implement(I).build();
465 
466         ConcreteClass C = b.clazz("C").extend(B)
467                 .concreteMethod("m", "()I").returns(2).build()
468             .build();
469 
470         b.test()
471                 .callSite(I, C, "m","()I")
472                 .returns(2)
473             .done()
474         .test()
475                 .callSite(B, C, "m","()I")
476                 .returns(2)
477             .done()
478         .test()
479                 .callSite(C, C, "m","()I")
480                 .returns(2)
481             .done();
482     }
483 
484     /*
485      * Diamond
486      *
487      * interface I { int m() default { return 1; } }
488      * interface J extends I {}
489      * interface K extends I {}
490      * class C implements J, K {}
491      *
492      * TEST: [I|J|K|C] c = new C(); c.m() == 99
493      */
testDiamond(TestBuilder b)494     public void testDiamond(TestBuilder b) {
495         Interface I = b.intf("I")
496                 .defaultMethod("m", "()I").returns(1).build()
497             .build();
498 
499         Interface J = b.intf("J").extend(I).build();
500         Interface K = b.intf("K").extend(I).build();
501 
502         ConcreteClass C = b.clazz("C").implement(J,K)
503             .build();
504 
505         b.test()
506                 .callSite(I, C, "m","()I")
507                 .returns(1)
508             .done()
509         .test()
510                 .callSite(J, C, "m","()I")
511                 .returns(1)
512             .done()
513         .test()
514                 .callSite(K, C, "m","()I")
515                 .returns(1)
516             .done()
517         .test()
518                 .callSite(C, C, "m","()I")
519                 .returns(1)
520             .done();
521     }
522 
523     /*
524      * ExpandedDiamond
525      *
526      * interface I { int m() default { return 1; } }
527      * interface J extends I {}
528      * interface K extends I {}
529      * interface L extends I {}
530      * interface M extends I {}
531      * class C implements J, K, L, M {}
532      *
533      * TEST: [I|J|K|L|M|C] c = new C(); c.m() == 1
534      */
testExpandedDiamond(TestBuilder b)535     public void testExpandedDiamond(TestBuilder b) {
536         Interface I = b.intf("I")
537                 .defaultMethod("m", "()I").returns(1).build()
538             .build();
539 
540         Interface J = b.intf("J").extend(I).build();
541         Interface K = b.intf("K").extend(I).build();
542         Interface L = b.intf("L").extend(I).build();
543         Interface M = b.intf("M").extend(I).build();
544 
545         ConcreteClass C = b.clazz("C").implement(J,K,L,M)
546             .build();
547 
548         b.test()
549                 .callSite(I, C, "m","()I")
550                 .returns(1)
551             .done()
552         .test()
553                 .callSite(J, C, "m","()I")
554                 .returns(1)
555             .done()
556         .test()
557                 .callSite(K, C, "m","()I")
558                 .returns(1)
559             .done()
560         .test()
561                 .callSite(L, C, "m","()I")
562                 .returns(1)
563             .done()
564         .test()
565                 .callSite(M, C, "m","()I")
566                 .returns(1)
567             .done()
568         .test()
569                 .callSite(C, C, "m","()I")
570                 .returns(1)
571             .done();
572     }
573 
574     /*
575      * SelfFill w/ explicit bridge
576      *
577      * interface I<T> { int m(T t) default { return 1; } }
578      * class C implements I<C> {
579      *   public int m(C s) { return 2; }
580      *   public int m(Object o) { ... }
581      * }
582      *
583      * TEST: I i = new C(); i.m((Object)null) == 2;
584      * TEST: C c = new C(); c.m((Object)null) == 2;
585      * TEST: C c = new C(); c.m((C)null) == 2;
586      */
testSelfFillWithExplicitBridge(TestBuilder b)587     public void testSelfFillWithExplicitBridge(TestBuilder b) {
588         /* interface I<T> { ... */
589         Interface I = b.intf("I").sig("<T:Ljava/lang/Object;>Ljava/lang/Object;")
590                     /* default int m(T t) { return 1; } */
591                     .defaultMethod("m", "(Ljava/lang/Object;)I")
592                         .sig("(TT;)I")
593                         .returns(1)
594                         .build()
595                 .build();
596 
597         /* class C implements I<C> { ... */
598         ConcreteClass C = b.clazz("C").implement(I)
599                 .sig("Ljava/lang/Object;LI<LC;>;")
600 
601                 /* public int m(I i) { return 2; } */
602                 .concreteMethod("m","(LC;)I").returns(2).build()
603 
604                 /* bridge method for m(LI;)I */
605                 .concreteMethod("m","(Ljava/lang/Object;)I")
606                     .flags(ACC_PUBLIC | ACC_BRIDGE | ACC_SYNTHETIC)
607                     .returns(2)
608                 .build()
609             .build();
610 
611         // I i = new C(); ...
612         b.test()
613                 .callSite(I, C, "m", "(Ljava/lang/Object;)I")
614                 .params(new NullParam())
615                 .returns(2)
616             .done()
617         // C c = new C(); ...
618         .test()
619                 .callSite(C, C, "m", "(Ljava/lang/Object;)I")
620                 .params(new NullParam())
621                 .returns(2)
622             .done()
623         .test()
624                 .callSite(C, C, "m", "(LC;)I")
625                 .params(new NullParam())
626                 .returns(2)
627             .done();
628     }
629 
630     /*
631      * interface I { int m() default { return 1; } }
632      * class C implements I { int m(int i) { return 2; } }
633      *
634      * TEST: C c = new C(); c.m(0) == 2;
635      * TEST: I i = new C(); i.m() == 1;
636      */
testMixedArity()637     public void testMixedArity() {
638         TestBuilder b = factory.getBuilder();
639 
640         Interface I =
641             b.intf("I")
642                 .defaultMethod("m", "()I").returns(1)
643                 .build()
644              .build();
645 
646         ConcreteClass C =
647              b.clazz("C").implement(I)
648                 .concreteMethod("m", "(I)I").returns(2)
649                 .build()
650               .build();
651 
652         b.test().callSite(I, C, "m", "()I")
653                 .returns(1)
654             .build();
655         b.test().callSite(C, C, "m", "(I)I").params(ICONST_0)
656                 .returns(2)
657             .build();
658     }
659 
660     /*
661      * interface I { int m() default { return 1; } }
662      * interface J { int m(int i) default { return 2; } }
663      * class C implements I, J {}
664      *
665      * TEST: I i = new C(); i.m() == 1;     i.m(0) ==> NSME
666      * TEST: J j = new C(); j.m() ==> NSME; j.m(0) == 2
667      * TEST: C c = new C(); c.m() == 1;     c.m(0) == 2
668      */
testConflictingDefaultMixedArity1(TestBuilder b)669     public void testConflictingDefaultMixedArity1(TestBuilder b) {
670         Interface I = b.intf("I")
671                 .defaultMethod("m", "()I").returns(1)
672                 .build()
673             .build();
674 
675         Interface J = b.intf("J")
676                 .defaultMethod("m", "(I)I").returns(2)
677                 .build()
678             .build();
679 
680         ConcreteClass C = b.clazz("C").implement(I,J).build();
681 
682 
683         // I i = new C(); ...
684         b.test().callSite(I, C, "m", "()I")
685                 .returns(1)
686             .build();
687         b.test().callSite(I, C, "m", "(I)I").params(ICONST_0)
688                 .throws_(NoSuchMethodError.class)
689             .build();
690 
691         // J j = new C(); ...
692         b.test().callSite(J, C, "m", "()I")
693                 .throws_(NoSuchMethodError.class)
694             .build();
695         b.test().callSite(J, C, "m", "(I)I").params(ICONST_0)
696                 .returns(2)
697             .build();
698 
699         // C c = new C(); ...
700         b.test().callSite(C, C, "m", "()I")
701                 .returns(1)
702             .build();
703         b.test().callSite(C, C, "m", "(I)I").params(ICONST_0)
704                 .returns(2)
705             .build();
706     }
707 
708     /*
709      * interface I { int m() default { return 1; } }
710      * interface J { int m() default { return 2; } }
711      * class C implements I, J {
712      *   int m(int i) { return 3; }
713      * }
714      *
715      * TEST: I i = new C(); i.m(0) ==> ICCE
716      * TEST: J j = new C(); j.m(0) ==> ICCE
717      * TEST: C c = new C(); c.m() ==> ICCE; c.m(0) == 3
718      */
testConflictingDefaultMixedArity2(TestBuilder b)719     public void testConflictingDefaultMixedArity2(TestBuilder b) {
720         Interface I = b.intf("I")
721                 .defaultMethod("m", "()I").returns(1)
722                 .build()
723             .build();
724 
725         Interface J = b.intf("J")
726                 .defaultMethod("m", "()I").returns(2)
727                 .build()
728             .build();
729 
730         ConcreteClass C = b.clazz("C").implement(I, J)
731                 .concreteMethod("m", "(I)I").returns(3)
732                 .build()
733             .build();
734 
735         // I i = new C(); ...
736         b.test().callSite(I, C, "m", "()I")
737                 .throws_(IncompatibleClassChangeError.class)
738             .build();
739         b.test().callSite(I, C, "m", "(I)I").params(ICONST_0)
740                 .throws_(NoSuchMethodError.class)
741             .build();
742 
743         // J j = new C(); ...
744         b.test().callSite(J, C, "m", "()I")
745                 .throws_(IncompatibleClassChangeError.class)
746             .build();
747         b.test().callSite(J, C, "m", "(I)I").params(ICONST_0)
748                 .throws_(NoSuchMethodError.class)
749             .build();
750 
751         // C c = new C(); ...
752         b.test().callSite(C, C, "m", "()I")
753                 .throws_(IncompatibleClassChangeError.class)
754             .build();
755         b.test().callSite(C, C, "m", "(I)I").params(ICONST_0)
756                 .returns(3)
757             .build();
758     }
759 
760     /* In package1:
761      * package p1;
762      * interface I {
763      *     default int m() { return 10; };
764      * }
765      * public interface J extends I {};
766      *
767      * In package2:
768      * class A implements p1.J {}
769      * A myA = new A;
770      * myA.m();  // should return 10 except for reflect mode,
771      *           // throw IllegalAccessException with reflect mode
772      */
773 
testMethodResolvedInDifferentPackage(TestBuilder b)774     public void testMethodResolvedInDifferentPackage(TestBuilder b) {
775         Interface I = b.intf("p1.I").flags(~ACC_PUBLIC & ACC_PUBLIC) // make it package private
776                 .defaultMethod("m", "()I").returns(10)
777                 .build()
778             .build();
779 
780         Interface J = b.intf("p1.J").extend(I)
781             .build();
782 
783         ConcreteClass myA = b.clazz("p2.A").implement(J)
784             .build();
785         if (!factory.getExecutionMode().equals("REFLECTION")) {
786             b.test()
787                 .callSite(myA, myA, "m", "()I")
788                 .returns(10)
789                 .done();
790         } else {
791             // -mode reflect will fail with IAE as expected
792             b.test()
793                 .callSite(myA, myA, "m", "()I")
794                 .throws_(IllegalAccessException.class)
795                 .done();
796         }
797     }
798 
799     /* In package p1:
800      * package p1;
801      * interface I {
802      *   public default int m() { return 12; };
803      * }
804      *
805      * public class A implements I {}
806      *
807      * In package p2:
808      * package p2;
809      * public interface J { int m(); }
810      *
811      * public class B extends p1.A implements J {
812      *   public int m() { return 13; }
813      * }
814      *
815      * Then:
816      *   A myA = new B;
817      *   myA.m();  // should return 13, not throw IllegalAccessError
818      */
819 
testMethodResolvedInLocalFirst(TestBuilder b)820     public void testMethodResolvedInLocalFirst(TestBuilder b) {
821         Interface I = b.intf("p1.I")
822                 .defaultMethod("m", "()I").returns(12)
823                 .build()
824             .build();
825 
826         ConcreteClass myA = b.clazz("p1.A").implement(I)
827             .build();
828 
829         Interface J = b.intf("p2.J").abstractMethod("m", "()I")
830                 .build()
831             .build();
832 
833         ConcreteClass myB = b.clazz("p2.B").extend(myA).implement(J)
834                  .concreteMethod("m", "()I").returns(13)
835                  .build()
836             .build();
837 
838         b.test()
839                 .callSite(myB, myB, "m", "()I")
840                 .returns(13)
841                 .done();
842     }
843 }
844