Path: blob/master/test/hotspot/jtreg/vmTestbase/vm/runtime/defmeth/DefaultVsAbstractTest.java
41159 views
/*1* Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25*26* @modules java.base/jdk.internal.org.objectweb.asm:+open java.base/jdk.internal.org.objectweb.asm.util:+open27* @library /vmTestbase /test/lib28*29* @comment build retransform.jar in current dir30* @run driver vm.runtime.defmeth.shared.BuildJar31*32* @run driver jdk.test.lib.FileInstaller . .33* @run main/othervm/native34* -agentlib:redefineClasses35* -javaagent:retransform.jar36* vm.runtime.defmeth.DefaultVsAbstractTest37*/38package vm.runtime.defmeth;3940import java.util.Set;4142import vm.runtime.defmeth.shared.DefMethTest;43import vm.runtime.defmeth.shared.data.*;44import vm.runtime.defmeth.shared.builder.TestBuilder;4546import static jdk.internal.org.objectweb.asm.Opcodes.ACC_SYNCHRONIZED;47import static vm.runtime.defmeth.shared.ExecutionMode.*;4849/**50* Tests on interaction of default methods with abstract methods51*52* The rule: "the superclass always wins."53*54* In searching the superclass hierarchy, a declaration in a superclass is55* preferred to a default in an interface. This preference includes abstract56* methods in superclasses as well; the defaults are only considered when57* the entire implementation hierarchy is silent on the status of the method58* in question.59*/60public class DefaultVsAbstractTest extends DefMethTest {6162public static void main(String[] args) {63DefMethTest.runTest(DefaultVsAbstractTest.class,64/* majorVer */ Set.of(MIN_MAJOR_VER, MAX_MAJOR_VER),65/* flags */ Set.of(0, ACC_SYNCHRONIZED),66/* redefine */ Set.of(false, true),67/* execMode */ Set.of(DIRECT, REFLECTION, INVOKE_EXACT, INVOKE_GENERIC, INVOKE_WITH_ARGS, INDY));68}6970/*71* interface I { public int m() default { return 1; } }72* class C implements I { public abstract int m(); }73*74* TEST: new C() throws InstantiationError75*/76public void test0(TestBuilder b) {77Interface I = b.intf("I")78.defaultMethod("m", "()I").returns(1).build()79.build();8081ConcreteClass C = b.clazz("C").implement(I)82.abstractMethod("m", "()I").build()83.build();8485b.test()86.callSite(I, C, "m", "()I")87.throws_(InstantiationError.class)88.done();89}9091/*92* interface I {93* public int m() default { return 1; }94* }95* class C implements I {96* public abstract int m();97* }98* class D extends C {}99*100* TEST: I i = new D(); i.m() ==> AME101* TEST: C c = new D(); c.m() ==> AME102* TEST: D d = new D(); d.m() ==> AME103*/104public void test1(TestBuilder b) {105Interface I = b.intf("I")106.defaultMethod("m", "()I").returns(1).build()107.build();108109ConcreteClass C = b.clazz("C").implement(I)110.abstractMethod("m", "()I").build()111.build();112113ConcreteClass D = b.clazz("D").extend(C).build();114115b.test()116.callSite(I, D, "m", "()I")117.throws_(AbstractMethodError.class)118.done()119.test()120.callSite(C, D, "m", "()I")121.throws_(AbstractMethodError.class)122.done()123.test()124.callSite(D, D, "m", "()I")125.throws_(AbstractMethodError.class)126.done();127}128129/*130* interface I {131* default public int m() { return 1; }132* }133* class C {134* abstract public int m();135* }136* class D extends C implements I {}137*138* TEST: I o = new D(); o.m()I throws AME139* TEST: C o = new D(); o.m()I throws AME140* TEST: D o = new D(); o.m()I throws AME141*/142public void test2(TestBuilder b) {143Interface I = b.intf("I")144.defaultMethod("m", "()I").returns(1).build()145.build();146147ConcreteClass C = b.clazz("C")148.abstractMethod("m", "()I").build()149.build();150151ConcreteClass D = b.clazz("D").extend(C).implement(I).build();152153b.test()154.callSite(I, D, "m", "()I")155.throws_(AbstractMethodError.class)156.done()157.test()158.callSite(C, D, "m", "()I")159.throws_(AbstractMethodError.class)160.done()161.test()162.callSite(D, D, "m", "()I")163.throws_(AbstractMethodError.class)164.done();165}166167/*168* interface I {169* default public int m() { return 1; }170* }171* class C {172* abstract public int m();173* }174* class D extends C implements I {175* public int m() { return 2; }176* }177*178* TEST: I o = new D(); o.m()I == 2179* TEST: C o = new D(); o.m()I == 2180* TEST: D o = new D(); o.m()I == 2181*/182public void test3(TestBuilder b) {183Interface I = b.intf("I")184.defaultMethod("m", "()I").returns(1).build()185.build();186187ConcreteClass C = b.clazz("C")188.abstractMethod("m", "()I").build()189.build();190191ConcreteClass D = b.clazz("D").extend(C).implement(I)192.concreteMethod("m", "()I").returns(2)193.build()194.build();195196b.test() // I i = new D(); ...197.callSite(I, D, "m", "()I").returns(2)198.done()199.test() // C c = new D(); ...200.callSite(C, D, "m", "()I").returns(2)201.done()202.test() // D d = new C(); ...203.callSite(D, D, "m", "()I").returns(2)204.done();205}206207/*208* interface I {209* default public int m() { return 1; }210* }211* class E {212* abstract public int m();213* }214* class D extends E {}215* class C extends D implements I {}216*217* TEST: I o = new C(); o.m()I throws AME218* TEST: E o = new C(); o.m()I throws AME219* TEST: D o = new C(); o.m()I throws AME220* TEST: C o = new C(); o.m()I throws AME221*/222public void test4(TestBuilder b) {223Interface I = b.intf("I")224.defaultMethod("m", "()I").returns(1).build()225.build();226227ConcreteClass E = b.clazz("E")228.abstractMethod("m", "()I").build()229.build();230231ConcreteClass D = b.clazz("D").extend(E).build();232233ConcreteClass C = b.clazz("C").extend(D).implement(I).build();234235b.test() // I i = new C(); ...236.callSite(I, C, "m", "()I")237.throws_(AbstractMethodError.class)238.done()239.test() // E e = new C(); ...240.callSite(E, C, "m", "()I")241.throws_(AbstractMethodError.class)242.done()243.test() // D d = new C(); ...244.callSite(D, C, "m", "()I")245.throws_(AbstractMethodError.class)246.done()247.test() // C c = new C(); ...248.callSite(C, C, "m", "()I")249.throws_(AbstractMethodError.class)250.done();251}252253/*254* interface I {255* default public int m() { return 1; }256* }257* class E {258* abstract public int m();259* }260* class D extends E {261* public int m() { return 2; }262* }263* class C extends D implements I {}264*265* TEST: I o = new C(); o.m()I == 2266* TEST: I o = new C(); o.m()I == 2267* TEST: I o = new C(); o.m()I == 2268* TEST: I o = new C(); o.m()I == 2269*/270public void test5(TestBuilder b) {271Interface I = b.intf("I")272.defaultMethod("m", "()I").returns(1).build()273.build();274275ConcreteClass E = b.clazz("E")276.abstractMethod("m", "()I").build()277.build();278279ConcreteClass D = b.clazz("D").extend(E)280.concreteMethod("m", "()I").returns(2).build()281.build();282283ConcreteClass C = b.clazz("C").extend(D).implement(I).build();284285b.test() // I i = new C(); ...286.callSite(I, C, "m", "()I")287.returns(2)288.done()289.test() // E e = new C(); ...290.callSite(I, C, "m", "()I")291.returns(2)292.done()293.test() // D d = new C(); ...294.callSite(I, C, "m", "()I")295.returns(2)296.done()297.test() // C c = new C(); ...298.callSite(I, C, "m", "()I")299.returns(2)300.done();301}302303/*304* interface I {305* default public int m() { return 1; }306* }307* interface J {308* default public int m() { return 2; }309* }310* class E {311* abstract public int m();312* }313* class D extends E {314* public int m() { return 3; }315* }316* class C extends D implements I, J {}317*318* TEST: I o = new C(); o.m()I == 3319* TEST: J o = new C(); o.m()I == 3320* TEST: E o = new C(); o.m()I == 3321* TEST: D o = new C(); o.m()I == 3322* TEST: J o = new C(); o.m()I == 3323*/324public void test6(TestBuilder b) {325Interface I = b.intf("I")326.defaultMethod("m", "()I").returns(1).build()327.build();328329Interface J = b.intf("J")330.defaultMethod("m", "()I").returns(2).build()331.build();332333ConcreteClass E = b.clazz("E")334.abstractMethod("m", "()I").build()335.build();336337ConcreteClass D = b.clazz("D").extend(E)338.concreteMethod("m", "()I").returns(3).build()339.build();340341ConcreteClass C = b.clazz("C").extend(D).implement(I, J).build();342343344b.test() // I i = new C(); ...345.callSite(I, C, "m", "()I").returns(3)346.done()347.test() // J j = new C(); ...348.callSite(J, C, "m", "()I").returns(3)349.done()350.test() // E e = new C(); ...351.callSite(E, C, "m", "()I").returns(3)352.done()353.test() // D d = new C(); ...354.callSite(D, C, "m", "()I").returns(3)355.done()356.test() // C c = new C(); ...357.callSite(J, C, "m", "()I").returns(3)358.done();359}360361/*362* interface I {363* abstract public int m();364* }365*366* interface J {367* default public int m() { return 1; }368* }369*370* class A implements I;371*372* class B extends A implements J;373*374* TEST: A o = new B(); o.m()I375* returns 1 for REFLECTION and INVOKE_WITH_ARGS376* ICCE for other modes377*/378public void testInvokeInterfaceClassDefaultMethod(TestBuilder b) {379Interface I = b.intf("I")380.abstractMethod("m", "()I").build()381.build();382383Interface J = b.intf("J")384.extend(I)385.defaultMethod("m", "()I").returns(1).build()386.build();387388ConcreteClass A = b.clazz("A").implement(I).build();389390ConcreteClass B = b.clazz("B").extend(A).implement(J).build();391392String exeMode = factory.getExecutionMode();393394// the test passes in the reflection mode because there's no way to395// express invokeinterface on a class using Reflection API396// In the test generator, vm.runtime.defmeth.shared.executor.ReflectionTest,397// the invokeinterface is switched to invokevirtual.398//399// the test passes in the INVOKE_WITH_ARGS mode due to the fix for400// JDK-8032010 to conform with the removal of the following check401// during method resolution in JVMS-5.4.3.3 Method Resolution402// "If method lookup succeeds and the method is abstract, but C is not403// abstract, method resolution throws an AbstractMethodError."404if (exeMode.equals("REFLECTION") ||405exeMode.equals("INVOKE_WITH_ARGS")) {406b.test().interfaceCallSite(A, B, "m", "()I")407.returns(1).done();408} else {409// ICCE in other modes due to410// JVMS-5.4.3.4. Interface Method Resolution411// When resolving an interface method reference:412// If C is not an interface, interface method resolution throws an IncompatibleClassChangeError.413b.test().interfaceCallSite(A, B, "m", "()I")414.throws_(IncompatibleClassChangeError.class).done();415}416}417418/*419* interface I {420* abstract public int m();421* }422*423* interface J {424* abstract public int m();425* }426*427* class A implements I;428*429* class B extends A implements J;430*431* TEST: A o = new B(); o.m()I throws ICCE432*/433public void testInvokeInterfaceClassAbstractMethod(TestBuilder b) {434Interface I = b.intf("I")435.abstractMethod("m", "()I").build()436.build();437438Interface J = b.intf("J")439.abstractMethod("m", "()I").build()440.build();441442ConcreteClass A = b.clazz("A").implement(I).build();443444ConcreteClass B = b.clazz("B").extend(A).implement(J).build();445446// JVMS-5.4.3.4. Interface Method Resolution447// When resolving an interface method reference:448// If C is not an interface, interface method resolution throws an IncompatibleClassChangeError.449b.test().interfaceCallSite(A, B, "m", "()I")450.throws_(IncompatibleClassChangeError.class).done();451}452453/*454* interface I {455* public int m() default { return 1; }456* }457*458* interface J {459* public int m() default { return 1; }460* }461*462* class A implements I;463*464* class B extends A implements J;465*466* TEST: A o = new B(); o.m()I throws ICCE467*/468public void testInvokeInterfaceMultipleDefinedClassDefaultMethod(TestBuilder b) {469Interface I = b.intf("I")470.defaultMethod("m", "()I").returns(1).build()471.build();472473Interface J = b.intf("J")474.defaultMethod("m", "()I").returns(1).build()475.build();476477ConcreteClass A = b.clazz("A").implement(I).build();478479ConcreteClass B = b.clazz("B").extend(A).implement(J).build();480481// JVMS-5.4.3.4. Interface Method Resolution482// When resolving an interface method reference:483// If C is not an interface, interface method resolution throws an IncompatibleClassChangeError.484b.test().interfaceCallSite(A, B, "m", "()I")485.throws_(IncompatibleClassChangeError.class).done();486}487488}489490491