1 /* 2 * Copyright (c) 2017, 2018, 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 * @bug 8186046 8199875 27 * @summary Test basic invocation of bootstrap methods 28 * @library /java/lang/invoke/common 29 * @enablePreview 30 * @run testng CondyBSMInvocation 31 * @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:UseBootstrapCallInfo=3 CondyBSMInvocation 32 */ 33 34 35 import org.testng.Assert; 36 import org.testng.annotations.Test; 37 import test.java.lang.invoke.lib.InstructionHelper; 38 39 import java.lang.constant.ConstantDesc; 40 import java.lang.invoke.MethodHandle; 41 import java.lang.invoke.MethodHandles; 42 import java.lang.invoke.MethodType; 43 import java.lang.invoke.WrongMethodTypeException; 44 import java.util.Arrays; 45 import java.util.Collections; 46 import java.util.stream.IntStream; 47 import java.util.stream.Stream; 48 49 import static java.lang.invoke.MethodType.methodType; 50 51 public class CondyBSMInvocation { 52 static final MethodHandles.Lookup L = MethodHandles.lookup(); 53 54 55 @Test 56 public void testNonexistent() throws Throwable { 57 MethodHandle mh = InstructionHelper.ldcDynamicConstant( 58 L, "name", Object.class, 59 "bsm", methodType(Object.class) 60 ); 61 62 try { 63 mh.invoke(); 64 Assert.fail("NoSuchMethodError expected to be thrown"); 65 } catch (NoSuchMethodError e) { 66 } 67 } 68 69 static MethodHandle[] bsms(String bsmName) { 70 return Stream.of(CondyBSMInvocation.class.getDeclaredMethods()). 71 filter(m -> m.getName().equals(bsmName)). 72 map(m -> { 73 try { 74 return MethodHandles.lookup().unreflect(m); 75 } catch (IllegalAccessException e) { 76 throw new RuntimeException(); 77 } 78 }).toArray(MethodHandle[]::new); 79 } 80 81 public static Object shape_bsm() { 82 return "0"; 83 } 84 85 public static Object shape_bsm(Object a1) { 86 return "0"; 87 } 88 89 public static Object shape_bsm(Object... args) { 90 return "0"; 91 } 92 93 public static Object shape_bsm(Object a1, Object a2) { 94 return "0"; 95 } 96 97 public static Object shape_bsm(Object a1, Object... args) { 98 return "0"; 99 } 100 101 public static Object shape_bsm(Object a1, Object a2, Object a3) { 102 return "0"; 103 } 104 105 public static Object shape_bsm(MethodHandles.Lookup a1) { 106 return "0"; 107 } 108 109 @Test 110 public void testWrongShape() throws Throwable { 111 for (MethodHandle bsm : bsms("shape_bsm")) { 112 MethodHandle mh = InstructionHelper.ldcDynamicConstant( 113 L, "name", Object.class, 114 "shape_bsm", bsm.type() 115 ); 116 117 try { 118 Object r = mh.invoke(); 119 Assert.fail("BootstrapMethodError expected to be thrown for " + bsm); 120 } catch (BootstrapMethodError e) { 121 } 122 } 123 } 124 125 126 public static Object sig_bsm(MethodHandles.Lookup a1, String[] a2) { 127 return "0"; 128 } 129 130 public static Object sig_bsm(MethodHandles.Lookup a1, String a2, String a3) { 131 return "0"; 132 } 133 134 @Test 135 public void testWrongSignature() throws Throwable { 136 for (MethodHandle bsm : bsms("sig_bsm")) { 137 MethodHandle mh = InstructionHelper.ldcDynamicConstant( 138 L, "name", Object.class, 139 "sig_bsm", bsm.type() 140 ); 141 142 try { 143 Object r = mh.invoke(); 144 Assert.fail("BootstrapMethodError expected to be thrown for " + bsm); 145 } catch (BootstrapMethodError e) { 146 } 147 } 148 } 149 150 151 public static Object bsm(MethodHandles.Lookup l, String name, Class<?> type) { 152 return "0"; 153 } 154 155 public static Object bsm(MethodHandles.Lookup l, String name, Class<?> type, 156 Object a1) { 157 assertAll(a1); 158 return "1"; 159 } 160 161 public static Object bsm(MethodHandles.Lookup l, String name, Class<?> type, 162 Object a1, Object a2) { 163 assertAll(a1, a2); 164 return "2"; 165 } 166 167 public static Object bsm(MethodHandles.Lookup l, String name, Class<?> type, 168 Object a1, Object a2, Object a3) { 169 assertAll(a1, a2, a3); 170 return "3"; 171 } 172 173 public static Object bsm(MethodHandles.Lookup l, String name, Class<?> type, 174 Object a1, Object a2, Object a3, Object a4) { 175 assertAll(a1, a2, a3, a4); 176 return "4"; 177 } 178 179 public static Object bsm(MethodHandles.Lookup l, String name, Class<?> type, 180 Object a1, Object a2, Object a3, Object a4, Object a5) { 181 assertAll(a1, a2, a3, a4, a5); 182 return "5"; 183 } 184 185 public static Object bsm(MethodHandles.Lookup l, String name, Class<?> type, 186 Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { 187 assertAll(a1, a2, a3, a4, a5, a6); 188 return "6"; 189 } 190 191 public static Object bsm(MethodHandles.Lookup l, String name, Class<?> type, 192 Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { 193 assertAll(a1, a2, a3, a4, a5, a6, a7); 194 return "7"; 195 } 196 197 public static Object bsm(MethodHandles.Lookup l, Object... args) { 198 Object[] staticArgs = Arrays.copyOfRange(args, 2, args.length); 199 assertAll(staticArgs); 200 return Integer.toString(staticArgs.length); 201 } 202 203 static void assertAll(Object... as) { 204 for (int i = 0; i < as.length; i++) { 205 Assert.assertEquals(as[i], i); 206 } 207 } 208 209 @Test 210 public void testArity() throws Throwable { 211 for (int i = 0; i < 8; i++) { 212 final int n = i; 213 MethodType mt = methodType(Object.class, MethodHandles.Lookup.class, String.class, Class.class) 214 .appendParameterTypes(Collections.nCopies(n, Object.class)); 215 MethodHandle mh = InstructionHelper.ldcDynamicConstant( 216 L, "name", Object.class, 217 "bsm", mt, 218 IntStream.range(0, n).boxed().toArray(ConstantDesc[]::new) 219 ); 220 221 Object r = mh.invoke(); 222 Assert.assertEquals(r, Integer.toString(n)); 223 } 224 225 { 226 MethodType mt = methodType(Object.class, MethodHandles.Lookup.class, Object[].class); 227 MethodHandle mh = InstructionHelper.ldcDynamicConstant( 228 L, "name", Object.class, 229 "bsm", mt, 230 IntStream.range(0, 9).boxed().toArray(ConstantDesc[]::new) 231 ); 232 233 Object r = mh.invoke(); 234 Assert.assertEquals(r, Integer.toString(9)); 235 236 } 237 } 238 239 @Test 240 public void testWrongNumberOfStaticArguments() throws Throwable { 241 for (int i = 1; i < 8; i++) { 242 final int n = i; 243 MethodType mt = methodType(Object.class, MethodHandles.Lookup.class, String.class, Class.class) 244 .appendParameterTypes(Collections.nCopies(n, Object.class)); 245 MethodHandle mh = InstructionHelper.ldcDynamicConstant( 246 L, "name", Object.class, 247 "bsm", mt, 248 IntStream.range(0, n - 1).boxed().toArray(ConstantDesc[]::new) 249 ); 250 251 try { 252 Object r = mh.invoke(); 253 Assert.fail("BootstrapMethodError expected to be thrown for arrity " + n); 254 } catch (BootstrapMethodError e) { 255 Throwable t = e.getCause(); 256 Assert.assertTrue(WrongMethodTypeException.class.isAssignableFrom(t.getClass())); 257 } 258 } 259 } 260 }