1 /* 2 * Copyright (c) 2015, 2016, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 /* @test 27 * @bug 8139885 28 * @bug 8143798 29 * @bug 8150825 30 * @bug 8150635 31 * @run testng/othervm -ea -esa test.java.lang.invoke.T8139885 32 */ 33 34 package test.java.lang.invoke; 35 36 import java.io.StringWriter; 37 import java.lang.invoke.MethodHandle; 38 import java.lang.invoke.MethodHandles; 39 import java.lang.invoke.MethodHandles.Lookup; 40 import java.lang.invoke.MethodType; 41 import java.lang.invoke.WrongMethodTypeException; 42 import java.util.*; 43 44 import static java.lang.invoke.MethodType.methodType; 45 46 import static org.testng.AssertJUnit.*; 47 48 import org.testng.annotations.*; 49 50 /** 51 * Example-scale and negative tests for JEP 274 extensions. 52 */ 53 public class T8139885 { 54 55 static final Lookup LOOKUP = MethodHandles.lookup(); 56 57 // 58 // Tests. 59 // 60 61 @Test 62 public static void testLoopFac() throws Throwable { 63 MethodHandle[] counterClause = new MethodHandle[]{Fac.MH_zero, Fac.MH_inc}; 64 MethodHandle[] accumulatorClause = new MethodHandle[]{Fac.MH_one, Fac.MH_mult, Fac.MH_pred, Fac.MH_fin}; 65 MethodHandle loop = MethodHandles.loop(counterClause, accumulatorClause); 66 assertEquals(Fac.MT_fac, loop.type()); 67 assertEquals(120, loop.invoke(5)); 68 } 69 70 @Test 71 public static void testLoopFacNullInit() throws Throwable { 72 // null initializer for counter, should initialize to 0 73 MethodHandle[] counterClause = new MethodHandle[]{null, Fac.MH_inc}; 74 MethodHandle[] accumulatorClause = new MethodHandle[]{Fac.MH_one, Fac.MH_mult, Fac.MH_pred, Fac.MH_fin}; 75 MethodHandle loop = MethodHandles.loop(counterClause, accumulatorClause); 76 assertEquals(Fac.MT_fac, loop.type()); 77 assertEquals(120, loop.invoke(5)); 78 } 79 80 @Test 81 public static void testLoopNullInit() throws Throwable { 82 // null initializer for counter, should initialize to 0, one-clause loop 83 MethodHandle[] counterClause = new MethodHandle[]{null, Loop.MH_inc, Loop.MH_pred, Loop.MH_fin}; 84 MethodHandle loop = MethodHandles.loop(counterClause); 85 assertEquals(Loop.MT_loop, loop.type()); 86 assertEquals(10, loop.invoke(10)); 87 } 88 89 @Test 90 public static void testLoopVoid1() throws Throwable { 91 // construct a post-checked loop that only does one iteration and has a void body and void local state 92 MethodHandle loop = MethodHandles.loop(new MethodHandle[]{Empty.MH_f, Empty.MH_f, Empty.MH_pred, null}); 93 assertEquals(MethodType.methodType(void.class), loop.type()); 94 loop.invoke(); 95 } 96 97 @Test 98 public static void testLoopVoid2() throws Throwable { 99 // construct a post-checked loop that only does one iteration and has a void body and void local state, 100 // initialized implicitly from the step type 101 MethodHandle loop = MethodHandles.loop(new MethodHandle[]{null, Empty.MH_f, Empty.MH_pred, null}); 102 assertEquals(MethodType.methodType(void.class), loop.type()); 103 loop.invoke(); 104 } 105 106 @Test 107 public static void testLoopVoid3() throws Throwable { 108 // construct a post-checked loop that only does one iteration and has a void body and void local state, 109 // and that has a void finalizer 110 MethodHandle loop = MethodHandles.loop(new MethodHandle[]{null, Empty.MH_f, Empty.MH_pred, Empty.MH_f}); 111 assertEquals(MethodType.methodType(void.class), loop.type()); 112 loop.invoke(); 113 } 114 115 @Test 116 public static void testLoopFacWithVoidState() throws Throwable { 117 // like testLoopFac, but with additional void state that outputs a dot 118 MethodHandle[] counterClause = new MethodHandle[]{Fac.MH_zero, Fac.MH_inc}; 119 MethodHandle[] accumulatorClause = new MethodHandle[]{Fac.MH_one, Fac.MH_mult, Fac.MH_pred, Fac.MH_fin}; 120 MethodHandle[] dotClause = new MethodHandle[]{null, Fac.MH_dot}; 121 MethodHandle loop = MethodHandles.loop(counterClause, accumulatorClause, dotClause); 122 assertEquals(Fac.MT_fac, loop.type()); 123 assertEquals(120, loop.invoke(5)); 124 } 125 126 @Test 127 public static void testLoopVoidInt() throws Throwable { 128 // construct a post-checked loop that only does one iteration and has a void body and void local state, 129 // and that returns a constant 130 MethodHandle loop = MethodHandles.loop(new MethodHandle[]{null, Empty.MH_f, Empty.MH_pred, Empty.MH_c}); 131 assertEquals(MethodType.methodType(int.class), loop.type()); 132 assertEquals(23, loop.invoke()); 133 } 134 135 @Test 136 public static void testLoopWithVirtuals() throws Throwable { 137 // construct a loop (to calculate factorial) that uses a mix of static and virtual methods 138 MethodHandle[] counterClause = new MethodHandle[]{null, LoopWithVirtuals.permute(LoopWithVirtuals.MH_inc)}; 139 MethodHandle[] accumulatorClause = new MethodHandle[]{ 140 // init function must indicate the loop arguments (there is no other means to determine them) 141 MethodHandles.dropArguments(LoopWithVirtuals.MH_one, 0, LoopWithVirtuals.class), 142 LoopWithVirtuals.permute(LoopWithVirtuals.MH_mult), 143 LoopWithVirtuals.permute(LoopWithVirtuals.MH_pred), 144 LoopWithVirtuals.permute(LoopWithVirtuals.MH_fin) 145 }; 146 MethodHandle loop = MethodHandles.loop(counterClause, accumulatorClause); 147 assertEquals(LoopWithVirtuals.MT_loop, loop.type()); 148 assertEquals(120, loop.invoke(new LoopWithVirtuals(), 5)); 149 } 150 151 @Test 152 public static void testLoopNegative() throws Throwable { 153 MethodHandle mh_loop = 154 LOOKUP.findStatic(MethodHandles.class, "loop", methodType(MethodHandle.class, MethodHandle[][].class)); 155 MethodHandle i0 = MethodHandles.constant(int.class, 0); 156 MethodHandle ii = MethodHandles.dropArguments(i0, 0, int.class, int.class); 157 MethodHandle id = MethodHandles.dropArguments(i0, 0, int.class, double.class); 158 MethodHandle i3 = MethodHandles.dropArguments(i0, 0, int.class, int.class, int.class); 159 List<MethodHandle> inits = Arrays.asList(ii, id, i3); 160 List<Class<?>> ints = Arrays.asList(int.class, int.class, int.class); 161 List<MethodHandle> finis = Arrays.asList(Fac.MH_fin, Fac.MH_inc, Counted.MH_step); 162 List<MethodHandle> preds1 = Arrays.asList(null, null, null); 163 List<MethodHandle> preds2 = Arrays.asList(null, Fac.MH_fin, null); 164 MethodHandle eek = MethodHandles.dropArguments(i0, 0, int.class, int.class, double.class); 165 List<MethodHandle> nesteps = Arrays.asList(Fac.MH_inc, eek, Fac.MH_dot); 166 List<MethodHandle> nepreds = Arrays.asList(null, Fac.MH_pred, null); 167 List<MethodHandle> nefinis = Arrays.asList(null, Fac.MH_fin, null); 168 List<MethodHandle> lvsteps = Arrays.asList(LoopWithVirtuals.MH_inc, LoopWithVirtuals.MH_mult); 169 List<MethodHandle> lvpreds = Arrays.asList(null, LoopWithVirtuals.MH_pred); 170 List<MethodHandle> lvfinis = Arrays.asList(null, LoopWithVirtuals.MH_fin); 171 MethodHandle[][][] cases = { 172 /* 1 */ null, 173 /* 2 */ {}, 174 /* 3 */ {{null, Fac.MH_inc}, {Fac.MH_one, null, Fac.MH_mult, Fac.MH_pred, Fac.MH_fin}}, 175 /* 4 */ {{null, Fac.MH_inc}, null}, 176 /* 5 */ {{Fac.MH_zero, Fac.MH_dot}}, 177 /* 6 */ {{ii}, {id}, {i3}}, 178 /* 7 */ {{null, Fac.MH_inc, null, Fac.MH_fin}, {null, Fac.MH_inc, null, Fac.MH_inc}, 179 {null, Counted.MH_start, null, Counted.MH_step}}, 180 /* 8 */ {{Fac.MH_zero, Fac.MH_inc}, {Fac.MH_one, Fac.MH_mult, null, Fac.MH_fin}, {null, Fac.MH_dot}}, 181 /* 9 */ {{Fac.MH_zero, Fac.MH_inc}, {Fac.MH_one, Fac.MH_mult, Fac.MH_fin, Fac.MH_fin}, {null, Fac.MH_dot}}, 182 /* 10 */ {{Fac.MH_zero, Fac.MH_inc}, {Fac.MH_one, eek, Fac.MH_pred, Fac.MH_fin}, {null, Fac.MH_dot}}, 183 /* 11 */ {{null, LoopWithVirtuals.MH_inc}, {LoopWithVirtuals.MH_one, LoopWithVirtuals.MH_mult, LoopWithVirtuals.MH_pred, LoopWithVirtuals.MH_fin}} 184 }; 185 String[] messages = { 186 /* 1 */ "null or no clauses passed", 187 /* 2 */ "null or no clauses passed", 188 /* 3 */ "All loop clauses must be represented as MethodHandle arrays with at most 4 elements.", 189 /* 4 */ "null clauses are not allowed", 190 /* 5 */ "clause 0: init and step return types must match: int != void", 191 /* 6 */ "found non-effectively identical init parameter type lists: " + inits + 192 " (common suffix: " + ints + ")", 193 /* 7 */ "found non-identical finalizer return types: " + finis + " (return type: int)", 194 /* 8 */ "no predicate found: " + preds1, 195 /* 9 */ "predicates must have boolean return type: " + preds2, 196 /* 10 */ "found non-effectively identical parameter type lists:\nstep: " + nesteps + 197 "\npred: " + nepreds + "\nfini: " + nefinis + " (common parameter sequence: " + ints + ")", 198 /* 11 */ "found non-effectively identical parameter type lists:\nstep: " + lvsteps + 199 "\npred: " + lvpreds + "\nfini: " + lvfinis + " (common parameter sequence: " + ints + ")" 200 }; 201 for (int i = 0; i < cases.length; ++i) { 202 boolean caught = false; 203 try { 204 mh_loop.invokeWithArguments(cases[i]); 205 } catch (IllegalArgumentException iae) { 206 assertEquals(messages[i], iae.getMessage()); 207 caught = true; 208 } 209 assertTrue(caught); 210 } 211 } 212 213 @Test 214 public static void testWhileLoop() throws Throwable { 215 // int i = 0; while (i < limit) { ++i; } return i; => limit 216 MethodHandle loop = MethodHandles.whileLoop(While.MH_zero, While.MH_pred, While.MH_step); 217 assertEquals(While.MT_while, loop.type()); 218 assertEquals(23, loop.invoke(23)); 219 } 220 221 @Test 222 public static void testWhileLoopNoIteration() throws Throwable { 223 // a while loop that never executes its body because the predicate evaluates to false immediately 224 MethodHandle loop = MethodHandles.whileLoop(While.MH_initString, While.MH_predString, While.MH_stepString); 225 assertEquals(While.MT_string, loop.type()); 226 assertEquals("a", loop.invoke()); 227 } 228 229 @Test 230 public static void testDoWhileLoop() throws Throwable { 231 // int i = 0; do { ++i; } while (i < limit); return i; => limit 232 MethodHandle loop = MethodHandles.doWhileLoop(While.MH_zero, While.MH_step, While.MH_pred); 233 assertEquals(While.MT_while, loop.type()); 234 assertEquals(23, loop.invoke(23)); 235 } 236 237 @Test 238 public static void testWhileZip() throws Throwable { 239 MethodHandle loop = MethodHandles.doWhileLoop(While.MH_zipInitZip, While.MH_zipStep, While.MH_zipPred); 240 assertEquals(While.MT_zip, loop.type()); 241 List<String> a = Arrays.asList("a", "b", "c", "d"); 242 List<String> b = Arrays.asList("e", "f", "g", "h"); 243 List<String> zipped = Arrays.asList("a", "e", "b", "f", "c", "g", "d", "h"); 244 assertEquals(zipped, (List<String>) loop.invoke(a.iterator(), b.iterator())); 245 } 246 247 @Test 248 public static void testCountedLoop() throws Throwable { 249 // String s = "Lambdaman!"; for (int i = 0; i < 13; ++i) { s = "na " + s; } return s; => a variation on a well known theme 250 MethodHandle fit13 = MethodHandles.constant(int.class, 13); 251 MethodHandle loop = MethodHandles.countedLoop(fit13, Counted.MH_start, Counted.MH_step); 252 assertEquals(Counted.MT_counted, loop.type()); 253 assertEquals("na na na na na na na na na na na na na Lambdaman!", loop.invoke("Lambdaman!")); 254 } 255 256 @Test 257 public static void testCountedArrayLoop() throws Throwable { 258 // int[] a = new int[]{0}; for (int i = 0; i < 13; ++i) { ++a[0]; } => a[0] == 13 259 MethodHandle fit13 = MethodHandles.dropArguments(MethodHandles.constant(int.class, 13), 0, int[].class); 260 MethodHandle loop = MethodHandles.countedLoop(fit13, null, Counted.MH_stepUpdateArray); 261 assertEquals(Counted.MT_arrayCounted, loop.type()); 262 int[] a = new int[]{0}; 263 loop.invoke(a); 264 assertEquals(13, a[0]); 265 } 266 267 @Test 268 public static void testCountedPrintingLoop() throws Throwable { 269 MethodHandle fit5 = MethodHandles.constant(int.class, 5); 270 MethodHandle loop = MethodHandles.countedLoop(fit5, null, Counted.MH_printHello); 271 assertEquals(Counted.MT_countedPrinting, loop.type()); 272 loop.invoke(); 273 } 274 275 @Test 276 public static void testCountedRangeLoop() throws Throwable { 277 // String s = "Lambdaman!"; for (int i = -5; i < 8; ++i) { s = "na " + s; } return s; => a well known theme 278 MethodHandle fitm5 = MethodHandles.dropArguments(Counted.MH_m5, 0, String.class); 279 MethodHandle fit8 = MethodHandles.dropArguments(Counted.MH_8, 0, String.class); 280 MethodHandle loop = MethodHandles.countedLoop(fitm5, fit8, Counted.MH_start, Counted.MH_step); 281 assertEquals(Counted.MT_counted, loop.type()); 282 assertEquals("na na na na na na na na na na na na na Lambdaman!", loop.invoke("Lambdaman!")); 283 } 284 285 @Test 286 public static void testIterateSum() throws Throwable { 287 // Integer[] a = new Integer[]{1,2,3,4,5,6}; int sum = 0; for (int e : a) { sum += e; } return sum; => 21 288 MethodHandle loop = MethodHandles.iteratedLoop(Iterate.MH_sumIterator, Iterate.MH_sumInit, Iterate.MH_sumStep); 289 assertEquals(Iterate.MT_sum, loop.type()); 290 assertEquals(21, loop.invoke(new Integer[]{1, 2, 3, 4, 5, 6})); 291 } 292 293 @Test 294 public static void testIterateReverse() throws Throwable { 295 MethodHandle loop = MethodHandles.iteratedLoop(null, Iterate.MH_reverseInit, Iterate.MH_reverseStep); 296 assertEquals(Iterate.MT_reverse, loop.type()); 297 List<String> list = Arrays.asList("a", "b", "c", "d", "e"); 298 List<String> reversedList = Arrays.asList("e", "d", "c", "b", "a"); 299 assertEquals(reversedList, (List<String>) loop.invoke(list)); 300 } 301 302 @Test 303 public static void testIterateLength() throws Throwable { 304 MethodHandle loop = MethodHandles.iteratedLoop(null, Iterate.MH_lengthInit, Iterate.MH_lengthStep); 305 assertEquals(Iterate.MT_length, loop.type()); 306 List<Double> list = Arrays.asList(23.0, 148.0, 42.0); 307 assertEquals(list.size(), (int) loop.invoke(list)); 308 } 309 310 @Test 311 public static void testIterateMap() throws Throwable { 312 MethodHandle loop = MethodHandles.iteratedLoop(null, Iterate.MH_mapInit, Iterate.MH_mapStep); 313 assertEquals(Iterate.MT_map, loop.type()); 314 List<String> list = Arrays.asList("Hello", "world", "!"); 315 List<String> upList = Arrays.asList("HELLO", "WORLD", "!"); 316 assertEquals(upList, (List<String>) loop.invoke(list)); 317 } 318 319 @Test 320 public static void testIteratePrint() throws Throwable { 321 MethodHandle loop = MethodHandles.iteratedLoop(null, null, Iterate.MH_printStep); 322 assertEquals(Iterate.MT_print, loop.type()); 323 loop.invoke(Arrays.asList("hello", "world")); 324 } 325 326 @Test 327 public static void testIterateNullBody() { 328 boolean caught = false; 329 try { 330 MethodHandles.iteratedLoop(MethodHandles.identity(int.class), MethodHandles.identity(int.class), null); 331 } catch (IllegalArgumentException iae) { 332 assertEquals("iterated loop body must not be null", iae.getMessage()); 333 caught = true; 334 } 335 assertTrue(caught); 336 } 337 338 @Test 339 public static void testTryFinally() throws Throwable { 340 MethodHandle hello = MethodHandles.tryFinally(TryFinally.MH_greet, TryFinally.MH_exclaim); 341 assertEquals(TryFinally.MT_hello, hello.type()); 342 assertEquals("Hello, world!", hello.invoke("world")); 343 } 344 345 @Test 346 public static void testTryFinallyVoid() throws Throwable { 347 MethodHandle tfVoid = MethodHandles.tryFinally(TryFinally.MH_print, TryFinally.MH_printMore); 348 assertEquals(TryFinally.MT_printHello, tfVoid.type()); 349 tfVoid.invoke("world"); 350 } 351 352 @Test 353 public static void testTryFinallySublist() throws Throwable { 354 MethodHandle helloMore = MethodHandles.tryFinally(TryFinally.MH_greetMore, TryFinally.MH_exclaimMore); 355 assertEquals(TryFinally.MT_moreHello, helloMore.type()); 356 assertEquals("Hello, world and universe (but world first)!", helloMore.invoke("world", "universe")); 357 } 358 359 @Test 360 public static void testTryFinallyNegative() { 361 MethodHandle intid = MethodHandles.identity(int.class); 362 MethodHandle intco = MethodHandles.constant(int.class, 0); 363 MethodHandle errTarget = MethodHandles.dropArguments(intco, 0, int.class, double.class, String.class, int.class); 364 MethodHandle errCleanup = MethodHandles.dropArguments(MethodHandles.constant(int.class, 0), 0, Throwable.class, 365 int.class, double.class, Object.class); 366 MethodHandle[][] cases = { 367 {intid, MethodHandles.identity(double.class)}, 368 {intid, MethodHandles.dropArguments(intid, 0, String.class)}, 369 {intid, MethodHandles.dropArguments(intid, 0, Throwable.class, double.class)}, 370 {errTarget, errCleanup}, 371 {TryFinally.MH_voidTarget, TryFinally.MH_voidCleanup} 372 }; 373 String[] messages = { 374 "target and return types must match: double != int", 375 "cleanup first argument and Throwable must match: (String,int)int != class java.lang.Throwable", 376 "cleanup second argument and target return type must match: (Throwable,double,int)int != int", 377 "cleanup parameters after (Throwable,result) and target parameter list prefix must match: " + 378 errCleanup.type() + " != " + errTarget.type(), 379 "cleanup parameters after (Throwable,result) and target parameter list prefix must match: " + 380 TryFinally.MH_voidCleanup.type() + " != " + TryFinally.MH_voidTarget.type() 381 }; 382 for (int i = 0; i < cases.length; ++i) { 383 boolean caught = false; 384 try { 385 MethodHandles.tryFinally(cases[i][0], cases[i][1]); 386 } catch (IllegalArgumentException iae) { 387 assertEquals(messages[i], iae.getMessage()); 388 caught = true; 389 } 390 assertTrue(caught); 391 } 392 } 393 394 @Test 395 public static void testFold0a() throws Throwable { 396 // equivalence to foldArguments(MethodHandle,MethodHandle) 397 MethodHandle fold = MethodHandles.foldArguments(Fold.MH_multer, 0, Fold.MH_adder); 398 assertEquals(Fold.MT_folded1, fold.type()); 399 assertEquals(720, (int) fold.invoke(3, 4, 5)); 400 } 401 402 @Test 403 public static void testFold1a() throws Throwable { 404 // test foldArguments for folding position 1 405 MethodHandle fold = MethodHandles.foldArguments(Fold.MH_multer, 1, Fold.MH_adder1); 406 assertEquals(Fold.MT_folded1, fold.type()); 407 assertEquals(540, (int) fold.invoke(3, 4, 5)); 408 } 409 410 @Test 411 public static void testFold0b() throws Throwable { 412 // test foldArguments equivalence with multiple types 413 MethodHandle fold = MethodHandles.foldArguments(Fold.MH_str, 0, Fold.MH_comb); 414 assertEquals(Fold.MT_folded2, fold.type()); 415 assertEquals(23, (int) fold.invoke("true", true, 23)); 416 } 417 418 @Test 419 public static void testFold1b() throws Throwable { 420 // test folgArguments for folding position 1, with multiple types 421 MethodHandle fold = MethodHandles.foldArguments(Fold.MH_str, 1, Fold.MH_comb2); 422 assertEquals(Fold.MT_folded3, fold.type()); 423 assertEquals(1, (int) fold.invoke(true, true, 1)); 424 assertEquals(-1, (int) fold.invoke(true, false, -1)); 425 } 426 427 @Test 428 public static void testFoldArgumentsExample() throws Throwable { 429 // test the JavaDoc foldArguments-with-pos example 430 StringWriter swr = new StringWriter(); 431 MethodHandle trace = LOOKUP.findVirtual(StringWriter.class, "write", methodType(void.class, String.class)).bindTo(swr); 432 MethodHandle cat = LOOKUP.findVirtual(String.class, "concat", methodType(String.class, String.class)); 433 assertEquals("boojum", (String) cat.invokeExact("boo", "jum")); 434 MethodHandle catTrace = MethodHandles.foldArguments(cat, 1, trace); 435 assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); 436 assertEquals("jum", swr.toString()); 437 } 438 439 @Test 440 public static void testAsSpreader() throws Throwable { 441 MethodHandle spreader = SpreadCollect.MH_forSpreading.asSpreader(1, int[].class, 3); 442 assertEquals(SpreadCollect.MT_spreader, spreader.type()); 443 assertEquals("A456B", (String) spreader.invoke("A", new int[]{4, 5, 6}, "B")); 444 } 445 446 @Test 447 public static void testAsSpreaderExample() throws Throwable { 448 // test the JavaDoc asSpreader-with-pos example 449 MethodHandle compare = LOOKUP.findStatic(Objects.class, "compare", methodType(int.class, Object.class, Object.class, Comparator.class)); 450 MethodHandle compare2FromArray = compare.asSpreader(0, Object[].class, 2); 451 Object[] ints = new Object[]{3, 9, 7, 7}; 452 Comparator<Integer> cmp = (a, b) -> a - b; 453 assertTrue((int) compare2FromArray.invoke(Arrays.copyOfRange(ints, 0, 2), cmp) < 0); 454 assertTrue((int) compare2FromArray.invoke(Arrays.copyOfRange(ints, 1, 3), cmp) > 0); 455 assertTrue((int) compare2FromArray.invoke(Arrays.copyOfRange(ints, 2, 4), cmp) == 0); 456 } 457 458 @Test 459 public static void testAsSpreaderIllegalPos() throws Throwable { 460 int[] illegalPos = {-7, 3, 19}; 461 int caught = 0; 462 for (int p : illegalPos) { 463 try { 464 SpreadCollect.MH_forSpreading.asSpreader(p, Object[].class, 3); 465 } catch (IllegalArgumentException iae) { 466 assertEquals("bad spread position", iae.getMessage()); 467 ++caught; 468 } 469 } 470 assertEquals(illegalPos.length, caught); 471 } 472 473 @Test 474 public static void testAsSpreaderIllegalMethodType() throws Throwable { 475 MethodHandle h = MethodHandles.dropArguments(MethodHandles.constant(String.class, ""), 0, int.class, int.class); 476 boolean caught = false; 477 try { 478 MethodHandle s = h.asSpreader(String[].class, 1); 479 } catch (WrongMethodTypeException wmte) { 480 caught = true; 481 } 482 assertTrue(caught); 483 } 484 485 @Test 486 public static void testAsCollector() throws Throwable { 487 MethodHandle collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 1); 488 assertEquals(SpreadCollect.MT_collector1, collector.type()); 489 assertEquals("A4B", (String) collector.invoke("A", 4, "B")); 490 collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 2); 491 assertEquals(SpreadCollect.MT_collector2, collector.type()); 492 assertEquals("A45B", (String) collector.invoke("A", 4, 5, "B")); 493 collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 3); 494 assertEquals(SpreadCollect.MT_collector3, collector.type()); 495 assertEquals("A456B", (String) collector.invoke("A", 4, 5, 6, "B")); 496 } 497 498 @Test 499 public static void testAsCollectorInvokeWithArguments() throws Throwable { 500 MethodHandle collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 1); 501 assertEquals(SpreadCollect.MT_collector1, collector.type()); 502 assertEquals("A4B", (String) collector.invokeWithArguments("A", 4, "B")); 503 collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 2); 504 assertEquals(SpreadCollect.MT_collector2, collector.type()); 505 assertEquals("A45B", (String) collector.invokeWithArguments("A", 4, 5, "B")); 506 collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 3); 507 assertEquals(SpreadCollect.MT_collector3, collector.type()); 508 assertEquals("A456B", (String) collector.invokeWithArguments("A", 4, 5, 6, "B")); 509 } 510 511 @Test 512 public static void testAsCollectorLeading() throws Throwable { 513 MethodHandle collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 1); 514 assertEquals(SpreadCollect.MT_collectorLeading1, collector.type()); 515 assertEquals("7Q", (String) collector.invoke(7, "Q")); 516 collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 2); 517 assertEquals(SpreadCollect.MT_collectorLeading2, collector.type()); 518 assertEquals("78Q", (String) collector.invoke(7, 8, "Q")); 519 collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 3); 520 assertEquals(SpreadCollect.MT_collectorLeading3, collector.type()); 521 assertEquals("789Q", (String) collector.invoke(7, 8, 9, "Q")); 522 } 523 524 @Test 525 public static void testAsCollectorLeadingInvokeWithArguments() throws Throwable { 526 MethodHandle collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 1); 527 assertEquals(SpreadCollect.MT_collectorLeading1, collector.type()); 528 assertEquals("7Q", (String) collector.invokeWithArguments(7, "Q")); 529 collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 2); 530 assertEquals(SpreadCollect.MT_collectorLeading2, collector.type()); 531 assertEquals("78Q", (String) collector.invokeWithArguments(7, 8, "Q")); 532 collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 3); 533 assertEquals(SpreadCollect.MT_collectorLeading3, collector.type()); 534 assertEquals("789Q", (String) collector.invokeWithArguments(7, 8, 9, "Q")); 535 } 536 537 @Test 538 public static void testAsCollectorNone() throws Throwable { 539 MethodHandle collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 0); 540 assertEquals(SpreadCollect.MT_collector0, collector.type()); 541 assertEquals("AB", (String) collector.invoke("A", "B")); 542 } 543 544 @Test 545 public static void testAsCollectorIllegalPos() throws Throwable { 546 int[] illegalPos = {-1, 17}; 547 int caught = 0; 548 for (int p : illegalPos) { 549 try { 550 SpreadCollect.MH_forCollecting.asCollector(p, int[].class, 0); 551 } catch (IllegalArgumentException iae) { 552 assertEquals("bad collect position", iae.getMessage()); 553 ++caught; 554 } 555 } 556 assertEquals(illegalPos.length, caught); 557 } 558 559 @Test 560 public static void testAsCollectorExample() throws Throwable { 561 // test the JavaDoc asCollector-with-pos example 562 StringWriter swr = new StringWriter(); 563 MethodHandle swWrite = LOOKUP. 564 findVirtual(StringWriter.class, "write", methodType(void.class, char[].class, int.class, int.class)). 565 bindTo(swr); 566 MethodHandle swWrite4 = swWrite.asCollector(0, char[].class, 4); 567 swWrite4.invoke('A', 'B', 'C', 'D', 1, 2); 568 assertEquals("BC", swr.toString()); 569 swWrite4.invoke('P', 'Q', 'R', 'S', 0, 4); 570 assertEquals("BCPQRS", swr.toString()); 571 swWrite4.invoke('W', 'X', 'Y', 'Z', 3, 1); 572 assertEquals("BCPQRSZ", swr.toString()); 573 } 574 575 @Test 576 public static void testFindSpecial() throws Throwable { 577 FindSpecial.C c = new FindSpecial.C(); 578 assertEquals("I1.m", c.m()); 579 MethodType t = MethodType.methodType(String.class); 580 MethodHandle ci1m = LOOKUP.findSpecial(FindSpecial.I1.class, "m", t, FindSpecial.C.class); 581 assertEquals("I1.m", (String) ci1m.invoke(c)); 582 } 583 584 @Test 585 public static void testFindSpecialAbstract() throws Throwable { 586 FindSpecial.C c = new FindSpecial.C(); 587 assertEquals("q", c.q()); 588 MethodType t = MethodType.methodType(String.class); 589 boolean caught = false; 590 try { 591 MethodHandle ci3q = LOOKUP.findSpecial(FindSpecial.I3.class, "q", t, FindSpecial.C.class); 592 } catch (Throwable thrown) { 593 if (!(thrown instanceof IllegalAccessException) || !FindSpecial.ABSTRACT_ERROR.equals(thrown.getMessage())) { 594 throw new AssertionError(thrown.getMessage(), thrown); 595 } 596 caught = true; 597 } 598 assertTrue(caught); 599 } 600 601 @Test 602 public static void testFindClassCNFE() throws Throwable { 603 boolean caught = false; 604 try { 605 LOOKUP.findClass("does.not.Exist"); 606 } catch (ClassNotFoundException cnfe) { 607 caught = true; 608 } 609 assertTrue(caught); 610 } 611 612 // 613 // Methods used to assemble tests. 614 // 615 616 static class Empty { 617 618 static void f() { } 619 620 static boolean pred() { 621 return false; 622 } 623 624 static int c() { 625 return 23; 626 } 627 628 static final Class<Empty> EMPTY = Empty.class; 629 630 static final MethodType MT_f = methodType(void.class); 631 static final MethodType MT_pred = methodType(boolean.class); 632 static final MethodType MT_c = methodType(int.class); 633 634 static final MethodHandle MH_f; 635 static final MethodHandle MH_pred; 636 static final MethodHandle MH_c; 637 638 static { 639 try { 640 MH_f = LOOKUP.findStatic(EMPTY, "f", MT_f); 641 MH_pred = LOOKUP.findStatic(EMPTY, "pred", MT_pred); 642 MH_c = LOOKUP.findStatic(EMPTY, "c", MT_c); 643 } catch (Exception e) { 644 throw new ExceptionInInitializerError(e); 645 } 646 } 647 } 648 649 static class Fac { 650 651 static int zero(int k) { 652 return 0; 653 } 654 655 static int one(int k) { 656 return 1; 657 } 658 659 static boolean pred(int i, int acc, int k) { 660 return i < k; 661 } 662 663 static int inc(int i, int acc, int k) { 664 return i + 1; 665 } 666 667 static int mult(int i, int acc, int k) { 668 return i * acc; 669 } 670 671 static void dot(int i, int acc, int k) { 672 System.out.print('.'); 673 } 674 675 static int fin(int i, int acc, int k) { 676 return acc; 677 } 678 679 static final Class<Fac> FAC = Fac.class; 680 681 static final MethodType MT_init = methodType(int.class, int.class); 682 static final MethodType MT_fn = methodType(int.class, int.class, int.class, int.class); 683 static final MethodType MT_dot = methodType(void.class, int.class, int.class, int.class); 684 static final MethodType MT_pred = methodType(boolean.class, int.class, int.class, int.class); 685 686 static final MethodHandle MH_zero; 687 static final MethodHandle MH_one; 688 static final MethodHandle MH_pred; 689 static final MethodHandle MH_inc; 690 static final MethodHandle MH_mult; 691 static final MethodHandle MH_dot; 692 static final MethodHandle MH_fin; 693 694 static final MethodType MT_fac = methodType(int.class, int.class); 695 696 static { 697 try { 698 MH_zero = LOOKUP.findStatic(FAC, "zero", MT_init); 699 MH_one = LOOKUP.findStatic(FAC, "one", MT_init); 700 MH_pred = LOOKUP.findStatic(FAC, "pred", MT_pred); 701 MH_inc = LOOKUP.findStatic(FAC, "inc", MT_fn); 702 MH_mult = LOOKUP.findStatic(FAC, "mult", MT_fn); 703 MH_dot = LOOKUP.findStatic(FAC, "dot", MT_dot); 704 MH_fin = LOOKUP.findStatic(FAC, "fin", MT_fn); 705 } catch (Exception e) { 706 throw new ExceptionInInitializerError(e); 707 } 708 } 709 710 } 711 712 static class Loop { 713 714 static int inc(int i, int k) { 715 return i + 1; 716 } 717 718 static boolean pred(int i, int k) { 719 return i < k; 720 } 721 722 static int fin(int i, int k) { 723 return k; 724 } 725 726 static final Class<Loop> LOOP = Loop.class; 727 728 static final MethodType MT_inc = methodType(int.class, int.class, int.class); 729 static final MethodType MT_pred = methodType(boolean.class, int.class, int.class); 730 static final MethodType MT_fin = methodType(int.class, int.class, int.class); 731 732 static final MethodHandle MH_inc; 733 static final MethodHandle MH_pred; 734 static final MethodHandle MH_fin; 735 736 static final MethodType MT_loop = methodType(int.class, int.class); 737 738 static { 739 try { 740 MH_inc = LOOKUP.findStatic(LOOP, "inc", MT_inc); 741 MH_pred = LOOKUP.findStatic(LOOP, "pred", MT_pred); 742 MH_fin = LOOKUP.findStatic(LOOP, "fin", MT_fin); 743 } catch (Exception e) { 744 throw new ExceptionInInitializerError(e); 745 } 746 } 747 748 } 749 750 static class LoopWithVirtuals { 751 752 static int one(int k) { 753 return 1; 754 } 755 756 int inc(int i, int acc, int k) { 757 return i + 1; 758 } 759 760 int mult(int i, int acc, int k) { 761 return i * acc; 762 } 763 764 boolean pred(int i, int acc, int k) { 765 return i < k; 766 } 767 768 int fin(int i, int acc, int k) { 769 return acc; 770 } 771 772 static final Class<LoopWithVirtuals> LOOP_WITH_VIRTUALS = LoopWithVirtuals.class; 773 774 static final MethodType MT_one = methodType(int.class, int.class); 775 static final MethodType MT_inc = methodType(int.class, int.class, int.class, int.class); 776 static final MethodType MT_mult = methodType(int.class, int.class, int.class, int.class); 777 static final MethodType MT_pred = methodType(boolean.class, int.class, int.class, int.class); 778 static final MethodType MT_fin = methodType(int.class, int.class, int.class, int.class); 779 780 static final MethodHandle MH_one; 781 static final MethodHandle MH_inc; 782 static final MethodHandle MH_mult; 783 static final MethodHandle MH_pred; 784 static final MethodHandle MH_fin; 785 786 static final MethodType MT_loop = methodType(int.class, LOOP_WITH_VIRTUALS, int.class); 787 788 static { 789 try { 790 MH_one = LOOKUP.findStatic(LOOP_WITH_VIRTUALS, "one", MT_one); 791 MH_inc = LOOKUP.findVirtual(LOOP_WITH_VIRTUALS, "inc", MT_inc); 792 MH_mult = LOOKUP.findVirtual(LOOP_WITH_VIRTUALS, "mult", MT_mult); 793 MH_pred = LOOKUP.findVirtual(LOOP_WITH_VIRTUALS, "pred", MT_pred); 794 MH_fin = LOOKUP.findVirtual(LOOP_WITH_VIRTUALS, "fin", MT_fin); 795 } catch (Exception e) { 796 throw new ExceptionInInitializerError(e); 797 } 798 } 799 800 static MethodHandle permute(MethodHandle h) { 801 // The handles representing virtual methods need to be rearranged to match the required order of arguments 802 // (loop-local state comes first, then loop arguments). As the receiver comes first in the signature but is 803 // a loop argument, it must be moved to the appropriate position in the signature. 804 return MethodHandles.permuteArguments(h, 805 methodType(h.type().returnType(), int.class, int.class, LOOP_WITH_VIRTUALS, int.class), 2, 0, 1, 3); 806 } 807 808 } 809 810 static class While { 811 812 static int zero(int limit) { 813 return 0; 814 } 815 816 static boolean pred(int i, int limit) { 817 return i < limit; 818 } 819 820 static int step(int i, int limit) { 821 return i + 1; 822 } 823 824 static String initString() { 825 return "a"; 826 } 827 828 static boolean predString(String s) { 829 return s.length() != 1; 830 } 831 832 static String stepString(String s) { 833 return s + "a"; 834 } 835 836 static List<String> zipInitZip(Iterator<String> a, Iterator<String> b) { 837 return new ArrayList<>(); 838 } 839 840 static boolean zipPred(List<String> zip, Iterator<String> a, Iterator<String> b) { 841 return a.hasNext() && b.hasNext(); 842 } 843 844 static List<String> zipStep(List<String> zip, Iterator<String> a, Iterator<String> b) { 845 zip.add(a.next()); 846 zip.add(b.next()); 847 return zip; 848 } 849 850 static final Class<While> WHILE = While.class; 851 852 static final MethodType MT_zero = methodType(int.class, int.class); 853 static final MethodType MT_pred = methodType(boolean.class, int.class, int.class); 854 static final MethodType MT_fn = methodType(int.class, int.class, int.class); 855 static final MethodType MT_initString = methodType(String.class); 856 static final MethodType MT_predString = methodType(boolean.class, String.class); 857 static final MethodType MT_stepString = methodType(String.class, String.class); 858 static final MethodType MT_zipInitZip = methodType(List.class, Iterator.class, Iterator.class); 859 static final MethodType MT_zipPred = methodType(boolean.class, List.class, Iterator.class, Iterator.class); 860 static final MethodType MT_zipStep = methodType(List.class, List.class, Iterator.class, Iterator.class); 861 862 static final MethodHandle MH_zero; 863 static final MethodHandle MH_pred; 864 static final MethodHandle MH_step; 865 static final MethodHandle MH_initString; 866 static final MethodHandle MH_predString; 867 static final MethodHandle MH_stepString; 868 static final MethodHandle MH_zipInitZip; 869 static final MethodHandle MH_zipPred; 870 static final MethodHandle MH_zipStep; 871 872 static final MethodType MT_while = methodType(int.class, int.class); 873 static final MethodType MT_string = methodType(String.class); 874 static final MethodType MT_zip = methodType(List.class, Iterator.class, Iterator.class); 875 876 static { 877 try { 878 MH_zero = LOOKUP.findStatic(WHILE, "zero", MT_zero); 879 MH_pred = LOOKUP.findStatic(WHILE, "pred", MT_pred); 880 MH_step = LOOKUP.findStatic(WHILE, "step", MT_fn); 881 MH_initString = LOOKUP.findStatic(WHILE, "initString", MT_initString); 882 MH_predString = LOOKUP.findStatic(WHILE, "predString", MT_predString); 883 MH_stepString = LOOKUP.findStatic(WHILE, "stepString", MT_stepString); 884 MH_zipInitZip = LOOKUP.findStatic(WHILE, "zipInitZip", MT_zipInitZip); 885 MH_zipPred = LOOKUP.findStatic(WHILE, "zipPred", MT_zipPred); 886 MH_zipStep = LOOKUP.findStatic(WHILE, "zipStep", MT_zipStep); 887 } catch (Exception e) { 888 throw new ExceptionInInitializerError(e); 889 } 890 } 891 892 } 893 894 static class Counted { 895 896 static String start(String arg) { 897 return arg; 898 } 899 900 static String step(int counter, String v, String arg) { 901 return "na " + v; 902 } 903 904 static void stepUpdateArray(int counter, int[] a) { 905 ++a[0]; 906 } 907 908 static void printHello(int counter) { 909 System.out.print("hello"); 910 } 911 912 static final Class<Counted> COUNTED = Counted.class; 913 914 static final MethodType MT_start = methodType(String.class, String.class); 915 static final MethodType MT_step = methodType(String.class, int.class, String.class, String.class); 916 static final MethodType MT_stepUpdateArray = methodType(void.class, int.class, int[].class); 917 static final MethodType MT_printHello = methodType(void.class, int.class); 918 919 static final MethodHandle MH_13; 920 static final MethodHandle MH_m5; 921 static final MethodHandle MH_8; 922 static final MethodHandle MH_start; 923 static final MethodHandle MH_step; 924 static final MethodHandle MH_stepUpdateArray; 925 static final MethodHandle MH_printHello; 926 927 static final MethodType MT_counted = methodType(String.class, String.class); 928 static final MethodType MT_arrayCounted = methodType(void.class, int[].class); 929 static final MethodType MT_countedPrinting = methodType(void.class); 930 931 static { 932 try { 933 MH_13 = MethodHandles.constant(int.class, 13); 934 MH_m5 = MethodHandles.constant(int.class, -5); 935 MH_8 = MethodHandles.constant(int.class, 8); 936 MH_start = LOOKUP.findStatic(COUNTED, "start", MT_start); 937 MH_step = LOOKUP.findStatic(COUNTED, "step", MT_step); 938 MH_stepUpdateArray = LOOKUP.findStatic(COUNTED, "stepUpdateArray", MT_stepUpdateArray); 939 MH_printHello = LOOKUP.findStatic(COUNTED, "printHello", MT_printHello); 940 } catch (Exception e) { 941 throw new ExceptionInInitializerError(e); 942 } 943 } 944 945 } 946 947 static class Iterate { 948 949 static Iterator<Integer> sumIterator(Integer[] a) { 950 return Arrays.asList(a).iterator(); 951 } 952 953 static int sumInit(Integer[] a) { 954 return 0; 955 } 956 957 static int sumStep(int s, int e, Integer[] a) { 958 return s + e; 959 } 960 961 static List<String> reverseInit(List<String> l) { 962 return new ArrayList<>(); 963 } 964 965 static List<String> reverseStep(String e, List<String> r, List<String> l) { 966 r.add(0, e); 967 return r; 968 } 969 970 static int lengthInit(List<Double> l) { 971 return 0; 972 } 973 974 static int lengthStep(Object o, int len, List<Double> l) { 975 return len + 1; 976 } 977 978 static List<String> mapInit(List<String> l) { 979 return new ArrayList<>(); 980 } 981 982 static List<String> mapStep(String e, List<String> r, List<String> l) { 983 r.add(e.toUpperCase()); 984 return r; 985 } 986 987 static void printStep(String s, List<String> l) { 988 System.out.print(s); 989 } 990 991 static final Class<Iterate> ITERATE = Iterate.class; 992 993 static final MethodType MT_sumIterator = methodType(Iterator.class, Integer[].class); 994 995 static final MethodType MT_sumInit = methodType(int.class, Integer[].class); 996 static final MethodType MT_reverseInit = methodType(List.class, List.class); 997 static final MethodType MT_lenghInit = methodType(int.class, List.class); 998 static final MethodType MT_mapInit = methodType(List.class, List.class); 999 1000 static final MethodType MT_sumStep = methodType(int.class, int.class, int.class, Integer[].class); 1001 static final MethodType MT_reverseStep = methodType(List.class, String.class, List.class, List.class); 1002 static final MethodType MT_lengthStep = methodType(int.class, Object.class, int.class, List.class); 1003 static final MethodType MT_mapStep = methodType(List.class, String.class, List.class, List.class); 1004 static final MethodType MT_printStep = methodType(void.class, String.class, List.class); 1005 1006 static final MethodHandle MH_sumIterator; 1007 static final MethodHandle MH_sumInit; 1008 static final MethodHandle MH_sumStep; 1009 static final MethodHandle MH_printStep; 1010 1011 static final MethodHandle MH_reverseInit; 1012 static final MethodHandle MH_reverseStep; 1013 1014 static final MethodHandle MH_lengthInit; 1015 static final MethodHandle MH_lengthStep; 1016 1017 static final MethodHandle MH_mapInit; 1018 static final MethodHandle MH_mapStep; 1019 1020 static final MethodType MT_sum = methodType(int.class, Integer[].class); 1021 static final MethodType MT_reverse = methodType(List.class, List.class); 1022 static final MethodType MT_length = methodType(int.class, List.class); 1023 static final MethodType MT_map = methodType(List.class, List.class); 1024 static final MethodType MT_print = methodType(void.class, List.class); 1025 1026 static { 1027 try { 1028 MH_sumIterator = LOOKUP.findStatic(ITERATE, "sumIterator", MT_sumIterator); 1029 MH_sumInit = LOOKUP.findStatic(ITERATE, "sumInit", MT_sumInit); 1030 MH_sumStep = LOOKUP.findStatic(ITERATE, "sumStep", MT_sumStep); 1031 MH_reverseInit = LOOKUP.findStatic(ITERATE, "reverseInit", MT_reverseInit); 1032 MH_reverseStep = LOOKUP.findStatic(ITERATE, "reverseStep", MT_reverseStep); 1033 MH_lengthInit = LOOKUP.findStatic(ITERATE, "lengthInit", MT_lenghInit); 1034 MH_lengthStep = LOOKUP.findStatic(ITERATE, "lengthStep", MT_lengthStep); 1035 MH_mapInit = LOOKUP.findStatic(ITERATE, "mapInit", MT_mapInit); 1036 MH_mapStep = LOOKUP.findStatic(ITERATE, "mapStep", MT_mapStep); 1037 MH_printStep = LOOKUP.findStatic(ITERATE, "printStep", MT_printStep); 1038 } catch (Exception e) { 1039 throw new ExceptionInInitializerError(e); 1040 } 1041 } 1042 1043 } 1044 1045 static class TryFinally { 1046 1047 static String greet(String whom) { 1048 return "Hello, " + whom; 1049 } 1050 1051 static String exclaim(Throwable t, String r, String whom) { 1052 return r + "!"; 1053 } 1054 1055 static void print(String what) { 1056 System.out.print("Hello, " + what); 1057 } 1058 1059 static void printMore(Throwable t, String what) { 1060 System.out.println("!"); 1061 } 1062 1063 static String greetMore(String first, String second) { 1064 return "Hello, " + first + " and " + second; 1065 } 1066 1067 static String exclaimMore(Throwable t, String r, String first) { 1068 return r + " (but " + first + " first)!"; 1069 } 1070 1071 static void voidTarget() {} 1072 1073 static void voidCleanup(Throwable t, int a) {} 1074 1075 static final Class<TryFinally> TRY_FINALLY = TryFinally.class; 1076 1077 static final MethodType MT_greet = methodType(String.class, String.class); 1078 static final MethodType MT_exclaim = methodType(String.class, Throwable.class, String.class, String.class); 1079 static final MethodType MT_print = methodType(void.class, String.class); 1080 static final MethodType MT_printMore = methodType(void.class, Throwable.class, String.class); 1081 static final MethodType MT_greetMore = methodType(String.class, String.class, String.class); 1082 static final MethodType MT_exclaimMore = methodType(String.class, Throwable.class, String.class, String.class); 1083 static final MethodType MT_voidTarget = methodType(void.class); 1084 static final MethodType MT_voidCleanup = methodType(void.class, Throwable.class, int.class); 1085 1086 static final MethodHandle MH_greet; 1087 static final MethodHandle MH_exclaim; 1088 static final MethodHandle MH_print; 1089 static final MethodHandle MH_printMore; 1090 static final MethodHandle MH_greetMore; 1091 static final MethodHandle MH_exclaimMore; 1092 static final MethodHandle MH_voidTarget; 1093 static final MethodHandle MH_voidCleanup; 1094 1095 static final MethodType MT_hello = methodType(String.class, String.class); 1096 static final MethodType MT_printHello = methodType(void.class, String.class); 1097 static final MethodType MT_moreHello = methodType(String.class, String.class, String.class); 1098 1099 static { 1100 try { 1101 MH_greet = LOOKUP.findStatic(TRY_FINALLY, "greet", MT_greet); 1102 MH_exclaim = LOOKUP.findStatic(TRY_FINALLY, "exclaim", MT_exclaim); 1103 MH_print = LOOKUP.findStatic(TRY_FINALLY, "print", MT_print); 1104 MH_printMore = LOOKUP.findStatic(TRY_FINALLY, "printMore", MT_printMore); 1105 MH_greetMore = LOOKUP.findStatic(TRY_FINALLY, "greetMore", MT_greetMore); 1106 MH_exclaimMore = LOOKUP.findStatic(TRY_FINALLY, "exclaimMore", MT_exclaimMore); 1107 MH_voidTarget = LOOKUP.findStatic(TRY_FINALLY, "voidTarget", MT_voidTarget); 1108 MH_voidCleanup = LOOKUP.findStatic(TRY_FINALLY, "voidCleanup", MT_voidCleanup); 1109 } catch (Exception e) { 1110 throw new ExceptionInInitializerError(e); 1111 } 1112 } 1113 1114 } 1115 1116 static class Fold { 1117 1118 static int adder(int a, int b, int c) { 1119 return a + b + c; 1120 } 1121 1122 static int adder1(int a, int b) { 1123 return a + b; 1124 } 1125 1126 static int multer(int x, int q, int r, int s) { 1127 return x * q * r * s; 1128 } 1129 1130 static int str(boolean b1, String s, boolean b2, int x) { 1131 return b1 && s.equals(String.valueOf(b2)) ? x : -x; 1132 } 1133 1134 static boolean comb(String s, boolean b2) { 1135 return !s.equals(b2); 1136 } 1137 1138 static String comb2(boolean b2, int x) { 1139 int ib = b2 ? 1 : 0; 1140 return ib == x ? "true" : "false"; 1141 } 1142 1143 static final Class<Fold> FOLD = Fold.class; 1144 1145 static final MethodType MT_adder = methodType(int.class, int.class, int.class, int.class); 1146 static final MethodType MT_adder1 = methodType(int.class, int.class, int.class); 1147 static final MethodType MT_multer = methodType(int.class, int.class, int.class, int.class, int.class); 1148 static final MethodType MT_str = methodType(int.class, boolean.class, String.class, boolean.class, int.class); 1149 static final MethodType MT_comb = methodType(boolean.class, String.class, boolean.class); 1150 static final MethodType MT_comb2 = methodType(String.class, boolean.class, int.class); 1151 1152 static final MethodHandle MH_adder; 1153 static final MethodHandle MH_adder1; 1154 static final MethodHandle MH_multer; 1155 static final MethodHandle MH_str; 1156 static final MethodHandle MH_comb; 1157 static final MethodHandle MH_comb2; 1158 1159 static final MethodType MT_folded1 = methodType(int.class, int.class, int.class, int.class); 1160 static final MethodType MT_folded2 = methodType(int.class, String.class, boolean.class, int.class); 1161 static final MethodType MT_folded3 = methodType(int.class, boolean.class, boolean.class, int.class); 1162 1163 static { 1164 try { 1165 MH_adder = LOOKUP.findStatic(FOLD, "adder", MT_adder); 1166 MH_adder1 = LOOKUP.findStatic(FOLD, "adder1", MT_adder1); 1167 MH_multer = LOOKUP.findStatic(FOLD, "multer", MT_multer); 1168 MH_str = LOOKUP.findStatic(FOLD, "str", MT_str); 1169 MH_comb = LOOKUP.findStatic(FOLD, "comb", MT_comb); 1170 MH_comb2 = LOOKUP.findStatic(FOLD, "comb2", MT_comb2); 1171 } catch (Exception e) { 1172 throw new ExceptionInInitializerError(e); 1173 } 1174 } 1175 } 1176 1177 static class SpreadCollect { 1178 1179 static String forSpreading(String s1, int i1, int i2, int i3, String s2) { 1180 return s1 + i1 + i2 + i3 + s2; 1181 } 1182 1183 static String forCollecting(String s1, int[] is, String s2) { 1184 StringBuilder sb = new StringBuilder(s1); 1185 for (int i : is) { 1186 sb.append(i); 1187 } 1188 return sb.append(s2).toString(); 1189 } 1190 1191 static String forCollectingLeading(int[] is, String s) { 1192 return forCollecting("", is, s); 1193 } 1194 1195 static final Class<SpreadCollect> SPREAD_COLLECT = SpreadCollect.class; 1196 1197 static final MethodType MT_forSpreading = methodType(String.class, String.class, int.class, int.class, int.class, String.class); 1198 static final MethodType MT_forCollecting = methodType(String.class, String.class, int[].class, String.class); 1199 static final MethodType MT_forCollectingLeading = methodType(String.class, int[].class, String.class); 1200 1201 static final MethodHandle MH_forSpreading; 1202 static final MethodHandle MH_forCollecting; 1203 static final MethodHandle MH_forCollectingLeading; 1204 1205 static final MethodType MT_spreader = methodType(String.class, String.class, int[].class, String.class); 1206 static final MethodType MT_collector0 = methodType(String.class, String.class, String.class); 1207 static final MethodType MT_collector1 = methodType(String.class, String.class, int.class, String.class); 1208 static final MethodType MT_collector2 = methodType(String.class, String.class, int.class, int.class, String.class); 1209 static final MethodType MT_collector3 = methodType(String.class, String.class, int.class, int.class, int.class, String.class); 1210 static final MethodType MT_collectorLeading1 = methodType(String.class, int.class, String.class); 1211 static final MethodType MT_collectorLeading2 = methodType(String.class, int.class, int.class, String.class); 1212 static final MethodType MT_collectorLeading3 = methodType(String.class, int.class, int.class, int.class, String.class); 1213 1214 static final String NONE_ERROR = "zero array length in MethodHandle.asCollector"; 1215 1216 static { 1217 try { 1218 MH_forSpreading = LOOKUP.findStatic(SPREAD_COLLECT, "forSpreading", MT_forSpreading); 1219 MH_forCollecting = LOOKUP.findStatic(SPREAD_COLLECT, "forCollecting", MT_forCollecting); 1220 MH_forCollectingLeading = LOOKUP.findStatic(SPREAD_COLLECT, "forCollectingLeading", MT_forCollectingLeading); 1221 } catch (Exception e) { 1222 throw new ExceptionInInitializerError(e); 1223 } 1224 } 1225 1226 } 1227 1228 static class FindSpecial { 1229 1230 interface I1 { 1231 default String m() { 1232 return "I1.m"; 1233 } 1234 } 1235 1236 interface I2 { 1237 default String m() { 1238 return "I2.m"; 1239 } 1240 } 1241 1242 interface I3 { 1243 String q(); 1244 } 1245 1246 static class C implements I1, I2, I3 { 1247 public String m() { 1248 return I1.super.m(); 1249 } 1250 public String q() { 1251 return "q"; 1252 } 1253 } 1254 1255 static final String ABSTRACT_ERROR = "no such method: test.java.lang.invoke.T8139885$FindSpecial$I3.q()String/invokeSpecial"; 1256 1257 } 1258 1259 // 1260 // Auxiliary methods. 1261 // 1262 1263 static MethodHandle[] mha(MethodHandle... mhs) { 1264 return mhs; 1265 } 1266 1267 }