Path: blob/jdk8u272-b10-aarch32-20201026/jdk/test/java/lang/invoke/lambda/MetafactoryParameterCastTest.java
48795 views
/*1* Copyright (c) 2014, 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* @bug 803577626* @summary Ensure that invocation parameters are always cast to the instantiatedMethodType27*/28import java.lang.invoke.*;29import java.util.Arrays;30import static java.lang.invoke.MethodType.methodType;3132public class MetafactoryParameterCastTest {3334static final MethodHandles.Lookup lookup = MethodHandles.lookup();3536public static class A {37}3839public static class B extends A {40void instance0() {}41void instance1(B arg) {}42static void static1(B arg) {}43static void static2(B arg1, B arg2) {}44}4546public static class C extends B {}47public static class NotC extends B {}4849public interface ASink { void take(A arg); }50public interface BSink { void take(B arg); }5152public static void main(String... args) throws Throwable {53new MetafactoryParameterCastTest().test();54}5556void test() throws Throwable {57MethodType takeA = methodType(void.class, A.class);58MethodType takeB = methodType(void.class, B.class);59MethodType takeC = methodType(void.class, C.class);6061Class<?>[] noCapture = {};62Class<?>[] captureB = { B.class };6364MethodHandle[] oneBParam = { lookup.findVirtual(B.class, "instance0", methodType(void.class)),65lookup.findStatic(B.class, "static1", methodType(void.class, B.class)) };66MethodHandle[] twoBParams = { lookup.findVirtual(B.class, "instance1", methodType(void.class, B.class)),67lookup.findStatic(B.class, "static2", methodType(void.class, B.class, B.class)) };6869for (MethodHandle mh : oneBParam) {70// sam71tryASink(invokeMetafactory(mh, ASink.class, "take", noCapture, takeC, takeA));72tryBSink(invokeMetafactory(mh, BSink.class, "take", noCapture, takeC, takeB));73tryASink(invokeAltMetafactory(mh, ASink.class, "take", noCapture, takeC, takeA));74tryBSink(invokeAltMetafactory(mh, BSink.class, "take", noCapture, takeC, takeB));7576// bridge77tryASink(invokeAltMetafactory(mh, ASink.class, "take", noCapture, takeC, takeC, takeA));78tryBSink(invokeAltMetafactory(mh, BSink.class, "take", noCapture, takeC, takeC, takeB));79}8081for (MethodHandle mh : twoBParams) {82// sam83tryCapASink(invokeMetafactory(mh, ASink.class, "take", captureB, takeC, takeA));84tryCapBSink(invokeMetafactory(mh, BSink.class, "take", captureB, takeC, takeB));85tryCapASink(invokeAltMetafactory(mh, ASink.class, "take", captureB, takeC, takeA));86tryCapBSink(invokeAltMetafactory(mh, BSink.class, "take", captureB, takeC, takeB));8788// bridge89tryCapASink(invokeAltMetafactory(mh, ASink.class, "take", captureB, takeC, takeC, takeA));90tryCapBSink(invokeAltMetafactory(mh, BSink.class, "take", captureB, takeC, takeC, takeB));91}92}9394void tryASink(CallSite cs) throws Throwable {95ASink sink = (ASink) cs.dynamicInvoker().invoke();96tryASink(sink);97}9899void tryCapASink(CallSite cs) throws Throwable {100ASink sink = (ASink) cs.dynamicInvoker().invoke(new B());101tryASink(sink);102}103104void tryBSink(CallSite cs) throws Throwable {105BSink sink = (BSink) cs.dynamicInvoker().invoke();106tryBSink(sink);107}108109void tryCapBSink(CallSite cs) throws Throwable {110BSink sink = (BSink) cs.dynamicInvoker().invoke(new B());111tryBSink(sink);112}113114void tryASink(ASink sink) {115try { sink.take(new C()); }116catch (ClassCastException e) {117throw new AssertionError("Unexpected cast failure: " + e + " " + lastMFParams());118}119120try {121sink.take(new B());122throw new AssertionError("Missing cast from A to C: " + lastMFParams());123}124catch (ClassCastException e) { /* expected */ }125126try {127sink.take(new NotC());128throw new AssertionError("Missing cast from A to C: " + lastMFParams());129}130catch (ClassCastException e) { /* expected */ }131}132133void tryBSink(BSink sink) {134try { sink.take(new C()); }135catch (ClassCastException e) {136throw new AssertionError("Unexpected cast failure: " + e + " " + lastMFParams());137}138139try {140sink.take(new B());141throw new AssertionError("Missing cast from B to C: " + lastMFParams());142}143catch (ClassCastException e) { /* expected */ }144145try {146sink.take(new NotC());147throw new AssertionError("Missing cast from B to C: " + lastMFParams());148}149catch (ClassCastException e) { /* expected */ }150}151152MethodHandle lastMH;153Class<?>[] lastCaptured;154MethodType lastInstMT;155MethodType lastSamMT;156MethodType[] lastBridgeMTs;157158String lastMFParams() {159return "mh=" + lastMH +160", captured=" + Arrays.toString(lastCaptured) +161", instMT=" + lastInstMT +162", samMT=" + lastSamMT +163", bridgeMTs=" + Arrays.toString(lastBridgeMTs);164}165166CallSite invokeMetafactory(MethodHandle mh, Class<?> sam, String methodName,167Class<?>[] captured, MethodType instMT, MethodType samMT) {168lastMH = mh;169lastCaptured = captured;170lastInstMT = instMT;171lastSamMT = samMT;172lastBridgeMTs = new MethodType[]{};173try {174return LambdaMetafactory.metafactory(lookup, methodName, methodType(sam, captured),175samMT, mh, instMT);176}177catch (LambdaConversionException e) {178// unexpected linkage error179throw new RuntimeException(e);180}181}182183CallSite invokeAltMetafactory(MethodHandle mh, Class<?> sam, String methodName,184Class<?>[] captured, MethodType instMT,185MethodType samMT, MethodType... bridgeMTs) {186lastMH = mh;187lastCaptured = captured;188lastInstMT = instMT;189lastSamMT = samMT;190lastBridgeMTs = bridgeMTs;191try {192boolean bridge = bridgeMTs.length > 0;193Object[] args = new Object[bridge ? 5+bridgeMTs.length : 4];194args[0] = samMT;195args[1] = mh;196args[2] = instMT;197args[3] = bridge ? LambdaMetafactory.FLAG_BRIDGES : 0;198if (bridge) {199args[4] = bridgeMTs.length;200for (int i = 0; i < bridgeMTs.length; i++) args[5+i] = bridgeMTs[i];201}202return LambdaMetafactory.altMetafactory(lookup, methodName, methodType(sam, captured), args);203}204catch (LambdaConversionException e) {205// unexpected linkage error206throw new RuntimeException(e);207}208}209210}211212213