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 /lib/testlibrary/bytecode /java/lang/invoke/common 29 * @build jdk.experimental.bytecode.BasicClassBuilder test.java.lang.invoke.lib.InstructionHelper 30 * @run testng/timeout=999999 CondyBSMInvocation 31 */ 32 33 34 import org.testng.Assert; 35 import org.testng.annotations.Test; 36 import test.java.lang.invoke.lib.InstructionHelper; 37 38 import java.lang.invoke.MethodHandle; 39 import java.lang.invoke.MethodHandles; 40 import java.lang.invoke.MethodType; 41 import java.lang.invoke.WrongMethodTypeException; 42 import java.util.Arrays; 43 import java.util.Collections; 44 import java.util.stream.IntStream; 45 import java.util.stream.Stream; 46 47 import static java.lang.invoke.MethodType.methodType; 48 49 public class CondyBSMInvocation { 50 static final MethodHandles.Lookup L = MethodHandles.lookup(); 51 52 53 @Test 54 public void testNonexistent() throws Throwable { 55 MethodHandle mh = InstructionHelper.ldcDynamicConstant( 56 L, "invoke", Object.class, 57 "noSuchMethod", methodType(Object.class), 58 S -> {}); 59 60 try { 61 mh.invoke(); 62 Assert.fail("NoSuchMethodError expected to be thrown"); 63 } catch (NoSuchMethodError e) { 64 } 65 } 66 67 @Test 68 public void testBadExpr() throws Throwable { 69 MethodHandle mh = InstructionHelper.ldcDynamicConstant( 70 L, "noSuchExprMode", Object.class, 71 "bsm", methodType(Object.class), 72 S -> {}); 73 74 try { 75 mh.invoke(); 76 Assert.fail("BootstrapMethodError expected to be thrown"); 77 } catch (BootstrapMethodError e) { 78 Assert.assertEquals(e.getCause().getClass(), IllegalArgumentException.class); 79 // Example: java.lang.IllegalArgumentException: invalid name 80 // for expression-mode constant: CondyBSMInvocation.bsm()Object 81 // /invokeStatic/noSuchExprMode:class java.lang.Object[] 82 83 } 84 } 85 86 static MethodHandle[] bsms(String bsmName) { 87 return Stream.of(CondyBSMInvocation.class.getDeclaredMethods()). 88 filter(m -> m.getName().equals(bsmName)). 89 map(m -> { 90 try { 91 return MethodHandles.lookup().unreflect(m); 92 } catch (IllegalAccessException e) { 93 throw new RuntimeException(); 94 } 95 }).toArray(MethodHandle[]::new); 96 } 97 98 public static Object shape_bsm() { 99 return "0"; 100 } 101 102 public static Object shape_bsm(Object a1) { 103 return "0"; 104 } 105 106 public static Object shape_bsm(Object... args) { 107 return "0"; 108 } 109 110 public static Object shape_bsm(Object a1, Object a2) { 111 return "0"; 112 } 113 114 public static Object shape_bsm(Object a1, Object... args) { 115 return "0"; 116 } 117 118 public static Object shape_bsm(Object a1, Object a2, Object a3) { 119 return "0"; 120 } 121 122 public static Object shape_bsm(MethodHandles.Lookup a1) { 123 return "0"; 124 } 125 126 @Test 127 public void testWrongShape() throws Throwable { 128 for (MethodHandle bsm : bsms("shape_bsm")) { 129 MethodHandle mh = InstructionHelper.ldcDynamicConstant( 130 L, "name", Object.class, 131 "shape_bsm", bsm.type(), 132 S -> {} 133 ); 134 135 try { 136 Object r = mh.invoke(); 137 Assert.fail("BootstrapMethodError expected to be thrown for " + bsm); 138 } catch (BootstrapMethodError e) { 139 } 140 } 141 } 142 143 144 public static Object sig_bsm(MethodHandles.Lookup a1, String[] a2) { 145 return "0"; 146 } 147 148 public static Object sig_bsm(MethodHandles.Lookup a1, String a2, String a3) { 149 return "0"; 150 } 151 152 @Test 153 public void testWrongSignature() throws Throwable { 154 for (MethodHandle bsm : bsms("sig_bsm")) { 155 MethodHandle mh = InstructionHelper.ldcDynamicConstant( 156 L, "name", Object.class, 157 "sig_bsm", bsm.type(), 158 S -> {} 159 ); 160 161 try { 162 Object r = mh.invoke(); 163 Assert.fail("BootstrapMethodError expected to be thrown for " + bsm); 164 } catch (BootstrapMethodError e) { 165 } 166 } 167 } 168 169 170 public static Object bsm(MethodHandles.Lookup l, String name, Class<?> type) { 171 return "0"; 172 } 173 174 public static Object bsm(MethodHandles.Lookup l, String name, Class<?> type, 175 Object a1) { 176 assertAll(a1); 177 return "1"; 178 } 179 180 public static Object bsm(MethodHandles.Lookup l, String name, Class<?> type, 181 Object a1, Object a2) { 182 assertAll(a1, a2); 183 return "2"; 184 } 185 186 public static Object bsm(MethodHandles.Lookup l, String name, Class<?> type, 187 Object a1, Object a2, Object a3) { 188 assertAll(a1, a2, a3); 189 return "3"; 190 } 191 192 public static Object bsm(MethodHandles.Lookup l, String name, Class<?> type, 193 Object a1, Object a2, Object a3, Object a4) { 194 assertAll(a1, a2, a3, a4); 195 return "4"; 196 } 197 198 public static Object bsm(MethodHandles.Lookup l, String name, Class<?> type, 199 Object a1, Object a2, Object a3, Object a4, Object a5) { 200 assertAll(a1, a2, a3, a4, a5); 201 return "5"; 202 } 203 204 public static Object bsm(MethodHandles.Lookup l, String name, Class<?> type, 205 Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { 206 assertAll(a1, a2, a3, a4, a5, a6); 207 return "6"; 208 } 209 210 public static Object bsm(MethodHandles.Lookup l, String name, Class<?> type, 211 Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { 212 assertAll(a1, a2, a3, a4, a5, a6, a7); 213 return "7"; 214 } 215 216 public static Object bsm(MethodHandles.Lookup l, Object... args) { 217 Object[] staticArgs = Arrays.copyOfRange(args, 2, args.length); 218 assertAll(staticArgs); 219 return Integer.toString(staticArgs.length); 220 } 221 222 // expression mode BSMs 223 public static Object bsm() { 224 return bsm((MethodHandles.Lookup)null, null, null); 225 } 226 public static Object bsm(Object a1) { 227 return bsm((MethodHandles.Lookup)null, null, null, a1); 228 } 229 public static Object bsm(Object a1, Object a2) { 230 return bsm((MethodHandles.Lookup)null, null, null, a1, a2); 231 } 232 public static Object bsm(Object a1, Object a2, Object a3) { 233 return bsm((MethodHandles.Lookup)null, null, null, a1, a2, a3); 234 } 235 public static Object bsm(Object a1, Object a2, Object a3, Object a4) { 236 return bsm((MethodHandles.Lookup)null, null, null, a1, a2, a3, a4); 237 } 238 public static Object bsm(Object a1, Object a2, Object a3, Object a4, Object a5) { 239 return bsm((MethodHandles.Lookup)null, null, null, a1, a2, a3, a4, a5); 240 } 241 public static Object bsm(Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { 242 return bsm((MethodHandles.Lookup)null, null, null, a1, a2, a3, a4, a5, a6); 243 } 244 public static Object bsm(Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { 245 return bsm((MethodHandles.Lookup)null, null, null, a1, a2, a3, a4, a5, a6, a7); 246 } 247 public static Object bsm(Object... args) { 248 assertAll(args); 249 return Integer.toString(args.length); 250 } 251 252 static void assertAll(Object... as) { 253 for (int i = 0; i < as.length; i++) { 254 Assert.assertEquals(as[i], i); 255 } 256 } 257 258 @Test 259 public void testArity() throws Throwable { 260 for (int i = 0; i < 8; i++) { 261 final int n = i; 262 MethodType mt = methodType(Object.class, MethodHandles.Lookup.class, String.class, Class.class) 263 .appendParameterTypes(Collections.nCopies(n, Object.class)); 264 MethodHandle mh = InstructionHelper.ldcDynamicConstant( 265 L, "name", Object.class, 266 "bsm", mt, 267 S -> IntStream.range(0, n).forEach(S::add) 268 ); 269 270 Object r = mh.invoke(); 271 Assert.assertEquals(r, Integer.toString(n)); 272 } 273 274 { 275 MethodType mt = methodType(Object.class, MethodHandles.Lookup.class, Object[].class); 276 MethodHandle mh = InstructionHelper.ldcDynamicConstant( 277 L, "name", Object.class, 278 "bsm", mt, 279 S -> IntStream.range(0, 9).forEach(S::add) 280 ); 281 282 Object r = mh.invoke(); 283 Assert.assertEquals(r, Integer.toString(9)); 284 285 } 286 } 287 288 @Test 289 public void testArityWithoutMetadata() throws Throwable { 290 for (int i = 0; i < 8; i++) { 291 final int n = i; 292 MethodType mt = methodType(Object.class) 293 .appendParameterTypes(Collections.nCopies(n, Object.class)); 294 MethodHandle mh = InstructionHelper.ldcDynamicConstant( 295 L, "invoke", Object.class, 296 "bsm", mt, 297 S -> IntStream.range(0, n).forEach(S::add) 298 ); 299 300 Object r = mh.invoke(); 301 Assert.assertEquals(r, Integer.toString(n)); 302 } 303 304 { 305 MethodType mt = methodType(Object.class, Object[].class); 306 MethodHandle mh = InstructionHelper.ldcDynamicConstant( 307 L, "invoke", Object.class, 308 "bsm", mt, 309 S -> IntStream.range(0, 9).forEach(S::add) 310 ); 311 312 Object r = mh.invoke(); 313 Assert.assertEquals(r, Integer.toString(9)); 314 } 315 } 316 @Test 317 public void testArityAsSymbolic() throws Throwable { 318 for (int i = 0; i < 8; i++) { 319 final int n = i; 320 MethodType mt = methodType(Object.class) 321 .appendParameterTypes(Collections.nCopies(n, Object.class)); 322 MethodHandle mh = InstructionHelper.ldcDynamicConstant( 323 L, "symbolic", Object.class, 324 "bsm", mt, 325 S -> IntStream.range(0, n).forEach(S::add) 326 ); 327 328 Object r = mh.invoke(); 329 Assert.assertEquals(r, Integer.toString(n)); 330 } 331 332 { 333 MethodType mt = methodType(Object.class, Object[].class); 334 MethodHandle mh = InstructionHelper.ldcDynamicConstant( 335 L, "symbolic", Object.class, 336 "bsm", mt, 337 S -> IntStream.range(0, 9).forEach(S::add) 338 ); 339 340 Object r = mh.invoke(); 341 Assert.assertEquals(r, Integer.toString(9)); 342 } 343 } 344 345 @Test 346 public void testWrongNumberOfStaticArgumentsWithMetaData() throws Throwable { 347 for (int i = 1; i < 8; i++) { 348 final int n = i; 349 MethodType mt = methodType(Object.class, MethodHandles.Lookup.class, String.class, Class.class) 350 .appendParameterTypes(Collections.nCopies(n, Object.class)); 351 MethodHandle mh = InstructionHelper.ldcDynamicConstant( 352 L, "name", Object.class, 353 "bsm", mt, 354 S -> IntStream.range(0, n - 1).forEach(S::add) 355 ); 356 357 try { 358 Object r = mh.invoke(); 359 Assert.fail("BootstrapMethodError expected to be thrown for arrity " + n); 360 } catch (BootstrapMethodError e) { 361 Throwable t = e.getCause(); 362 Assert.assertTrue(WrongMethodTypeException.class.isAssignableFrom(t.getClass())); 363 } 364 } 365 } 366 367 @Test 368 public void testWrongNumberOfStaticArgumentsWithoutMetaData() throws Throwable { 369 for (int i = 1; i < 8; i++) { 370 final int n = i; 371 MethodType mt = methodType(Object.class) 372 .appendParameterTypes(Collections.nCopies(n, Object.class)); 373 MethodHandle mh = InstructionHelper.ldcDynamicConstant( 374 L, "invoke", Object.class, 375 "bsm", mt, 376 S -> IntStream.range(0, n - 1).forEach(S::add) 377 ); 378 379 try { 380 Object r = mh.invoke(); 381 Assert.fail("BootstrapMethodError expected to be thrown for arrity " + n); 382 } catch (BootstrapMethodError e) { 383 Throwable t = e.getCause(); 384 Assert.assertTrue(WrongMethodTypeException.class.isAssignableFrom(t.getClass())); 385 } 386 } 387 } 388 389 }