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.ConflictingDefaultsTest 38 */ 39 package vm.runtime.defmeth; 40 41 import java.util.Set; 42 43 import vm.runtime.defmeth.shared.DefMethTest; 44 import vm.runtime.defmeth.shared.annotation.NotApplicableFor; 45 import vm.runtime.defmeth.shared.builder.TestBuilder; 46 import vm.runtime.defmeth.shared.data.*; 47 48 import static jdk.internal.org.objectweb.asm.Opcodes.ACC_SYNCHRONIZED; 49 import static vm.runtime.defmeth.shared.data.method.body.CallMethod.Invoke.*; 50 import static vm.runtime.defmeth.shared.data.method.body.CallMethod.IndexbyteOp.*; 51 import static vm.runtime.defmeth.shared.ExecutionMode.*; 52 53 /** 54 * Tests on conflicting defaults. 55 * 56 * It is allowable to inherit a default through multiple paths (such as 57 * through a diamond-shaped interface hierarchy), but the resolution procedure 58 * is looking for a unique, most specific default-providing interface. 59 * 60 * If one default shadows another (where a subinterface provides a different 61 * default for an extension method declared in a superinterface), then the less 62 * specific interface is pruned from consideration no matter where it appears 63 * in the inheritance hierarchy. If two or more extended interfaces provide 64 * default implementations, and one is not a superinterface of the other, then 65 * neither is used and a linkage exception is thrown indicating conflicting 66 * default implementations. 67 */ 68 public class ConflictingDefaultsTest extends DefMethTest { main(String[] args)69 public static void main(String[] args) { 70 DefMethTest.runTest(ConflictingDefaultsTest.class, 71 /* majorVer */ Set.of(MIN_MAJOR_VER, MAX_MAJOR_VER), 72 /* flags */ Set.of(0, ACC_SYNCHRONIZED), 73 /* redefine */ Set.of(false, true), 74 /* execMode */ Set.of(DIRECT, REFLECTION, INVOKE_EXACT, INVOKE_GENERIC, INVOKE_WITH_ARGS, INDY)); 75 } 76 77 /* 78 * Conflict 79 * 80 * interface I { int m() default { return 1; } } 81 * interface J { int m() default { return 2; } } 82 * class C implements I, J {} 83 * 84 * TEST: C c = new C(); c.m() ==> ICCE 85 */ testConflict(TestBuilder b)86 public void testConflict(TestBuilder b) { 87 Interface I = b.intf("I") 88 .defaultMethod("m", "()I").returns(1).build() 89 .build(); 90 91 Interface J = b.intf("J") 92 .defaultMethod("m", "()I").returns(2).build() 93 .build(); 94 95 ConcreteClass C = b.clazz("C").implement(I,J).build(); 96 97 b.test().callSite(C, C, "m","()I") 98 .throws_(IncompatibleClassChangeError.class) 99 .done(); 100 } 101 102 /* 103 * Maximally-specific Default (0.6.3 spec change) 104 * 105 * interface I { int m(); } 106 * interface J { int m() default { return 2; } } 107 * class C implements I, J {} 108 * 109 * TEST: C c = new C(); c.m() return 2 110 */ testMaximallySpecificDefault(TestBuilder b)111 public void testMaximallySpecificDefault(TestBuilder b) { 112 Interface I = b.intf("I") 113 .abstractMethod("m", "()I").build() 114 .build(); 115 116 Interface J = b.intf("J") 117 .defaultMethod("m", "()I").returns(2).build() 118 .build(); 119 120 ConcreteClass C = b.clazz("C").implement(I,J).build(); 121 122 b.test().callSite(C, C, "m","()I") 123 .returns(2) 124 .done(); 125 } 126 127 /* 128 * Reabstract 129 * 130 * interface I { int m() default { return 1; } } 131 * interface J extends I { int m(); } 132 * class C implements J {} 133 * 134 * TEST: C c = new C(); c.m() ==> AME 135 */ testReabstract(TestBuilder b)136 public void testReabstract(TestBuilder b) { 137 Interface I = b.intf("I") 138 .defaultMethod("m", "()I").returns(1).build() 139 .build(); 140 141 Interface J = b.intf("J").extend(I) 142 .abstractMethod("m", "()I").build() 143 .build(); 144 145 ConcreteClass C = b.clazz("C").implement(J).build(); 146 147 b.test().callSite(C, C, "m","()I") 148 .throws_(AbstractMethodError.class) 149 .done(); 150 } 151 152 /* 153 * Reabstract2 154 * 155 * interface I { int m() default { return 1; } } 156 * interface J extends I { int m(); } 157 * class C implements J {} 158 * class D extends C { callSuper C.m} 159 * 160 * TEST: C c = new C(); c.m() ==> AME 161 * TEST: J j = new C(); j.m() ==> AME 162 * TEST: I i = new C(); i.m() ==> AME 163 * TEST: D d = new D(); d.m() ==> callSuper C.m ==> AME 164 */ testReabstract2(TestBuilder b)165 public void testReabstract2(TestBuilder b) { 166 Interface I = b.intf("I") 167 .defaultMethod("m", "()I").returns(1).build() 168 .build(); 169 170 Interface J = b.intf("J").extend(I) 171 .abstractMethod("m", "()I").build() 172 .build(); 173 174 ConcreteClass C = b.clazz("C").implement(J).build(); 175 ConcreteClass D = b.clazz("D").extend(C) 176 .concreteMethod("m", "()I").callSuper(C, "m", "()I").build() 177 .build(); 178 179 b.test().callSite(C, C, "m","()I") 180 .throws_(AbstractMethodError.class) 181 .done() 182 .test().callSite(J, C, "m","()I") 183 .throws_(AbstractMethodError.class) 184 .done() 185 .test().callSite(I, C, "m","()I") 186 .throws_(AbstractMethodError.class) 187 .done() 188 .test().callSite(D, D, "m","()I") 189 .throws_(AbstractMethodError.class) 190 .done(); 191 } 192 193 /* 194 * ReabstractConflictingDefaults 195 * 196 * interface I { int m() default { return 1; } } 197 * interface J { int m() default { return 2; } } 198 * interface K extends I,J { int m(); } 199 * class A implements I,J {} 200 * class C extends A implements K {} 201 * 202 * TEST: A c = new C(); c.m() ==> AME 203 */ testReabstractConflictingDefaults(TestBuilder b)204 public void testReabstractConflictingDefaults(TestBuilder b) { 205 Interface I = b.intf("I") 206 .defaultMethod("m", "()I").returns(1).build() 207 .build(); 208 209 Interface J = b.intf("J") 210 .defaultMethod("m", "()I").returns(2).build() 211 .build(); 212 213 Interface K = b.intf("K").extend(I,J) 214 .abstractMethod("m", "()I").build() 215 .build(); 216 217 ConcreteClass A = b.clazz("A").implement(I,J).build(); 218 ConcreteClass C = b.clazz("C").extend(A).implement(K).build(); 219 220 b.test().callSite(A, C, "m","()I") 221 .throws_(AbstractMethodError.class) 222 .done(); 223 } 224 225 226 /* 227 * ReabstractConflictingDefaultsInvokeInterface 228 * 229 * interface I { int m() default { return 1; } } 230 * interface J { int m() default { return 2; } } 231 * interface K extends I,J { int m(); } 232 * interface L extends K { } 233 * class A implements I,J {} 234 * class C extends A implements K {} 235 * class D extends C implements L {} 236 * 237 * TEST: I i = new A(); i.m() ==> ICCE 238 * TEST: K k = new C(); k.m() ==> AME 239 * TEST: L l = new D(); l.m() ==> AME 240 */ testReabstractConflictingDefaultsInvokeInterface(TestBuilder b)241 public void testReabstractConflictingDefaultsInvokeInterface(TestBuilder b) { 242 Interface I = b.intf("I") 243 .defaultMethod("m", "()I").returns(1).build() 244 .build(); 245 246 Interface J = b.intf("J") 247 .defaultMethod("m", "()I").returns(2).build() 248 .build(); 249 250 Interface K = b.intf("K").extend(I,J) 251 .abstractMethod("m", "()I").build() 252 .build(); 253 254 Interface L = b.intf("L").extend(K) 255 .build(); 256 257 ConcreteClass A = b.clazz("A").implement(I,J).build(); 258 ConcreteClass C = b.clazz("C").extend(A).implement(K).build(); 259 ConcreteClass D = b.clazz("D").extend(C).implement(L).build(); 260 261 b.test().callSite(I, A, "m","()I") 262 .throws_(IncompatibleClassChangeError.class) 263 .done() 264 .test().callSite(K, C, "m","()I") 265 .throws_(AbstractMethodError.class) 266 .done() 267 .test().callSite(L, D, "m","()I") 268 .throws_(AbstractMethodError.class) 269 .done(); 270 } 271 272 /* 273 * ReabstractConflictingDefaultsSuper 274 * 275 * interface I { int m() default { return 1; } } 276 * interface J { int m() default { return 2; } } 277 * interface K extends I,J { int m(); } 278 * interface L extends K { } 279 * class A implements I,J {} 280 * class C extends A implements K {} 281 * class D extends C implements L {int m() {callSuper A.m } 282 * 283 * TEST: I i = new A(); i.m() ==> ICCE 284 * TEST: K k = new C(); CallSuper k.m() ==> AME 285 * TEST: L l = new D(); l.m() ==> AME 286 */ testReabstractConflictingDefaultsSuper(TestBuilder b)287 public void testReabstractConflictingDefaultsSuper(TestBuilder b) { 288 Interface I = b.intf("I") 289 .defaultMethod("m", "()I").returns(1).build() 290 .build(); 291 292 Interface J = b.intf("J") 293 .defaultMethod("m", "()I").returns(2).build() 294 .build(); 295 296 Interface K = b.intf("K").extend(I,J) 297 .abstractMethod("m", "()I").build() 298 .build(); 299 300 Interface L = b.intf("L").extend(K) 301 .build(); 302 303 ConcreteClass A = b.clazz("A").implement(I,J).build(); 304 ConcreteClass C = b.clazz("C").extend(A).implement(K).build(); 305 ConcreteClass D = b.clazz("D").extend(C).implement(L) 306 .concreteMethod("m", "()I").callSuper(A, "m", "()I").build() 307 .build(); 308 309 b.test().callSite(I, A, "m","()I") 310 .throws_(IncompatibleClassChangeError.class) 311 .done() 312 .test().callSite(L, D, "m","()I") 313 .throws_(AbstractMethodError.class) 314 .done(); 315 } 316 317 /* 318 * testReabstractResolveMethod00705m2 319 * 320 * Test case for JDK-8027804: JCK resolveMethod test fails expecting AME 321 * 322 * This test is an extension of the JCK test resolveMethod00705m2 323 * with additional invoke* bytecodes specified for testing purposes. 324 * 325 * interface I { int m() default { return 1; } } 326 * interface J implements I { int m(); } 327 * class A implements J,I {} 328 * class C extends A {} 329 * 330 * TEST: A a = new C(); a.m() ==> AME (invokevirtual) 331 * C c = new C(); c.m() ==> AME (invokevirtual) 332 * J j = new C(); j.m() ==> AME (invokeinterface) 333 * I i = new C(); i.m() ==> AME (invokeinterface) 334 * c.test_Cmethod_ISMR(); c.super.m() ==> AME (invokespecial MR) 335 * a.test_Amethod_ISIMR(); j.super.m() ==> AME (invokespecial IMR) 336 * 337 * For ver > 49, error will be AME 338 * For ver = 49, error will be VE 339 */ 340 341 @NotApplicableFor(modes = { REDEFINITION }) // Can't redefine a class that gets error during loading testReabstractResolveMethod00705m2(TestBuilder b)342 public void testReabstractResolveMethod00705m2(TestBuilder b) { 343 Interface I = b.intf("I") 344 .defaultMethod("m", "()I").returns(1).build() 345 .build(); 346 347 Interface J = b.intf("J").extend(I) 348 .abstractMethod("m", "()I").build() 349 .build(); 350 351 ConcreteClass A = b.clazz("A").implement(J,I) 352 .concreteMethod("test_Amethod_ISIMR", "()V") 353 .invoke(SPECIAL, b.clazzByName("J"), b.clazzByName("A"), 354 "m", "()I", INTERFACEMETHODREF) 355 .build() 356 .build(); 357 358 ConcreteClass C = b.clazz("C").extend(A) 359 .concreteMethod("test_Cmethod_ISMR", "()V") 360 .invoke(SPECIAL, b.clazzByName("C"), b.clazzByName("C"), 361 "m", "()I", CALLSITE) 362 .build() 363 .build(); 364 365 Class expectedError1, expectedError2; 366 if (factory.getVer() >=52) { 367 expectedError1 = expectedError2 = AbstractMethodError.class; 368 } else { 369 expectedError1 = expectedError2 = VerifyError.class; 370 } 371 372 b.test().callSite(A, C, "m", "()I") 373 .throws_(expectedError2) 374 .done() 375 .test().callSite(C, C, "m", "()I") 376 .throws_(expectedError2) 377 .done() 378 .test().callSite(J, C, "m", "()I") 379 .throws_(expectedError1) 380 .done() 381 .test().callSite(I, C, "m", "()I") 382 .throws_(expectedError1) 383 .done() 384 .test().callSite(C, C, "test_Cmethod_ISMR", "()V") 385 .throws_(expectedError2) 386 .done() 387 .test().callSite(A, C, "test_Amethod_ISIMR", "()V") 388 .throws_(expectedError2) 389 .done(); 390 } 391 392 /* 393 * Shadow 394 * 395 * interface I { int m() default { return 1; } } 396 * interface J extends I { int m() default { return 2; } } 397 * class C implements J {} 398 * 399 * TEST: [I|J|C] c = new C(); c.m() == 2; 400 */ testShadow(TestBuilder b)401 public void testShadow(TestBuilder b) { 402 Interface I = b.intf("I") 403 .defaultMethod("m", "()I").returns(1).build() 404 .build(); 405 406 Interface J = b.intf("J").extend(I) 407 .defaultMethod("m", "()I").returns(2).build() 408 .build(); 409 410 ConcreteClass C = b.clazz("C").implement(J).build(); 411 412 b.test().callSite(I, C, "m","()I") 413 .returns(2) 414 .done() 415 .test() 416 .callSite(J, C, "m","()I") 417 .returns(2) 418 .done() 419 .test() 420 .callSite(C, C, "m","()I") 421 .returns(2) 422 .done(); 423 } 424 425 /* 426 * Disqualified 427 * 428 * interface I { int m() default { return 1; } } 429 * interface J extends I { int m() default { return 2; } } 430 * class C implements I, J {} 431 * 432 * TEST: [I|J|C] c = new C(); c.m() == 2; 433 */ testDisqualified(TestBuilder b)434 public void testDisqualified(TestBuilder b) { 435 Interface I = b.intf("I") 436 .defaultMethod("m", "()I").returns(1).build() 437 .build(); 438 439 Interface J = b.intf("J").extend(I) 440 .defaultMethod("m", "()I").returns(2).build() 441 .build(); 442 443 ConcreteClass C = b.clazz("C").implement(I,J).build(); 444 445 b.test() 446 .callSite(I, C, "m","()I") 447 .returns(2) 448 .done() 449 .test() 450 .callSite(J, C, "m","()I") 451 .returns(2) 452 .done() 453 .test() 454 .callSite(C, C, "m","()I") 455 .returns(2) 456 .done(); 457 } 458 459 /* 460 * Mixed arity 461 * 462 * interface I { int m() default { return 1; } } 463 * interface J { int m(int i) default { return 2; } } 464 * class C implements I, J {} 465 * 466 * TEST: I i = new C(); i.m() == 1; i.m(0) ==> NSME 467 * TEST: J j = new C(); j.m() ==> NSME; j.m(0) == 2 468 * TEST: C c = new C(); c.m() == 1; c.m(0) == 2 469 */ testMixedArity1(TestBuilder b)470 public void testMixedArity1(TestBuilder b) { 471 Interface I = b.intf("I") 472 .defaultMethod("m", "()I").returns(1).build() 473 .build(); 474 475 Interface J = b.intf("J") 476 .defaultMethod("m", "(I)I").returns(2).build() 477 .build(); 478 479 ConcreteClass C = b.clazz("C").implement(I,J).build(); 480 481 // I i = new C(); ... 482 b.test() 483 .callSite(I, C, "m","()I") 484 .returns(1) 485 .done() 486 .test() 487 .callSite(I, C, "m","(I)I") 488 .params(0) 489 .throws_(NoSuchMethodError.class) 490 .done() 491 492 // J j = new C(); ... 493 .test() 494 .callSite(J, C, "m","()I") 495 .throws_(NoSuchMethodError.class) 496 .done() 497 .test() 498 .callSite(J, C, "m","(I)I") 499 .params(0) 500 .returns(2) 501 .done() 502 503 // C c = new C(); ... 504 .test() 505 .callSite(C, C, "m","()I") 506 .returns(1) 507 .done() 508 .test() 509 .callSite(C, C, "m","(I)I") 510 .params(0) 511 .returns(2) 512 .done(); 513 } 514 515 /* 516 * Mixed arity 517 * 518 * interface I { int m() default { return 1; } } 519 * interface J { int m() default { return 2; } } 520 * class C implements I, J { int m(int i) { return 3; }} 521 * 522 * TEST: I i = new C(); i.m() ==> ICCE 523 * TEST: J j = new C(); j.m() ==> ICCE 524 * TEST: C c = new C(); c.m() ==> ICCE; c.m(0) == 3 525 */ testMixedArity2(TestBuilder b)526 public void testMixedArity2(TestBuilder b) { 527 Interface I = b.intf("I") 528 .defaultMethod("m", "()I").returns(1).build() 529 .build(); 530 531 Interface J = b.intf("J") 532 .defaultMethod("m", "()I").returns(2).build() 533 .build(); 534 535 ConcreteClass C = b.clazz("C").implement(I,J) 536 .concreteMethod("m", "(I)I").returns(3).build() 537 .build(); 538 539 // I i = new C(); ... 540 b.test() 541 .callSite(I, C, "m","()I") 542 .throws_(IncompatibleClassChangeError.class) 543 .done() 544 545 // J j = new C(); ... 546 .test() 547 .callSite(J, C, "m","()I") 548 .throws_(IncompatibleClassChangeError.class) 549 .done() 550 551 // C c = new C(); ... 552 .test() 553 .callSite(C, C, "m","()I") 554 .throws_(IncompatibleClassChangeError.class) 555 .done() 556 .test() 557 .callSite(C, C, "m","(I)I") 558 .params(0) 559 .returns(3) 560 .done(); 561 } 562 } 563