1/* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17package libcore.java.lang.invoke; 18 19import java.lang.Thread; 20import java.lang.invoke.MethodHandle; 21import java.lang.invoke.MethodHandles; 22import java.lang.invoke.MethodType; 23import java.lang.invoke.WrongMethodTypeException; 24import java.util.ArrayList; 25import java.util.Arrays; 26 27import junit.framework.TestCase; 28 29public class MethodHandleCombinersTest extends TestCase { 30 31 static final int TEST_THREAD_ITERATIONS = 1000; 32 33 public static void testThrowException() throws Throwable { 34 MethodHandle handle = MethodHandles.throwException(String.class, 35 IllegalArgumentException.class); 36 37 if (handle.type().returnType() != String.class) { 38 fail("Unexpected return type for handle: " + handle + 39 " [ " + handle.type() + "]"); 40 } 41 42 final IllegalArgumentException iae = new IllegalArgumentException("boo!"); 43 try { 44 handle.invoke(iae); 45 fail("Expected an exception of type: java.lang.IllegalArgumentException"); 46 } catch (IllegalArgumentException expected) { 47 if (expected != iae) { 48 fail("Wrong exception: expected " + iae + " but was " + expected); 49 } 50 } 51 } 52 53 public static void dropArguments_delegate(String message, long message2) { 54 assertEquals("foo", message); 55 assertEquals(42l, message2); 56 } 57 58 public static void testDropArguments() throws Throwable { 59 MethodHandle delegate = MethodHandles.lookup().findStatic(MethodHandleCombinersTest.class, 60 "dropArguments_delegate", 61 MethodType.methodType(void.class, new Class<?>[]{String.class, long.class})); 62 63 MethodHandle transform = MethodHandles.dropArguments( 64 delegate, 0, int.class, Object.class); 65 66 // The transformer will accept two additional arguments at position zero. 67 try { 68 transform.invokeExact("foo", 42l); 69 fail(); 70 } catch (WrongMethodTypeException expected) { 71 } 72 73 transform.invokeExact(45, new Object(), "foo", 42l); 74 transform.invoke(45, new Object(), "foo", 42l); 75 76 // Additional arguments at position 1. 77 transform = MethodHandles.dropArguments(delegate, 1, int.class, Object.class); 78 transform.invokeExact("foo", 45, new Object(), 42l); 79 transform.invoke("foo", 45, new Object(), 42l); 80 81 // Additional arguments at position 2. 82 transform = MethodHandles.dropArguments(delegate, 2, int.class, Object.class); 83 transform.invokeExact("foo", 42l, 45, new Object()); 84 transform.invoke("foo", 42l, 45, new Object()); 85 86 // Note that we still perform argument conversions even for the arguments that 87 // are subsequently dropped. 88 try { 89 transform.invoke("foo", 42l, 45l, new Object()); 90 fail(); 91 } catch (WrongMethodTypeException expected) { 92 } catch (IllegalArgumentException expected) { 93 // TODO(narayan): We currently throw the wrong type of exception here, 94 // it's IAE and should be WMTE instead. 95 } 96 97 // Check that asType works as expected. 98 transform = MethodHandles.dropArguments(delegate, 0, int.class, Object.class); 99 transform = transform.asType(MethodType.methodType(void.class, 100 new Class<?>[]{short.class, Object.class, String.class, long.class})); 101 transform.invokeExact((short) 45, new Object(), "foo", 42l); 102 103 // Invalid argument location, should not be allowed. 104 try { 105 MethodHandles.dropArguments(delegate, -1, int.class, Object.class); 106 fail(); 107 } catch (IllegalArgumentException expected) { 108 } 109 110 // Invalid argument location, should not be allowed. 111 try { 112 MethodHandles.dropArguments(delegate, 3, int.class, Object.class); 113 fail(); 114 } catch (IllegalArgumentException expected) { 115 } 116 117 try { 118 MethodHandles.dropArguments(delegate, 1, void.class); 119 fail(); 120 } catch (IllegalArgumentException expected) { 121 } 122 } 123 124 public static void testDropArguments_List() throws Throwable { 125 MethodHandle delegate = MethodHandles.lookup().findStatic(MethodHandleCombinersTest.class, 126 "dropArguments_delegate", 127 MethodType.methodType(void.class, new Class<?>[]{String.class, long.class})); 128 129 MethodHandle transform = MethodHandles.dropArguments( 130 delegate, 0, Arrays.asList(int.class, Object.class)); 131 132 transform.invokeExact(45, new Object(), "foo", 42l); 133 transform.invoke(45, new Object(), "foo", 42l); 134 135 // Check that asType works as expected. 136 transform = transform.asType(MethodType.methodType(void.class, 137 new Class<?>[]{short.class, Object.class, String.class, long.class})); 138 transform.invokeExact((short) 45, new Object(), "foo", 42l); 139 } 140 141 public static String testCatchException_target(String arg1, long arg2, String exceptionMessage) 142 throws Throwable { 143 if (exceptionMessage != null) { 144 throw new IllegalArgumentException(exceptionMessage); 145 } 146 147 assertEquals(null, exceptionMessage); 148 assertEquals(42l, arg2); 149 return "target"; 150 } 151 152 public static String testCatchException_handler(IllegalArgumentException iae, String arg1, 153 long arg2, 154 String exMsg) { 155 // Check that the thrown exception has the right message. 156 assertEquals("exceptionMessage", iae.getMessage()); 157 // Check the other arguments. 158 assertEquals("foo", arg1); 159 assertEquals(42, arg2); 160 assertEquals("exceptionMessage", exMsg); 161 162 return "handler1"; 163 } 164 165 public static String testCatchException_handler2(IllegalArgumentException iae, String arg1) { 166 assertEquals("exceptionMessage", iae.getMessage()); 167 assertEquals("foo", arg1); 168 169 return "handler2"; 170 } 171 172 public static void testCatchException() throws Throwable { 173 MethodHandle target = MethodHandles.lookup().findStatic(MethodHandleCombinersTest.class, 174 "testCatchException_target", 175 MethodType 176 .methodType(String.class, new Class<?>[]{String.class, long.class, String.class})); 177 178 MethodHandle handler = MethodHandles.lookup().findStatic(MethodHandleCombinersTest.class, 179 "testCatchException_handler", 180 MethodType.methodType(String.class, new Class<?>[]{IllegalArgumentException.class, 181 String.class, long.class, String.class})); 182 183 MethodHandle adapter = MethodHandles.catchException(target, IllegalArgumentException.class, 184 handler); 185 186 String returnVal = null; 187 188 // These two should end up calling the target always. We're passing a null exception 189 // message here, which means the target will not throw. 190 returnVal = (String) adapter.invoke("foo", 42, null); 191 assertEquals("target", returnVal); 192 returnVal = (String) adapter.invokeExact("foo", 42l, (String) null); 193 assertEquals("target", returnVal); 194 195 // We're passing a non-null exception message here, which means the target will throw, 196 // which in turn means that the handler must be called for the next two invokes. 197 returnVal = (String) adapter.invoke("foo", 42, "exceptionMessage"); 198 assertEquals("handler1", returnVal); 199 returnVal = (String) adapter.invokeExact("foo", 42l, "exceptionMessage"); 200 assertEquals("handler1", returnVal); 201 202 handler = MethodHandles.lookup().findStatic(MethodHandleCombinersTest.class, 203 "testCatchException_handler2", 204 MethodType.methodType(String.class, new Class<?>[]{IllegalArgumentException.class, 205 String.class})); 206 adapter = MethodHandles.catchException(target, IllegalArgumentException.class, handler); 207 208 returnVal = (String) adapter.invoke("foo", 42, "exceptionMessage"); 209 assertEquals("handler2", returnVal); 210 returnVal = (String) adapter.invokeExact("foo", 42l, "exceptionMessage"); 211 assertEquals("handler2", returnVal); 212 213 // Test that the type of the invoke doesn't matter. Here we call 214 // IllegalArgumentException.toString() on the exception that was thrown by 215 // the target. 216 handler = MethodHandles.lookup().findVirtual(IllegalArgumentException.class, 217 "toString", MethodType.methodType(String.class)); 218 adapter = MethodHandles.catchException(target, IllegalArgumentException.class, handler); 219 220 returnVal = (String) adapter.invoke("foo", 42, "exceptionMessage"); 221 assertEquals("java.lang.IllegalArgumentException: exceptionMessage", returnVal); 222 returnVal = (String) adapter.invokeExact("foo", 42l, "exceptionMessage"); 223 assertEquals("java.lang.IllegalArgumentException: exceptionMessage", returnVal); 224 225 // Check that asType works as expected. 226 adapter = MethodHandles.catchException(target, IllegalArgumentException.class, 227 handler); 228 adapter = adapter.asType(MethodType.methodType(String.class, 229 new Class<?>[]{String.class, int.class, String.class})); 230 returnVal = (String) adapter.invokeExact("foo", 42, "exceptionMessage"); 231 assertEquals("java.lang.IllegalArgumentException: exceptionMessage", returnVal); 232 } 233 234 public static boolean testGuardWithTest_test(String arg1, long arg2) { 235 return "target".equals(arg1) && 42 == arg2; 236 } 237 238 public static String testGuardWithTest_target(String arg1, long arg2, int arg3) { 239 // Make sure that the test passed. 240 assertTrue(testGuardWithTest_test(arg1, arg2)); 241 // Make sure remaining arguments were passed through unmodified. 242 assertEquals(56, arg3); 243 244 return "target"; 245 } 246 247 public static String testGuardWithTest_fallback(String arg1, long arg2, int arg3) { 248 // Make sure that the test failed. 249 assertTrue(!testGuardWithTest_test(arg1, arg2)); 250 // Make sure remaining arguments were passed through unmodified. 251 assertEquals(56, arg3); 252 253 return "fallback"; 254 } 255 256 public static void testGuardWithTest() throws Throwable { 257 MethodHandle test = MethodHandles.lookup().findStatic(MethodHandleCombinersTest.class, 258 "testGuardWithTest_test", 259 MethodType.methodType(boolean.class, new Class<?>[]{String.class, long.class})); 260 261 final MethodType type = MethodType.methodType(String.class, 262 new Class<?>[]{String.class, long.class, int.class}); 263 264 final MethodHandle target = MethodHandles.lookup().findStatic(MethodHandleCombinersTest.class, 265 "testGuardWithTest_target", type); 266 final MethodHandle fallback = MethodHandles.lookup().findStatic(MethodHandleCombinersTest.class, 267 "testGuardWithTest_fallback", type); 268 269 MethodHandle adapter = MethodHandles.guardWithTest(test, target, fallback); 270 271 String returnVal = null; 272 273 returnVal = (String) adapter.invoke("target", 42, 56); 274 assertEquals("target", returnVal); 275 returnVal = (String) adapter.invokeExact("target", 42l, 56); 276 assertEquals("target", returnVal); 277 278 returnVal = (String) adapter.invoke("fallback", 42l, 56); 279 assertEquals("fallback", returnVal); 280 returnVal = (String) adapter.invoke("target", 46l, 56); 281 assertEquals("fallback", returnVal); 282 returnVal = (String) adapter.invokeExact("target", 42l, 56); 283 assertEquals("target", returnVal); 284 285 // Check that asType works as expected. 286 adapter = adapter.asType(MethodType.methodType(String.class, 287 new Class<?>[]{String.class, int.class, int.class})); 288 returnVal = (String) adapter.invokeExact("target", 42, 56); 289 assertEquals("target", returnVal); 290 } 291 292 public static void testArrayElementGetter() throws Throwable { 293 MethodHandle getter = MethodHandles.arrayElementGetter(int[].class); 294 295 { 296 int[] array = new int[1]; 297 array[0] = 42; 298 int value = (int) getter.invoke(array, 0); 299 assertEquals(42, value); 300 301 try { 302 value = (int) getter.invoke(array, -1); 303 fail(); 304 } catch (ArrayIndexOutOfBoundsException expected) { 305 } 306 307 try { 308 value = (int) getter.invoke(null, -1); 309 fail(); 310 } catch (NullPointerException expected) { 311 } 312 } 313 314 { 315 getter = MethodHandles.arrayElementGetter(long[].class); 316 long[] array = new long[1]; 317 array[0] = 42; 318 long value = (long) getter.invoke(array, 0); 319 assertEquals(42l, value); 320 } 321 322 { 323 getter = MethodHandles.arrayElementGetter(short[].class); 324 short[] array = new short[1]; 325 array[0] = 42; 326 short value = (short) getter.invoke(array, 0); 327 assertEquals((short) 42, value); 328 } 329 330 { 331 getter = MethodHandles.arrayElementGetter(char[].class); 332 char[] array = new char[1]; 333 array[0] = 42; 334 char value = (char) getter.invoke(array, 0); 335 assertEquals((char) 42, value); 336 } 337 338 { 339 getter = MethodHandles.arrayElementGetter(byte[].class); 340 byte[] array = new byte[1]; 341 array[0] = (byte) 0x8; 342 byte value = (byte) getter.invoke(array, 0); 343 assertEquals((byte) 0x8, value); 344 } 345 346 { 347 getter = MethodHandles.arrayElementGetter(boolean[].class); 348 boolean[] array = new boolean[1]; 349 array[0] = true; 350 boolean value = (boolean) getter.invoke(array, 0); 351 assertTrue(value); 352 } 353 354 { 355 getter = MethodHandles.arrayElementGetter(float[].class); 356 float[] array = new float[1]; 357 array[0] = 42.0f; 358 float value = (float) getter.invoke(array, 0); 359 assertEquals(42.0f, value); 360 } 361 362 { 363 getter = MethodHandles.arrayElementGetter(double[].class); 364 double[] array = new double[1]; 365 array[0] = 42.0; 366 double value = (double) getter.invoke(array, 0); 367 assertEquals(42.0, value); 368 } 369 370 { 371 getter = MethodHandles.arrayElementGetter(String[].class); 372 String[] array = new String[3]; 373 array[0] = "42"; 374 array[1] = "48"; 375 array[2] = "54"; 376 String value = (String) getter.invoke(array, 0); 377 assertEquals("42", value); 378 value = (String) getter.invoke(array, 1); 379 assertEquals("48", value); 380 value = (String) getter.invoke(array, 2); 381 assertEquals("54", value); 382 } 383 } 384 385 public static void testArrayElementSetter() throws Throwable { 386 MethodHandle setter = MethodHandles.arrayElementSetter(int[].class); 387 388 { 389 int[] array = new int[2]; 390 setter.invoke(array, 0, 42); 391 setter.invoke(array, 1, 43); 392 393 assertEquals(42, array[0]); 394 assertEquals(43, array[1]); 395 396 try { 397 setter.invoke(array, -1, 42); 398 fail(); 399 } catch (ArrayIndexOutOfBoundsException expected) { 400 } 401 402 try { 403 setter.invoke(null, 0, 42); 404 fail(); 405 } catch (NullPointerException expected) { 406 } 407 } 408 409 { 410 setter = MethodHandles.arrayElementSetter(long[].class); 411 long[] array = new long[1]; 412 setter.invoke(array, 0, 42l); 413 assertEquals(42l, array[0]); 414 } 415 416 { 417 setter = MethodHandles.arrayElementSetter(short[].class); 418 short[] array = new short[1]; 419 setter.invoke(array, 0, (short) 42); 420 assertEquals((short) 42, array[0]); 421 } 422 423 { 424 setter = MethodHandles.arrayElementSetter(char[].class); 425 char[] array = new char[1]; 426 setter.invoke(array, 0, (char) 42); 427 assertEquals((char) 42, array[0]); 428 } 429 430 { 431 setter = MethodHandles.arrayElementSetter(byte[].class); 432 byte[] array = new byte[1]; 433 setter.invoke(array, 0, (byte) 0x8); 434 assertEquals((byte) 0x8, array[0]); 435 } 436 437 { 438 setter = MethodHandles.arrayElementSetter(boolean[].class); 439 boolean[] array = new boolean[1]; 440 setter.invoke(array, 0, true); 441 assertTrue(array[0]); 442 } 443 444 { 445 setter = MethodHandles.arrayElementSetter(float[].class); 446 float[] array = new float[1]; 447 setter.invoke(array, 0, 42.0f); 448 assertEquals(42.0f, array[0]); 449 } 450 451 { 452 setter = MethodHandles.arrayElementSetter(double[].class); 453 double[] array = new double[1]; 454 setter.invoke(array, 0, 42.0); 455 assertEquals(42.0, array[0]); 456 } 457 458 { 459 setter = MethodHandles.arrayElementSetter(String[].class); 460 String[] array = new String[3]; 461 setter.invoke(array, 0, "42"); 462 setter.invoke(array, 1, "48"); 463 setter.invoke(array, 2, "54"); 464 assertEquals("42", array[0]); 465 assertEquals("48", array[1]); 466 assertEquals("54", array[2]); 467 } 468 } 469 470 public static void testIdentity() throws Throwable { 471 { 472 MethodHandle identity = MethodHandles.identity(boolean.class); 473 boolean value = (boolean) identity.invoke(false); 474 assertFalse(value); 475 } 476 477 { 478 MethodHandle identity = MethodHandles.identity(byte.class); 479 byte value = (byte) identity.invoke((byte) 0x8); 480 assertEquals((byte) 0x8, value); 481 } 482 483 { 484 MethodHandle identity = MethodHandles.identity(char.class); 485 char value = (char) identity.invoke((char) -56); 486 assertEquals((char) -56, value); 487 } 488 489 { 490 MethodHandle identity = MethodHandles.identity(short.class); 491 short value = (short) identity.invoke((short) -59); 492 assertEquals((short) -59, value); 493 } 494 495 { 496 MethodHandle identity = MethodHandles.identity(int.class); 497 int value = (int) identity.invoke(52); 498 assertEquals((int) 52, value); 499 } 500 501 { 502 MethodHandle identity = MethodHandles.identity(long.class); 503 long value = (long) identity.invoke(-76l); 504 assertEquals(-76l, value); 505 } 506 507 { 508 MethodHandle identity = MethodHandles.identity(float.class); 509 float value = (float) identity.invoke(56.0f); 510 assertEquals(56.0f, value); 511 } 512 513 { 514 MethodHandle identity = MethodHandles.identity(double.class); 515 double value = (double) identity.invoke((double) 72.0); 516 assertEquals(72.0, value); 517 } 518 519 { 520 MethodHandle identity = MethodHandles.identity(String.class); 521 String value = (String) identity.invoke("bazman"); 522 assertEquals("bazman", value); 523 } 524 } 525 526 public static void testConstant() throws Throwable { 527 // int constants. 528 { 529 MethodHandle constant = MethodHandles.constant(int.class, 56); 530 assertEquals(56, (int) constant.invoke()); 531 532 // short constant values are converted to int. 533 constant = MethodHandles.constant(int.class, (short) 52); 534 assertEquals(52, (int) constant.invoke()); 535 536 // char constant values are converted to int. 537 constant = MethodHandles.constant(int.class, (char) 'b'); 538 assertEquals('b', (int) constant.invoke()); 539 540 // int constant values are converted to int. 541 constant = MethodHandles.constant(int.class, (byte) 0x1); 542 assertEquals(0x1, (int) constant.invoke()); 543 544 // boolean, float, double and long primitive constants are not convertible 545 // to int, so the handle creation must fail with a CCE. 546 try { 547 MethodHandles.constant(int.class, false); 548 fail(); 549 } catch (ClassCastException expected) { 550 } 551 552 try { 553 MethodHandles.constant(int.class, 0.1f); 554 fail(); 555 } catch (ClassCastException expected) { 556 } 557 558 try { 559 MethodHandles.constant(int.class, 0.2); 560 fail(); 561 } catch (ClassCastException expected) { 562 } 563 564 try { 565 MethodHandles.constant(int.class, 73l); 566 fail(); 567 } catch (ClassCastException expected) { 568 } 569 } 570 571 // long constants. 572 { 573 MethodHandle constant = MethodHandles.constant(long.class, 56l); 574 assertEquals(56l, (long) constant.invoke()); 575 576 constant = MethodHandles.constant(long.class, (int) 56); 577 assertEquals(56l, (long) constant.invoke()); 578 } 579 580 // byte constants. 581 { 582 MethodHandle constant = MethodHandles.constant(byte.class, (byte) 0x12); 583 assertEquals((byte) 0x12, (byte) constant.invoke()); 584 } 585 586 // boolean constants. 587 { 588 MethodHandle constant = MethodHandles.constant(boolean.class, true); 589 assertTrue((boolean) constant.invoke()); 590 } 591 592 // char constants. 593 { 594 MethodHandle constant = MethodHandles.constant(char.class, 'f'); 595 assertEquals('f', (char) constant.invoke()); 596 } 597 598 // short constants. 599 { 600 MethodHandle constant = MethodHandles.constant(short.class, (short) 123); 601 assertEquals((short) 123, (short) constant.invoke()); 602 } 603 604 // float constants. 605 { 606 MethodHandle constant = MethodHandles.constant(float.class, 56.0f); 607 assertEquals(56.0f, (float) constant.invoke()); 608 } 609 610 // double constants. 611 { 612 MethodHandle constant = MethodHandles.constant(double.class, 256.0); 613 assertEquals(256.0, (double) constant.invoke()); 614 } 615 616 // reference constants. 617 { 618 MethodHandle constant = MethodHandles.constant(String.class, "256.0"); 619 assertEquals("256.0", (String) constant.invoke()); 620 } 621 } 622 623 public static void testBindTo() throws Throwable { 624 MethodHandle stringCharAt = MethodHandles.lookup().findVirtual( 625 String.class, "charAt", MethodType.methodType(char.class, int.class)); 626 627 char value = (char) stringCharAt.invoke("foo", 0); 628 if (value != 'f') { 629 fail("Unexpected value: " + value); 630 } 631 632 MethodHandle bound = stringCharAt.bindTo("foo"); 633 value = (char) bound.invoke(0); 634 if (value != 'f') { 635 fail("Unexpected value: " + value); 636 } 637 638 try { 639 stringCharAt.bindTo(new Object()); 640 fail(); 641 } catch (ClassCastException expected) { 642 } 643 644 bound = stringCharAt.bindTo(null); 645 try { 646 bound.invoke(0); 647 fail(); 648 } catch (NullPointerException expected) { 649 } 650 651 MethodHandle integerParseInt = MethodHandles.lookup().findStatic( 652 Integer.class, "parseInt", MethodType.methodType(int.class, String.class)); 653 654 bound = integerParseInt.bindTo("78452"); 655 int intValue = (int) bound.invoke(); 656 if (intValue != 78452) { 657 fail("Unexpected value: " + intValue); 658 } 659 } 660 661 public static String filterReturnValue_target(int a) { 662 return "ReturnValue" + a; 663 } 664 665 public static boolean filterReturnValue_filter(String value) { 666 return value.indexOf("42") != -1; 667 } 668 669 public static int filterReturnValue_intTarget(String a) { 670 return Integer.parseInt(a); 671 } 672 673 public static int filterReturnValue_intFilter(int b) { 674 return b + 1; 675 } 676 677 public static void filterReturnValue_voidTarget() { 678 } 679 680 public static int filterReturnValue_voidFilter() { 681 return 42; 682 } 683 684 public static void testFilterReturnValue() throws Throwable { 685 // A target that returns a reference. 686 { 687 final MethodHandle target = MethodHandles.lookup().findStatic(MethodHandleCombinersTest.class, 688 "filterReturnValue_target", MethodType.methodType(String.class, int.class)); 689 final MethodHandle filter = MethodHandles.lookup().findStatic(MethodHandleCombinersTest.class, 690 "filterReturnValue_filter", MethodType.methodType(boolean.class, String.class)); 691 692 MethodHandle adapter = MethodHandles.filterReturnValue(target, filter); 693 694 boolean value = (boolean) adapter.invoke((int) 42); 695 if (!value) { 696 fail("Unexpected value: " + value); 697 } 698 value = (boolean) adapter.invoke((int) 43); 699 if (value) { 700 fail("Unexpected value: " + value); 701 } 702 } 703 704 // A target that returns a primitive. 705 { 706 final MethodHandle target = MethodHandles.lookup().findStatic(MethodHandleCombinersTest.class, 707 "filterReturnValue_intTarget", MethodType.methodType(int.class, String.class)); 708 final MethodHandle filter = MethodHandles.lookup().findStatic(MethodHandleCombinersTest.class, 709 "filterReturnValue_intFilter", MethodType.methodType(int.class, int.class)); 710 711 MethodHandle adapter = MethodHandles.filterReturnValue(target, filter); 712 713 int value = (int) adapter.invoke("56"); 714 if (value != 57) { 715 fail("Unexpected value: " + value); 716 } 717 } 718 719 // A target that returns void. 720 { 721 final MethodHandle target = MethodHandles.lookup().findStatic(MethodHandleCombinersTest.class, 722 "filterReturnValue_voidTarget", MethodType.methodType(void.class)); 723 final MethodHandle filter = MethodHandles.lookup().findStatic(MethodHandleCombinersTest.class, 724 "filterReturnValue_voidFilter", MethodType.methodType(int.class)); 725 726 MethodHandle adapter = MethodHandles.filterReturnValue(target, filter); 727 728 int value = (int) adapter.invoke(); 729 if (value != 42) { 730 fail("Unexpected value: " + value); 731 } 732 } 733 } 734 735 public static void permuteArguments_callee(boolean a, byte b, char c, 736 short d, int e, long f, float g, double h) { 737 assertTrue(a); 738 assertEquals((byte) 'b', b); 739 assertEquals('c', c); 740 assertEquals((short) 56, d); 741 assertEquals(78, e); 742 assertEquals(97l, f); 743 assertEquals(98.0f, g); 744 assertEquals(97.0, h); 745 } 746 747 public static void permuteArguments_boxingCallee(boolean a, Integer b) { 748 assertTrue(a); 749 assertEquals(Integer.valueOf(42), b); 750 } 751 752 public static void testPermuteArguments() throws Throwable { 753 { 754 final MethodHandle target = MethodHandles.lookup().findStatic( 755 MethodHandleCombinersTest.class, "permuteArguments_callee", 756 MethodType.methodType(void.class, new Class<?>[]{ 757 boolean.class, byte.class, char.class, short.class, int.class, 758 long.class, float.class, double.class})); 759 760 final MethodType newType = MethodType.methodType(void.class, new Class<?>[]{ 761 double.class, float.class, long.class, int.class, short.class, char.class, 762 byte.class, boolean.class}); 763 764 final MethodHandle permutation = MethodHandles.permuteArguments( 765 target, newType, new int[]{7, 6, 5, 4, 3, 2, 1, 0}); 766 767 permutation.invoke((double) 97.0, (float) 98.0f, (long) 97, 78, 768 (short) 56, 'c', (byte) 'b', (boolean) true); 769 770 // The permutation array was not of the right length. 771 try { 772 MethodHandles.permuteArguments(target, newType, 773 new int[]{7}); 774 fail(); 775 } catch (IllegalArgumentException expected) { 776 } 777 778 // The permutation array has an element that's out of bounds 779 // (there's no argument with idx == 8). 780 try { 781 MethodHandles.permuteArguments(target, newType, 782 new int[]{8, 6, 5, 4, 3, 2, 1, 0}); 783 fail(); 784 } catch (IllegalArgumentException expected) { 785 } 786 787 // The permutation array maps to an incorrect type. 788 try { 789 MethodHandles.permuteArguments(target, newType, 790 new int[]{7, 7, 5, 4, 3, 2, 1, 0}); 791 fail(); 792 } catch (IllegalArgumentException expected) { 793 } 794 } 795 796 // Tests for reference arguments as well as permutations that 797 // repeat arguments. 798 { 799 final MethodHandle target = MethodHandles.lookup().findVirtual( 800 String.class, "concat", MethodType.methodType(String.class, String.class)); 801 802 final MethodType newType = MethodType.methodType(String.class, String.class, 803 String.class); 804 805 assertEquals("foobar", (String) target.invoke("foo", "bar")); 806 807 MethodHandle permutation = MethodHandles.permuteArguments(target, 808 newType, new int[]{1, 0}); 809 assertEquals("barfoo", (String) permutation.invoke("foo", "bar")); 810 811 permutation = MethodHandles.permuteArguments(target, newType, new int[]{0, 0}); 812 assertEquals("foofoo", (String) permutation.invoke("foo", "bar")); 813 814 permutation = MethodHandles.permuteArguments(target, newType, new int[]{1, 1}); 815 assertEquals("barbar", (String) permutation.invoke("foo", "bar")); 816 } 817 818 // Tests for boxing and unboxing. 819 { 820 final MethodHandle target = MethodHandles.lookup().findStatic( 821 MethodHandleCombinersTest.class, "permuteArguments_boxingCallee", 822 MethodType.methodType(void.class, new Class<?>[]{boolean.class, Integer.class})); 823 824 final MethodType newType = MethodType.methodType(void.class, 825 new Class<?>[]{Integer.class, boolean.class}); 826 827 MethodHandle permutation = MethodHandles.permuteArguments(target, 828 newType, new int[]{1, 0}); 829 830 permutation.invoke(42, true); 831 permutation.invoke(42, Boolean.TRUE); 832 permutation.invoke(Integer.valueOf(42), true); 833 permutation.invoke(Integer.valueOf(42), Boolean.TRUE); 834 } 835 } 836 837 private static Object returnBar() { 838 return "bar"; 839 } 840 841 public static void testInvokers() throws Throwable { 842 final MethodType targetType = MethodType.methodType(String.class, String.class); 843 final MethodHandle target = MethodHandles.lookup().findVirtual( 844 String.class, "concat", targetType); 845 846 MethodHandle invoker = MethodHandles.invoker(target.type()); 847 assertEquals("barbar", (String) invoker.invoke(target, "bar", "bar")); 848 assertEquals("barbar", (String) invoker.invoke(target, (Object) returnBar(), "bar")); 849 try { 850 String foo = (String) invoker.invoke(target, "bar", "bar", 24); 851 fail(); 852 } catch (WrongMethodTypeException expected) { 853 } 854 855 MethodHandle exactInvoker = MethodHandles.exactInvoker(target.type()); 856 assertEquals("barbar", (String) exactInvoker.invoke(target, "bar", "bar")); 857 try { 858 String foo = (String) exactInvoker.invoke(target, (Object) returnBar(), "bar"); 859 fail(); 860 } catch (WrongMethodTypeException expected) { 861 } 862 try { 863 String foo = (String) exactInvoker.invoke(target, "bar", "bar", 24); 864 fail(); 865 } catch (WrongMethodTypeException expected) { 866 } 867 } 868 869 public static int spreadReferences(String a, String b, String c) { 870 assertEquals("a", a); 871 assertEquals("b", b); 872 assertEquals("c", c); 873 return 42; 874 } 875 876 public static int spreadReferences_Unbox(String a, int b) { 877 assertEquals("a", a); 878 assertEquals(43, b); 879 return 43; 880 } 881 882 public static void testSpreaders_reference() throws Throwable { 883 MethodType methodType = MethodType.methodType(int.class, 884 new Class<?>[]{String.class, String.class, String.class}); 885 MethodHandle delegate = MethodHandles.lookup().findStatic( 886 MethodHandleCombinersTest.class, "spreadReferences", methodType); 887 888 // Basic checks on array lengths. 889 // 890 // Array size = 0 891 MethodHandle mhAsSpreader = delegate.asSpreader(String[].class, 0); 892 int ret = (int) mhAsSpreader.invoke("a", "b", "c", new String[]{}); 893 assertEquals(42, ret); 894 // Array size = 1 895 mhAsSpreader = delegate.asSpreader(String[].class, 1); 896 ret = (int) mhAsSpreader.invoke("a", "b", new String[]{"c"}); 897 assertEquals(42, ret); 898 // Array size = 2 899 mhAsSpreader = delegate.asSpreader(String[].class, 2); 900 ret = (int) mhAsSpreader.invoke("a", new String[]{"b", "c"}); 901 assertEquals(42, ret); 902 // Array size = 3 903 mhAsSpreader = delegate.asSpreader(String[].class, 3); 904 ret = (int) mhAsSpreader.invoke(new String[]{"a", "b", "c"}); 905 assertEquals(42, ret); 906 907 // Exception case, array size = 4 is illegal. 908 try { 909 delegate.asSpreader(String[].class, 4); 910 fail(); 911 } catch (IllegalArgumentException expected) { 912 } 913 914 // Exception case, calling with an arg of the wrong size. 915 // Array size = 3 916 mhAsSpreader = delegate.asSpreader(String[].class, 3); 917 try { 918 ret = (int) mhAsSpreader.invoke(new String[]{"a", "b"}); 919 } catch (IllegalArgumentException expected) { 920 } 921 922 // Various other hijinks, pass as Object[] arrays, Object etc. 923 mhAsSpreader = delegate.asSpreader(Object[].class, 2); 924 ret = (int) mhAsSpreader.invoke("a", new String[]{"b", "c"}); 925 assertEquals(42, ret); 926 927 mhAsSpreader = delegate.asSpreader(Object[].class, 2); 928 ret = (int) mhAsSpreader.invoke("a", new Object[]{"b", "c"}); 929 assertEquals(42, ret); 930 931 mhAsSpreader = delegate.asSpreader(Object[].class, 2); 932 ret = (int) mhAsSpreader.invoke("a", (Object) new Object[]{"b", "c"}); 933 assertEquals(42, ret); 934 935 // Test implicit unboxing. 936 MethodType methodType2 = MethodType.methodType(int.class, 937 new Class<?>[]{String.class, int.class}); 938 MethodHandle delegate2 = MethodHandles.lookup().findStatic( 939 MethodHandleCombinersTest.class, "spreadReferences_Unbox", methodType2); 940 941 // .. with an Integer[] array. 942 mhAsSpreader = delegate2.asSpreader(Integer[].class, 1); 943 ret = (int) mhAsSpreader.invoke("a", new Integer[]{43}); 944 assertEquals(43, ret); 945 946 // .. with an Integer[] array declared as an Object[] argument type. 947 mhAsSpreader = delegate2.asSpreader(Object[].class, 1); 948 ret = (int) mhAsSpreader.invoke("a", new Integer[]{43}); 949 assertEquals(43, ret); 950 951 // .. with an Object[] array. 952 mhAsSpreader = delegate2.asSpreader(Object[].class, 1); 953 ret = (int) mhAsSpreader.invoke("a", new Object[]{Integer.valueOf(43)}); 954 assertEquals(43, ret); 955 956 // -- Part 2-- 957 // Run a subset of these tests on MethodHandles.spreadInvoker, which only accepts 958 // a trailing argument type of Object[]. 959 MethodHandle spreadInvoker = MethodHandles.spreadInvoker(methodType2, 1); 960 ret = (int) spreadInvoker.invoke(delegate2, "a", new Object[]{Integer.valueOf(43)}); 961 assertEquals(43, ret); 962 963 ret = (int) spreadInvoker.invoke(delegate2, "a", new Integer[]{43}); 964 assertEquals(43, ret); 965 966 // NOTE: Annoyingly, the second argument here is leadingArgCount and not 967 // arrayLength. 968 spreadInvoker = MethodHandles.spreadInvoker(methodType, 3); 969 ret = (int) spreadInvoker.invoke(delegate, "a", "b", "c", new String[]{}); 970 assertEquals(42, ret); 971 972 spreadInvoker = MethodHandles.spreadInvoker(methodType, 0); 973 ret = (int) spreadInvoker.invoke(delegate, new String[]{"a", "b", "c"}); 974 assertEquals(42, ret); 975 976 // Exact invokes: Double check that the expected parameter type is 977 // Object[] and not T[]. 978 try { 979 spreadInvoker.invokeExact(delegate, new String[]{"a", "b", "c"}); 980 fail(); 981 } catch (WrongMethodTypeException expected) { 982 } 983 984 ret = (int) spreadInvoker.invoke(delegate, new Object[]{"a", "b", "c"}); 985 assertEquals(42, ret); 986 } 987 988 public static int spreadBoolean(String a, Boolean b, boolean c) { 989 assertEquals("a", a); 990 assertSame(Boolean.TRUE, b); 991 assertFalse(c); 992 993 return 44; 994 } 995 996 public static int spreadByte(String a, Byte b, byte c, 997 short d, int e, long f, float g, double h) { 998 assertEquals("a", a); 999 assertEquals(Byte.valueOf((byte) 1), b); 1000 assertEquals((byte) 2, c); 1001 assertEquals((short) 3, d); 1002 assertEquals(4, e); 1003 assertEquals(5l, f); 1004 assertEquals(6.0f, g); 1005 assertEquals(7.0, h); 1006 1007 return 45; 1008 } 1009 1010 public static int spreadChar(String a, Character b, char c, 1011 int d, long e, float f, double g) { 1012 assertEquals("a", a); 1013 assertEquals(Character.valueOf('1'), b); 1014 assertEquals('2', c); 1015 assertEquals((short) '3', d); 1016 assertEquals('4', e); 1017 assertEquals((float) '5', f); 1018 assertEquals((double) '6', g); 1019 1020 return 46; 1021 } 1022 1023 public static int spreadShort(String a, Short b, short c, 1024 int d, long e, float f, double g) { 1025 assertEquals("a", a); 1026 assertEquals(Short.valueOf((short) 1), b); 1027 assertEquals(2, c); 1028 assertEquals(3, d); 1029 assertEquals(4l, e); 1030 assertEquals(5.0f, f); 1031 assertEquals(6.0, g); 1032 1033 return 47; 1034 } 1035 1036 public static int spreadInt(String a, Integer b, int c, 1037 long d, float e, double f) { 1038 assertEquals("a", a); 1039 assertEquals(Integer.valueOf(1), b); 1040 assertEquals(2, c); 1041 assertEquals(3l, d); 1042 assertEquals(4.0f, e); 1043 assertEquals(5.0, f); 1044 1045 return 48; 1046 } 1047 1048 public static int spreadLong(String a, Long b, long c, float d, double e) { 1049 assertEquals("a", a); 1050 assertEquals(Long.valueOf(1), b); 1051 assertEquals(2l, c); 1052 assertEquals(3.0f, d); 1053 assertEquals(4.0, e); 1054 1055 return 49; 1056 } 1057 1058 public static int spreadFloat(String a, Float b, float c, double d) { 1059 assertEquals("a", a); 1060 assertEquals(Float.valueOf(1.0f), b); 1061 assertEquals(2.0f, c); 1062 assertEquals(3.0, d); 1063 1064 return 50; 1065 } 1066 1067 public static int spreadDouble(String a, Double b, double c) { 1068 assertEquals("a", a); 1069 assertEquals(Double.valueOf(1.0), b); 1070 assertEquals(2.0, c); 1071 1072 return 51; 1073 } 1074 1075 public static void testSpreaders_primitive() throws Throwable { 1076 // boolean[] 1077 // --------------------- 1078 MethodType type = MethodType.methodType(int.class, 1079 new Class<?>[]{String.class, Boolean.class, boolean.class}); 1080 MethodHandle delegate = MethodHandles.lookup().findStatic( 1081 MethodHandleCombinersTest.class, "spreadBoolean", type); 1082 1083 MethodHandle spreader = delegate.asSpreader(boolean[].class, 2); 1084 int ret = (int) spreader.invokeExact("a", new boolean[]{true, false}); 1085 assertEquals(44, ret); 1086 ret = (int) spreader.invoke("a", new boolean[]{true, false}); 1087 assertEquals(44, ret); 1088 1089 // boolean can't be cast to String (the first argument to the method). 1090 try { 1091 delegate.asSpreader(boolean[].class, 3); 1092 fail(); 1093 } catch (WrongMethodTypeException expected) { 1094 } 1095 1096 // int can't be cast to boolean to supply the last argument to the method. 1097 try { 1098 delegate.asSpreader(int[].class, 1); 1099 fail(); 1100 } catch (WrongMethodTypeException expected) { 1101 } 1102 1103 // byte[] 1104 // --------------------- 1105 type = MethodType.methodType(int.class, 1106 new Class<?>[]{ 1107 String.class, Byte.class, byte.class, 1108 short.class, int.class, long.class, 1109 float.class, double.class}); 1110 delegate = MethodHandles.lookup().findStatic(MethodHandleCombinersTest.class, "spreadByte", type); 1111 1112 spreader = delegate.asSpreader(byte[].class, 7); 1113 ret = (int) spreader.invokeExact("a", 1114 new byte[]{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7}); 1115 assertEquals(45, ret); 1116 ret = (int) spreader.invoke("a", 1117 new byte[]{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7}); 1118 assertEquals(45, ret); 1119 1120 // char[] 1121 // --------------------- 1122 type = MethodType.methodType(int.class, 1123 new Class<?>[]{ 1124 String.class, Character.class, char.class, 1125 int.class, long.class, float.class, double.class}); 1126 delegate = MethodHandles.lookup().findStatic(MethodHandleCombinersTest.class, "spreadChar", type); 1127 1128 spreader = delegate.asSpreader(char[].class, 6); 1129 ret = (int) spreader.invokeExact("a", 1130 new char[]{'1', '2', '3', '4', '5', '6'}); 1131 assertEquals(46, ret); 1132 ret = (int) spreader.invokeExact("a", 1133 new char[]{'1', '2', '3', '4', '5', '6'}); 1134 assertEquals(46, ret); 1135 1136 // short[] 1137 // --------------------- 1138 type = MethodType.methodType(int.class, 1139 new Class<?>[]{ 1140 String.class, Short.class, short.class, 1141 int.class, long.class, float.class, double.class}); 1142 delegate = MethodHandles.lookup().findStatic(MethodHandleCombinersTest.class, "spreadShort", type); 1143 1144 spreader = delegate.asSpreader(short[].class, 6); 1145 ret = (int) spreader.invokeExact("a", 1146 new short[]{0x1, 0x2, 0x3, 0x4, 0x5, 0x6}); 1147 assertEquals(47, ret); 1148 ret = (int) spreader.invoke("a", 1149 new short[]{0x1, 0x2, 0x3, 0x4, 0x5, 0x6}); 1150 assertEquals(47, ret); 1151 1152 // int[] 1153 // --------------------- 1154 type = MethodType.methodType(int.class, 1155 new Class<?>[]{ 1156 String.class, Integer.class, int.class, 1157 long.class, float.class, double.class}); 1158 delegate = MethodHandles.lookup().findStatic(MethodHandleCombinersTest.class, "spreadInt", type); 1159 1160 spreader = delegate.asSpreader(int[].class, 5); 1161 ret = (int) spreader.invokeExact("a", new int[]{1, 2, 3, 4, 5}); 1162 assertEquals(48, ret); 1163 ret = (int) spreader.invokeExact("a", new int[]{1, 2, 3, 4, 5}); 1164 assertEquals(48, ret); 1165 1166 // long[] 1167 // --------------------- 1168 type = MethodType.methodType(int.class, 1169 new Class<?>[]{ 1170 String.class, Long.class, long.class, float.class, double.class}); 1171 delegate = MethodHandles.lookup().findStatic(MethodHandleCombinersTest.class, "spreadLong", type); 1172 1173 spreader = delegate.asSpreader(long[].class, 4); 1174 ret = (int) spreader.invokeExact("a", 1175 new long[]{0x1, 0x2, 0x3, 0x4}); 1176 assertEquals(49, ret); 1177 ret = (int) spreader.invoke("a", 1178 new long[]{0x1, 0x2, 0x3, 0x4}); 1179 assertEquals(49, ret); 1180 1181 // float[] 1182 // --------------------- 1183 type = MethodType.methodType(int.class, 1184 new Class<?>[]{ 1185 String.class, Float.class, float.class, double.class}); 1186 delegate = MethodHandles.lookup().findStatic(MethodHandleCombinersTest.class, "spreadFloat", type); 1187 1188 spreader = delegate.asSpreader(float[].class, 3); 1189 ret = (int) spreader.invokeExact("a", 1190 new float[]{1.0f, 2.0f, 3.0f}); 1191 assertEquals(50, ret); 1192 ret = (int) spreader.invokeExact("a", 1193 new float[]{1.0f, 2.0f, 3.0f}); 1194 assertEquals(50, ret); 1195 1196 // double[] 1197 // --------------------- 1198 type = MethodType.methodType(int.class, 1199 new Class<?>[]{String.class, Double.class, double.class}); 1200 delegate = MethodHandles.lookup().findStatic(MethodHandleCombinersTest.class, "spreadDouble", type); 1201 1202 spreader = delegate.asSpreader(double[].class, 2); 1203 ret = (int) spreader.invokeExact("a", new double[]{1.0, 2.0}); 1204 assertEquals(51, ret); 1205 ret = (int) spreader.invokeExact("a", new double[]{1.0, 2.0}); 1206 assertEquals(51, ret); 1207 } 1208 1209 public static void testInvokeWithArguments() throws Throwable { 1210 MethodType methodType = MethodType.methodType(int.class, 1211 new Class<?>[]{String.class, String.class, String.class}); 1212 MethodHandle handle = MethodHandles.lookup().findStatic( 1213 MethodHandleCombinersTest.class, "spreadReferences", methodType); 1214 1215 Object ret = handle.invokeWithArguments(new Object[]{"a", "b", "c"}); 1216 assertEquals(42, (int) ret); 1217 ret = handle.invokeWithArguments(new String[]{"a", "b", "c"}); 1218 assertEquals(42, (int) ret); 1219 1220 // Also test the versions that take a List<?> instead of an array. 1221 ret = handle.invokeWithArguments(Arrays.asList(new Object[] {"a", "b", "c"})); 1222 assertEquals(42, (int) ret); 1223 ret = handle.invokeWithArguments(Arrays.asList(new String[]{"a", "b", "c"})); 1224 assertEquals(42, (int) ret); 1225 1226 // Pass in an array that's too small. Should throw an IAE. 1227 try { 1228 handle.invokeWithArguments(new Object[]{"a", "b"}); 1229 fail(); 1230 } catch (IllegalArgumentException expected) { 1231 } catch (WrongMethodTypeException expected) { 1232 } 1233 1234 try { 1235 handle.invokeWithArguments(Arrays.asList(new Object[]{"a", "b"})); 1236 fail(); 1237 } catch (IllegalArgumentException expected) { 1238 } catch (WrongMethodTypeException expected) { 1239 } 1240 1241 1242 // Test implicit unboxing. 1243 MethodType methodType2 = MethodType.methodType(int.class, 1244 new Class<?>[]{String.class, int.class}); 1245 MethodHandle handle2 = MethodHandles.lookup().findStatic( 1246 MethodHandleCombinersTest.class, "spreadReferences_Unbox", methodType2); 1247 1248 ret = (int) handle2.invokeWithArguments(new Object[]{"a", 43}); 1249 assertEquals(43, (int) ret); 1250 } 1251 1252 public static int collectBoolean(String a, boolean[] b) { 1253 assertEquals("a", a); 1254 assertTrue(b[0]); 1255 assertFalse(b[1]); 1256 1257 return 44; 1258 } 1259 1260 public static int collectByte(String a, byte[] b) { 1261 assertEquals("a", a); 1262 assertEquals((byte) 1, b[0]); 1263 assertEquals((byte) 2, b[1]); 1264 return 45; 1265 } 1266 1267 public static int collectChar(String a, char[] b) { 1268 assertEquals("a", a); 1269 assertEquals('a', b[0]); 1270 assertEquals('b', b[1]); 1271 return 46; 1272 } 1273 1274 public static int collectShort(String a, short[] b) { 1275 assertEquals("a", a); 1276 assertEquals((short) 3, b[0]); 1277 assertEquals((short) 4, b[1]); 1278 1279 return 47; 1280 } 1281 1282 public static int collectInt(String a, int[] b) { 1283 assertEquals("a", a); 1284 assertEquals(42, b[0]); 1285 assertEquals(43, b[1]); 1286 1287 return 48; 1288 } 1289 1290 public static int collectLong(String a, long[] b) { 1291 assertEquals("a", a); 1292 assertEquals(100l, b[0]); 1293 assertEquals(99l, b[1]); 1294 1295 return 49; 1296 } 1297 1298 public static int collectFloat(String a, float[] b) { 1299 assertEquals("a", a); 1300 assertEquals(8.9f, b[0]); 1301 assertEquals(9.1f, b[1]); 1302 1303 return 50; 1304 } 1305 1306 public static int collectDouble(String a, double[] b) { 1307 assertEquals("a", a); 1308 assertEquals(6.7, b[0]); 1309 assertEquals(7.8, b[1]); 1310 1311 return 51; 1312 } 1313 1314 public static int collectCharSequence(String a, CharSequence[] b) { 1315 assertEquals("a", a); 1316 assertEquals("b", b[0]); 1317 assertEquals("c", b[1]); 1318 return 99; 1319 } 1320 1321 public static void testAsCollector() throws Throwable { 1322 // Reference arrays. 1323 // ------------------- 1324 MethodHandle trailingRef = MethodHandles.lookup().findStatic( 1325 MethodHandleCombinersTest.class, "collectCharSequence", 1326 MethodType.methodType(int.class, String.class, CharSequence[].class)); 1327 1328 // int[] is not convertible to CharSequence[].class. 1329 try { 1330 trailingRef.asCollector(int[].class, 1); 1331 fail(); 1332 } catch (IllegalArgumentException expected) { 1333 } 1334 1335 // Object[] is not convertible to CharSequence[].class. 1336 try { 1337 trailingRef.asCollector(Object[].class, 1); 1338 fail(); 1339 } catch (IllegalArgumentException expected) { 1340 } 1341 1342 // String[].class is convertible to CharSequence.class 1343 MethodHandle collector = trailingRef.asCollector(String[].class, 2); 1344 assertEquals(99, (int) collector.invoke("a", "b", "c")); 1345 1346 // Too few arguments should fail with a WMTE. 1347 try { 1348 collector.invoke("a", "b"); 1349 fail(); 1350 } catch (WrongMethodTypeException expected) { 1351 } 1352 1353 // Too many arguments should fail with a WMTE. 1354 try { 1355 collector.invoke("a", "b", "c", "d"); 1356 fail(); 1357 } catch (WrongMethodTypeException expected) { 1358 } 1359 1360 // Sanity checks on other array types. 1361 1362 MethodHandle target = MethodHandles.lookup().findStatic( 1363 MethodHandleCombinersTest.class, "collectBoolean", 1364 MethodType.methodType(int.class, String.class, boolean[].class)); 1365 assertEquals(44, (int) target.asCollector(boolean[].class, 2).invoke("a", true, false)); 1366 1367 target = MethodHandles.lookup().findStatic(MethodHandleCombinersTest.class, "collectByte", 1368 MethodType.methodType(int.class, String.class, byte[].class)); 1369 assertEquals(45, (int) target.asCollector(byte[].class, 2).invoke("a", (byte) 1, (byte) 2)); 1370 1371 target = MethodHandles.lookup().findStatic(MethodHandleCombinersTest.class, "collectChar", 1372 MethodType.methodType(int.class, String.class, char[].class)); 1373 assertEquals(46, (int) target.asCollector(char[].class, 2).invoke("a", 'a', 'b')); 1374 1375 target = MethodHandles.lookup().findStatic(MethodHandleCombinersTest.class, "collectShort", 1376 MethodType.methodType(int.class, String.class, short[].class)); 1377 assertEquals(47, (int) target.asCollector(short[].class, 2).invoke("a", (short) 3, (short) 4)); 1378 1379 target = MethodHandles.lookup().findStatic(MethodHandleCombinersTest.class, "collectInt", 1380 MethodType.methodType(int.class, String.class, int[].class)); 1381 assertEquals(48, (int) target.asCollector(int[].class, 2).invoke("a", 42, 43)); 1382 1383 target = MethodHandles.lookup().findStatic(MethodHandleCombinersTest.class, "collectLong", 1384 MethodType.methodType(int.class, String.class, long[].class)); 1385 assertEquals(49, (int) target.asCollector(long[].class, 2).invoke("a", 100, 99)); 1386 1387 target = MethodHandles.lookup().findStatic(MethodHandleCombinersTest.class, "collectFloat", 1388 MethodType.methodType(int.class, String.class, float[].class)); 1389 assertEquals(50, (int) target.asCollector(float[].class, 2).invoke("a", 8.9f, 9.1f)); 1390 1391 target = MethodHandles.lookup().findStatic(MethodHandleCombinersTest.class, "collectDouble", 1392 MethodType.methodType(int.class, String.class, double[].class)); 1393 assertEquals(51, (int) target.asCollector(double[].class, 2).invoke("a", 6.7, 7.8)); 1394 } 1395 1396 public static String filter1(char a) { 1397 return String.valueOf(a); 1398 } 1399 1400 public static char filter2(String b) { 1401 return b.charAt(0); 1402 } 1403 1404 public static String badFilter1(char a, char b) { 1405 return "bad"; 1406 } 1407 1408 public static int filterTarget(String a, char b, String c, char d) { 1409 assertEquals("a", a); 1410 assertEquals('b', b); 1411 assertEquals("c", c); 1412 assertEquals('d', d); 1413 return 56; 1414 } 1415 1416 public static void testFilterArguments() throws Throwable { 1417 MethodHandle filter1 = MethodHandles.lookup().findStatic( 1418 MethodHandleCombinersTest.class, "filter1", MethodType.methodType(String.class, char.class)); 1419 MethodHandle filter2 = MethodHandles.lookup().findStatic( 1420 MethodHandleCombinersTest.class, "filter2", MethodType.methodType(char.class, String.class)); 1421 1422 MethodHandle target = MethodHandles.lookup().findStatic( 1423 MethodHandleCombinersTest.class, "filterTarget", MethodType.methodType(int.class, 1424 String.class, char.class, String.class, char.class)); 1425 1426 // In all the cases below, the values printed will be 'a', 'b', 'c', 'd'. 1427 1428 // Filter arguments [0, 1] - all other arguments are passed through 1429 // as is. 1430 MethodHandle adapter = MethodHandles.filterArguments( 1431 target, 0, filter1, filter2); 1432 assertEquals(56, (int) adapter.invokeExact('a', "bXXXX", "c", 'd')); 1433 1434 // Filter arguments [1, 2]. 1435 adapter = MethodHandles.filterArguments(target, 1, filter2, filter1); 1436 assertEquals(56, (int) adapter.invokeExact("a", "bXXXX", 'c', 'd')); 1437 1438 // Filter arguments [2, 3]. 1439 adapter = MethodHandles.filterArguments(target, 2, filter1, filter2); 1440 assertEquals(56, (int) adapter.invokeExact("a", 'b', 'c', "dXXXXX")); 1441 1442 // Try out a few error cases : 1443 1444 // The return types of the filter doesn't align with the expected argument 1445 // type of the target. 1446 try { 1447 adapter = MethodHandles.filterArguments(target, 2, filter2, filter1); 1448 fail(); 1449 } catch (IllegalArgumentException expected) { 1450 } 1451 1452 // There are more filters than arguments. 1453 try { 1454 adapter = MethodHandles.filterArguments(target, 3, filter2, filter1); 1455 fail(); 1456 } catch (IllegalArgumentException expected) { 1457 } 1458 1459 // We pass in an obviously bogus position. 1460 try { 1461 adapter = MethodHandles.filterArguments(target, -1, filter2, filter1); 1462 fail(); 1463 } catch (ArrayIndexOutOfBoundsException expected) { 1464 } 1465 1466 // We pass in a function that has more than one argument. 1467 MethodHandle badFilter1 = MethodHandles.lookup().findStatic( 1468 MethodHandleCombinersTest.class, "badFilter1", 1469 MethodType.methodType(String.class, char.class, char.class)); 1470 1471 try { 1472 adapter = MethodHandles.filterArguments(target, 0, badFilter1, filter2); 1473 fail(); 1474 } catch (IllegalArgumentException expected) { 1475 } 1476 } 1477 1478 static void voidFilter(char a, char b) { 1479 } 1480 1481 static String filter(char a, char b) { 1482 return String.valueOf(a) + "+" + b; 1483 } 1484 1485 static char badFilter(char a, char b) { 1486 return 0; 1487 } 1488 1489 static String target(String a, String b, String c) { 1490 return ("a: " + a + ", b: " + b + ", c: " + c); 1491 } 1492 1493 public static void testCollectArguments() throws Throwable { 1494 // Test non-void filters. 1495 MethodHandle filter = MethodHandles.lookup().findStatic( 1496 MethodHandleCombinersTest.class, "filter", 1497 MethodType.methodType(String.class, char.class, char.class)); 1498 1499 MethodHandle target = MethodHandles.lookup().findStatic( 1500 MethodHandleCombinersTest.class, "target", 1501 MethodType.methodType(String.class, String.class, String.class, String.class)); 1502 1503 // Filter at position 0. 1504 MethodHandle adapter = MethodHandles.collectArguments(target, 0, filter); 1505 assertEquals("a: a+b, b: c, c: d", 1506 (String) adapter.invokeExact('a', 'b', "c", "d")); 1507 1508 // Filter at position 1. 1509 adapter = MethodHandles.collectArguments(target, 1, filter); 1510 assertEquals("a: a, b: b+c, c: d", 1511 (String) adapter.invokeExact("a", 'b', 'c', "d")); 1512 1513 // Filter at position 2. 1514 adapter = MethodHandles.collectArguments(target, 2, filter); 1515 assertEquals("a: a, b: b, c: c+d", 1516 (String) adapter.invokeExact("a", "b", 'c', 'd')); 1517 1518 // Test void filters. Note that we're passing in one more argument 1519 // than usual because the filter returns nothing - we have to invoke with 1520 // the full set of filter args and the full set of target args. 1521 filter = MethodHandles.lookup().findStatic(MethodHandleCombinersTest.class, "voidFilter", 1522 MethodType.methodType(void.class, char.class, char.class)); 1523 adapter = MethodHandles.collectArguments(target, 0, filter); 1524 assertEquals("a: a, b: b, c: c", 1525 (String) adapter.invokeExact('a', 'b', "a", "b", "c")); 1526 1527 adapter = MethodHandles.collectArguments(target, 1, filter); 1528 assertEquals("a: a, b: b, c: c", 1529 (String) adapter.invokeExact("a", 'a', 'b', "b", "c")); 1530 1531 // Test out a few failure cases. 1532 filter = MethodHandles.lookup().findStatic( 1533 MethodHandleCombinersTest.class, "filter", 1534 MethodType.methodType(String.class, char.class, char.class)); 1535 1536 // Bogus filter position. 1537 try { 1538 adapter = MethodHandles.collectArguments(target, 3, filter); 1539 fail(); 1540 } catch (IndexOutOfBoundsException expected) { 1541 } 1542 1543 // Mismatch in filter return type. 1544 filter = MethodHandles.lookup().findStatic( 1545 MethodHandleCombinersTest.class, "badFilter", 1546 MethodType.methodType(char.class, char.class, char.class)); 1547 try { 1548 adapter = MethodHandles.collectArguments(target, 0, filter); 1549 fail(); 1550 } catch (IllegalArgumentException expected) { 1551 } 1552 } 1553 1554 static int insertReceiver(String a, int b, Integer c, String d) { 1555 assertEquals("foo", a); 1556 assertEquals(56, b); 1557 assertEquals(Integer.valueOf(57), c); 1558 assertEquals("bar", d); 1559 1560 return 73; 1561 } 1562 1563 public static void testInsertArguments() throws Throwable { 1564 MethodHandle target = MethodHandles.lookup().findStatic( 1565 MethodHandleCombinersTest.class, "insertReceiver", 1566 MethodType.methodType(int.class, 1567 String.class, int.class, Integer.class, String.class)); 1568 1569 // Basic single element array inserted at position 0. 1570 MethodHandle adapter = MethodHandles.insertArguments( 1571 target, 0, new Object[]{"foo"}); 1572 assertEquals(73, (int) adapter.invokeExact(56, Integer.valueOf(57), "bar")); 1573 1574 // Exercise unboxing. 1575 adapter = MethodHandles.insertArguments( 1576 target, 1, new Object[]{Integer.valueOf(56), 57}); 1577 assertEquals(73, (int) adapter.invokeExact("foo", "bar")); 1578 1579 // Exercise a widening conversion. 1580 adapter = MethodHandles.insertArguments( 1581 target, 1, new Object[]{(short) 56, Integer.valueOf(57)}); 1582 assertEquals(73, (int) adapter.invokeExact("foo", "bar")); 1583 1584 // Insert an argument at the last position. 1585 adapter = MethodHandles.insertArguments( 1586 target, 3, new Object[]{"bar"}); 1587 assertEquals(73, (int) adapter.invokeExact("foo", 56, Integer.valueOf(57))); 1588 1589 // Exercise a few error cases. 1590 1591 // A reference type that can't be cast to another reference type. 1592 try { 1593 MethodHandles.insertArguments(target, 3, new Object[]{new Object()}); 1594 fail(); 1595 } catch (ClassCastException expected) { 1596 } 1597 1598 // A boxed type that can't be unboxed correctly. 1599 try { 1600 MethodHandles.insertArguments(target, 1, new Object[]{Long.valueOf(56)}); 1601 fail(); 1602 } catch (ClassCastException expected) { 1603 } 1604 } 1605 1606 public static String foldFilter(char a, char b) { 1607 return String.valueOf(a) + "+" + b; 1608 } 1609 1610 public static void voidFoldFilter(String e, char a, char b) { 1611 assertEquals("a", e); 1612 assertEquals('c', a); 1613 assertEquals('d', b); 1614 } 1615 1616 public static String foldTarget(String a, char b, char c, String d) { 1617 return ("a: " + a + " ,b:" + b + " ,c:" + c + " ,d:" + d); 1618 } 1619 1620 public static void mismatchedVoidFilter(Integer a) { 1621 } 1622 1623 public static Integer mismatchedNonVoidFilter(char a, char b) { 1624 return null; 1625 } 1626 1627 public static void testFoldArguments() throws Throwable { 1628 // Test non-void filters. 1629 MethodHandle filter = MethodHandles.lookup().findStatic( 1630 MethodHandleCombinersTest.class, "foldFilter", 1631 MethodType.methodType(String.class, char.class, char.class)); 1632 1633 MethodHandle target = MethodHandles.lookup().findStatic( 1634 MethodHandleCombinersTest.class, "foldTarget", 1635 MethodType.methodType(String.class, String.class, 1636 char.class, char.class, String.class)); 1637 1638 // Folder with a non-void type. 1639 MethodHandle adapter = MethodHandles.foldArguments(target, filter); 1640 assertEquals("a: c+d ,b:c ,c:d ,d:e", 1641 (String) adapter.invokeExact('c', 'd', "e")); 1642 1643 // Folder with a void type. 1644 filter = MethodHandles.lookup().findStatic( 1645 MethodHandleCombinersTest.class, "voidFoldFilter", 1646 MethodType.methodType(void.class, String.class, char.class, char.class)); 1647 adapter = MethodHandles.foldArguments(target, filter); 1648 assertEquals("a: a ,b:c ,c:d ,d:e", 1649 (String) adapter.invokeExact("a", 'c', 'd', "e")); 1650 1651 // Test a few erroneous cases. 1652 1653 filter = MethodHandles.lookup().findStatic( 1654 MethodHandleCombinersTest.class, "mismatchedVoidFilter", 1655 MethodType.methodType(void.class, Integer.class)); 1656 try { 1657 adapter = MethodHandles.foldArguments(target, filter); 1658 fail(); 1659 } catch (IllegalArgumentException expected) { 1660 } 1661 1662 filter = MethodHandles.lookup().findStatic( 1663 MethodHandleCombinersTest.class, "mismatchedNonVoidFilter", 1664 MethodType.methodType(Integer.class, char.class, char.class)); 1665 try { 1666 adapter = MethodHandles.foldArguments(target, filter); 1667 fail(); 1668 } catch (IllegalArgumentException expected) { 1669 } 1670 } 1671 1672 // An exception thrown on worker threads and re-thrown on the main thread. 1673 static Throwable workerException = null; 1674 1675 private static void invokeMultiThreaded(final MethodHandle mh) throws Throwable { 1676 // Create enough worker threads to be oversubscribed in bid to force some parallelism. 1677 final int threadCount = Runtime.getRuntime().availableProcessors() + 1; 1678 final Thread threads [] = new Thread [threadCount]; 1679 1680 // Launch worker threads and iterate invoking method handle. 1681 for (int i = 0; i < threadCount; ++i) { 1682 threads[i] = new Thread(new Runnable() { 1683 @Override 1684 public void run() { 1685 try { 1686 for (int j = 0; j < TEST_THREAD_ITERATIONS; ++j) { 1687 mh.invoke(); 1688 } 1689 } catch (Throwable t) { 1690 workerException = t; 1691 fail("Unexpected exception " + workerException); 1692 } 1693 }}); 1694 threads[i].start(); 1695 } 1696 1697 // Wait for completion 1698 for (int i = 0; i < threadCount; ++i) { 1699 threads[i].join(); 1700 } 1701 1702 // Fail on main thread to avoid test appearing to complete successfully. 1703 Throwable t = workerException; 1704 workerException = null; 1705 if (t != null) { 1706 throw t; 1707 } 1708 } 1709 1710 public static void testDropInsertArgumentsMultithreaded() throws Throwable { 1711 MethodHandle delegate = MethodHandles.lookup().findStatic(MethodHandleCombinersTest.class, 1712 "dropArguments_delegate", 1713 MethodType.methodType(void.class, new Class<?>[]{String.class, long.class})); 1714 MethodHandle mh = MethodHandles.dropArguments(delegate, 0, int.class, Object.class); 1715 mh = MethodHandles.insertArguments(mh, 0, 3333, "bogon", "foo", 42); 1716 invokeMultiThreaded(mh); 1717 } 1718 1719 private static void exceptionHandler_delegate(NumberFormatException e, int x, int y, long z) 1720 throws Throwable { 1721 assertEquals(e.getClass(), NumberFormatException.class); 1722 assertEquals(e.getMessage(), "fake"); 1723 assertEquals(x, 66); 1724 assertEquals(y, 51); 1725 assertEquals(z, 20000000000l); 1726 } 1727 1728 public static void testThrowCatchExceptionMultiThreaded() throws Throwable { 1729 MethodHandle thrower = MethodHandles.throwException(void.class, 1730 NumberFormatException.class); 1731 thrower = MethodHandles.dropArguments(thrower, 0, int.class, int.class, long.class); 1732 MethodHandle handler = MethodHandles.lookup().findStatic( 1733 MethodHandleCombinersTest.class, "exceptionHandler_delegate", 1734 MethodType.methodType(void.class, NumberFormatException.class, 1735 int.class, int.class, long.class)); 1736 MethodHandle catcher = 1737 MethodHandles.catchException(thrower, NumberFormatException.class, handler); 1738 MethodHandle caller = MethodHandles.insertArguments(catcher, 0, 66, 51, 20000000000l, 1739 new NumberFormatException("fake")); 1740 invokeMultiThreaded(caller); 1741 } 1742 1743 private static void testTargetAndFallback_delegate(MethodHandle mh) throws Throwable { 1744 String actual = (String) mh.invoke("target", 42, 56); 1745 assertEquals("target", actual); 1746 actual = (String) mh.invoke("blah", 41, 56); 1747 assertEquals("fallback", actual); 1748 } 1749 1750 public static void testGuardWithTestMultiThreaded() throws Throwable { 1751 MethodHandle test = 1752 MethodHandles.lookup().findStatic(MethodHandleCombinersTest.class, 1753 "testGuardWithTest_test", 1754 MethodType.methodType(boolean.class, 1755 new Class<?>[]{String.class, 1756 long.class})); 1757 final MethodType type = MethodType.methodType(String.class, 1758 new Class<?>[]{String.class, long.class, int.class}); 1759 final MethodHandle target = 1760 MethodHandles.lookup().findStatic(MethodHandleCombinersTest.class, 1761 "testGuardWithTest_target", type); 1762 final MethodHandle fallback = 1763 MethodHandles.lookup().findStatic(MethodHandleCombinersTest.class, 1764 "testGuardWithTest_fallback", type); 1765 MethodHandle adapter = MethodHandles.guardWithTest(test, target, fallback); 1766 MethodHandle tester = MethodHandles.lookup().findStatic( 1767 MethodHandleCombinersTest.class, 1768 "testTargetAndFallback_delegate", 1769 MethodType.methodType(void.class, MethodHandle.class)); 1770 invokeMultiThreaded(MethodHandles.insertArguments(tester, 0, adapter)); 1771 } 1772 1773 private static void arrayElementSetterGetter_delegate(MethodHandle getter, 1774 MethodHandle setter, 1775 int [] values) 1776 throws Throwable{ 1777 for (int i = 0; i < values.length; ++i) { 1778 int value = i * 13; 1779 setter.invoke(values, i, value); 1780 assertEquals(values[i], value); 1781 assertEquals(getter.invoke(values, i), values[i]); 1782 } 1783 } 1784 1785 public static void testReferenceArrayGetterMultiThreaded() throws Throwable { 1786 MethodHandle getter = MethodHandles.arrayElementGetter(int[].class); 1787 MethodHandle setter = MethodHandles.arrayElementSetter(int[].class); 1788 MethodHandle mh = MethodHandles.lookup().findStatic( 1789 MethodHandleCombinersTest.class, 1790 "arrayElementSetterGetter_delegate", 1791 MethodType.methodType(void.class, MethodHandle.class, MethodHandle.class, int[].class)); 1792 mh = MethodHandles.insertArguments(mh, 0, getter, setter, 1793 new int[] { 1, 2, 3, 5, 7, 11, 13, 17, 19, 23 }); 1794 invokeMultiThreaded(mh); 1795 } 1796 1797 private static void checkConstant_delegate(MethodHandle mh, double value) throws Throwable { 1798 assertEquals(mh.invoke(), value); 1799 } 1800 1801 public static void testConstantMultithreaded() throws Throwable { 1802 final double value = 7.77e77; 1803 MethodHandle constant = MethodHandles.constant(double.class, value); 1804 MethodHandle mh = MethodHandles.lookup().findStatic( 1805 MethodHandleCombinersTest.class, "checkConstant_delegate", 1806 MethodType.methodType(void.class, MethodHandle.class, double.class)); 1807 mh = MethodHandles.insertArguments(mh, 0, constant, value); 1808 invokeMultiThreaded(mh); 1809 } 1810 1811 private static void checkIdentity_delegate(MethodHandle mh, char value) throws Throwable { 1812 assertEquals(mh.invoke(value), value); 1813 } 1814 1815 public static void testIdentityMultiThreaded() throws Throwable { 1816 final char value = 'z'; 1817 MethodHandle identity = MethodHandles.identity(char.class); 1818 MethodHandle mh = MethodHandles.lookup().findStatic( 1819 MethodHandleCombinersTest.class, "checkIdentity_delegate", 1820 MethodType.methodType(void.class, MethodHandle.class, char.class)); 1821 mh = MethodHandles.insertArguments(mh, 0, identity, value); 1822 invokeMultiThreaded(mh); 1823 } 1824 1825 private static int multiplyByTwo(int x) { return x * 2; } 1826 private static int divideByTwo(int x) { return x / 2; } 1827 private static void assertMethodHandleInvokeEquals(MethodHandle mh, int value) throws Throwable{ 1828 assertEquals(mh.invoke(value), value); 1829 } 1830 1831 public static void testFilterReturnValueMultiThreaded() throws Throwable { 1832 MethodHandle target = MethodHandles.lookup().findStatic( 1833 MethodHandleCombinersTest.class, "multiplyByTwo", 1834 MethodType.methodType(int.class, int.class)); 1835 MethodHandle filter = MethodHandles.lookup().findStatic( 1836 MethodHandleCombinersTest.class, "divideByTwo", 1837 MethodType.methodType(int.class, int.class)); 1838 MethodHandle filtered = MethodHandles.filterReturnValue(target, filter); 1839 assertEquals(filtered.invoke(33), 33); 1840 MethodHandle mh = MethodHandles.lookup().findStatic( 1841 MethodHandleCombinersTest.class, "assertMethodHandleInvokeEquals", 1842 MethodType.methodType(void.class, MethodHandle.class, int.class)); 1843 invokeMultiThreaded(MethodHandles.insertArguments(mh, 0, filtered, 77)); 1844 } 1845 1846 public static void compareStringAndFloat(String s, float f) { 1847 assertEquals(s, Float.toString(f)); 1848 } 1849 1850 public static void testPermuteArgumentsMultiThreaded() throws Throwable { 1851 MethodHandle mh = MethodHandles.lookup().findStatic( 1852 MethodHandleCombinersTest.class, "compareStringAndFloat", 1853 MethodType.methodType(void.class, String.class, float.class)); 1854 mh = MethodHandles.permuteArguments( 1855 mh, MethodType.methodType(void.class, float.class, String.class), 1, 0); 1856 invokeMultiThreaded(MethodHandles.insertArguments(mh, 0, 2.22f, "2.22")); 1857 } 1858 1859 public static void testSpreadInvokerMultiThreaded() throws Throwable { 1860 MethodType methodType = MethodType.methodType( 1861 int.class, new Class<?>[]{String.class, String.class, String.class}); 1862 MethodHandle delegate = MethodHandles.lookup().findStatic( 1863 MethodHandleCombinersTest.class, "spreadReferences", methodType); 1864 MethodHandle mh = delegate.asSpreader(String[].class, 3); 1865 mh = MethodHandles.insertArguments(mh, 0, new Object[] { new String [] { "a", "b", "c" }}); 1866 invokeMultiThreaded(mh); 1867 } 1868 1869 public static void testCollectorMultiThreaded() throws Throwable { 1870 MethodHandle trailingRef = MethodHandles.lookup().findStatic( 1871 MethodHandleCombinersTest.class, "collectCharSequence", 1872 MethodType.methodType(int.class, String.class, CharSequence[].class)); 1873 MethodHandle mh = trailingRef.asCollector(String[].class, 2); 1874 mh = MethodHandles.insertArguments(mh, 0, "a", "b", "c"); 1875 invokeMultiThreaded(mh); 1876 } 1877 1878 public static void testFilterArgumentsMultiThreaded() throws Throwable { 1879 MethodHandle filter1 = MethodHandles.lookup().findStatic( 1880 MethodHandleCombinersTest.class, "filter1", 1881 MethodType.methodType(String.class, char.class)); 1882 MethodHandle filter2 = MethodHandles.lookup().findStatic( 1883 MethodHandleCombinersTest.class, "filter2", 1884 MethodType.methodType(char.class, String.class)); 1885 MethodHandle target = MethodHandles.lookup().findStatic( 1886 MethodHandleCombinersTest.class, "filterTarget", 1887 MethodType.methodType(int.class, String.class, char.class, String.class, char.class)); 1888 MethodHandle adapter = MethodHandles.filterArguments(target, 2, filter1, filter2); 1889 invokeMultiThreaded(MethodHandles.insertArguments(adapter, 0, "a", 'b', 'c', "dXXXXX")); 1890 } 1891 1892 private static void checkStringResult_delegate(MethodHandle mh, 1893 String expected) throws Throwable { 1894 assertEquals(mh.invoke(), expected); 1895 } 1896 1897 public static void testCollectArgumentsMultiThreaded() throws Throwable { 1898 MethodHandle filter = MethodHandles.lookup().findStatic( 1899 MethodHandleCombinersTest.class, "filter", 1900 MethodType.methodType(String.class, char.class, char.class)); 1901 MethodHandle target = MethodHandles.lookup().findStatic( 1902 MethodHandleCombinersTest.class, "target", 1903 MethodType.methodType(String.class, String.class, String.class, String.class)); 1904 MethodHandle collect = MethodHandles.collectArguments(target, 2, filter); 1905 collect = MethodHandles.insertArguments(collect, 0, "a", "b", 'c', 'd'); 1906 MethodHandle mh = MethodHandles.lookup().findStatic( 1907 MethodHandleCombinersTest.class, "checkStringResult_delegate", 1908 MethodType.methodType(void.class, MethodHandle.class, String.class)); 1909 invokeMultiThreaded(MethodHandles.insertArguments(mh, 0, collect, "a: a, b: b, c: c+d")); 1910 } 1911 1912 public static void testFoldArgumentsMultiThreaded() throws Throwable { 1913 MethodHandle target = MethodHandles.lookup().findStatic( 1914 MethodHandleCombinersTest.class, "foldTarget", 1915 MethodType.methodType(String.class, String.class, 1916 char.class, char.class, String.class)); 1917 MethodHandle filter = MethodHandles.lookup().findStatic( 1918 MethodHandleCombinersTest.class, "foldFilter", 1919 MethodType.methodType(String.class, char.class, char.class)); 1920 MethodHandle adapter = MethodHandles.foldArguments(target, filter); 1921 adapter = MethodHandles.insertArguments(adapter, 0, 'c', 'd', "e"); 1922 MethodHandle mh = MethodHandles.lookup().findStatic( 1923 MethodHandleCombinersTest.class, "checkStringResult_delegate", 1924 MethodType.methodType(void.class, MethodHandle.class, String.class)); 1925 invokeMultiThreaded(MethodHandles.insertArguments(mh, 0, adapter, "a: c+d ,b:c ,c:d ,d:e")); 1926 } 1927 1928 private static void checkBooleanCast_delegate(boolean expected, boolean z, boolean b, 1929 boolean c, boolean s, boolean i, boolean j, 1930 boolean f, boolean d, boolean l) { 1931 assertEquals(expected, z); 1932 assertEquals(expected, b); 1933 assertEquals(expected, c); 1934 assertEquals(expected, s); 1935 assertEquals(expected, i); 1936 assertEquals(expected, j); 1937 assertEquals(expected, f); 1938 assertEquals(expected, d); 1939 assertEquals(expected, l); 1940 } 1941 1942 private static void checkByteCast_delegate(byte expected, byte z, byte b, byte c, byte s, 1943 byte i, byte j, byte f, byte d, byte l) { 1944 int mask = 0xff; 1945 assertEquals(expected & 1, z); 1946 assertEquals(expected, b); 1947 assertEquals(expected, c & mask); 1948 assertEquals(expected, s & mask); 1949 assertEquals(expected, i & mask); 1950 assertEquals(expected, j & mask); 1951 assertEquals(expected, f & mask); 1952 assertEquals(expected, d & mask); 1953 assertEquals(expected, l); 1954 } 1955 1956 private static void checkCharCast_delegate(char expected, char z, char b, char c, char s, 1957 char i, char j, char f, char d, char l) { 1958 int mask = 0xffff; 1959 assertEquals(expected & 1, z); 1960 assertEquals(expected & 0xff, b); 1961 assertEquals(expected, c); 1962 assertEquals(expected, s & mask); 1963 assertEquals(expected, i & mask); 1964 assertEquals(expected, j & mask); 1965 assertEquals(expected, f & mask); 1966 assertEquals(expected, d & mask); 1967 assertEquals(expected, l); 1968 } 1969 1970 private static void checkShortCast_delegate(short expected, short z, short b, short c, short s, 1971 short i, short j, short f, short d, short l) { 1972 int mask = 0xffff; 1973 assertEquals(expected & 1, z); 1974 assertEquals(expected & 0xff, b); 1975 assertEquals(expected, c & mask); 1976 assertEquals(expected, s); 1977 assertEquals(expected, i & mask); 1978 assertEquals(expected, j & mask); 1979 assertEquals(expected, f & mask); 1980 assertEquals(expected, d & mask); 1981 assertEquals(expected, l); 1982 } 1983 1984 private static void checkIntCast_delegate(int expected, int z, int b, int c, int s, int i, 1985 int j, int f, int d, int l) { 1986 int mask = 0xffffffff; 1987 assertEquals(expected & 1, z); 1988 assertEquals(expected & 0xff, b); 1989 assertEquals(expected & 0xffff, c); 1990 assertEquals(expected & 0xffff, s); 1991 assertEquals(expected, i & mask); 1992 assertEquals(expected, j & mask); 1993 assertEquals(expected, f & mask); 1994 assertEquals(expected, d & mask); 1995 assertEquals(expected, l); 1996 } 1997 1998 private static void checkLongCast_delegate(long expected, long z, long b, long c, long s, 1999 long i, long j, long f, long d, long l) { 2000 long mask = 0xffffffffl; 2001 assertEquals(expected & 1, z); 2002 assertEquals(expected & 0xff, b); 2003 assertEquals(expected & 0xffff, c); 2004 assertEquals(expected & 0xffff, s); 2005 assertEquals(expected & mask, i & mask); 2006 assertEquals(expected, j); 2007 assertEquals(expected & mask, f & mask); 2008 assertEquals(expected, d); 2009 assertEquals(expected, l); 2010 } 2011 2012 private static void checkFloatCast_delegate(float expected, float z, float b, float c, float s, 2013 float i, float j, float f, float d, float l) { 2014 assertEquals((byte) expected & 1, (int) z); 2015 assertEquals((byte) expected, (int) b & 0xff); 2016 assertEquals((char) expected & 0xffff, (int) c& 0xffff); 2017 assertEquals((short) expected & 0xffff, (int) s & 0xffff); 2018 assertEquals((int) expected, (int) i); 2019 assertEquals((long) expected, (long) j); 2020 assertEquals(expected, f); 2021 assertEquals(expected, d); 2022 assertEquals(expected, l); 2023 } 2024 2025 private static void checkDoubleCast_delegate(double expected, double z, double b, double c, 2026 double s, double i, double j, double f, double d, 2027 double l) { 2028 assertEquals((byte) expected & 1, (int) z); 2029 assertEquals((byte) expected & 0xff, (int) b & 0xff); 2030 assertEquals((int) expected & 0xffff, (int) c & 0xffff); 2031 assertEquals((int) expected & 0xffff, (int) s & 0xffff); 2032 assertEquals((int) expected, (int) i); 2033 assertEquals((long) expected, (long) j); 2034 assertEquals((float) expected, (float) f); 2035 assertEquals(expected, d); 2036 assertEquals(expected, l); 2037 } 2038 2039 private static void checkBoxingCasts_delegate(boolean expected, Boolean z, Byte b, Character c, 2040 Short s, Integer i, Long j, Float f, Double d) { 2041 int v = expected ? 1 : 0; 2042 assertEquals(Boolean.valueOf(expected ? true : false), z); 2043 assertEquals(Byte.valueOf((byte) v), b); 2044 assertEquals(Character.valueOf((char) v), c); 2045 assertEquals(Short.valueOf((short) v), s); 2046 assertEquals(Integer.valueOf(v), i); 2047 assertEquals(Long.valueOf(v), j); 2048 assertEquals(Float.valueOf(v), f); 2049 assertEquals(Double.valueOf(v), d); 2050 } 2051 2052 public static void testExplicitCastArguments() throws Throwable { 2053 MethodHandle target = MethodHandles.lookup().findStatic( 2054 MethodHandleCombinersTest.class, "checkBooleanCast_delegate", 2055 MethodType.methodType(void.class, boolean.class, boolean.class, boolean.class, 2056 boolean.class, boolean.class, boolean.class, boolean.class, 2057 boolean.class, boolean.class, boolean.class)); 2058 MethodHandle mh = MethodHandles.explicitCastArguments( 2059 target, MethodType.methodType(void.class, boolean.class, boolean.class, byte.class, 2060 char.class, short.class, int.class, long.class, 2061 float.class, double.class, Boolean.class)); 2062 mh.invokeExact(false, false, (byte) 0, (char) 0, (short) 0, 0, 0l, 0.0f, 0.0, 2063 Boolean.valueOf(false)); 2064 mh.invokeExact(false, false, (byte) 2, (char) 2, (short) 2, 2, 2l, 2.2f, 2.2, 2065 Boolean.valueOf(false)); 2066 mh.invokeExact(true, true, (byte) 1, (char) 1, (short) 1, 1, 1l, 1.0f, 1.0, 2067 Boolean.valueOf(true)); 2068 mh.invokeExact(true, true, (byte) 51, (char) 51, (short) 51, 51, 51l, 51.0f, 51.0, 2069 Boolean.valueOf(true)); 2070 MethodHandles.explicitCastArguments( 2071 target, MethodType.methodType(void.class, boolean.class, boolean.class, byte.class, 2072 char.class, short.class, int.class, long.class, 2073 float.class, double.class, String.class)); 2074 try { 2075 mh.invoke(true, true, (byte) 51, (char) 51, (short) 51, 51, 51l, 51.0f, 51.0, 2076 "ClassCastException here!"); 2077 fail(); 2078 } catch (ClassCastException e) { 2079 } 2080 2081 target = MethodHandles.lookup().findStatic( 2082 MethodHandleCombinersTest.class, "checkByteCast_delegate", 2083 MethodType.methodType(void.class, byte.class, byte.class, byte.class, 2084 byte.class, byte.class, byte.class, byte.class, 2085 byte.class, byte.class, byte.class)); 2086 mh = MethodHandles.explicitCastArguments( 2087 target, MethodType.methodType(void.class, byte.class, boolean.class, byte.class, 2088 char.class, short.class, int.class, long.class, 2089 float.class, double.class, Byte.class)); 2090 mh.invokeExact((byte) 0x5a, false, (byte) 0x5a, (char) 0x5a5a, (short) 0x5a5a, (int) 0x5a5a, 2091 (long) 0x5a5a, (float) 0x5a5a, (double) 0x5a5a, Byte.valueOf((byte) 0x5a)); 2092 try { 2093 mh.invoke((byte) 0x5a, false, (byte) 0x5a, (char) 0x5a5a, (short) 0x5a5a, (int) 0x5a5a, 2094 (long) 0x5a5a, (float) 0x5a5a, (double) 0x5a5a, 2095 Short.valueOf((short) 0x5a5a)); 2096 fail(); 2097 } catch (ClassCastException e) { 2098 } 2099 2100 target = MethodHandles.lookup().findStatic( 2101 MethodHandleCombinersTest.class, "checkCharCast_delegate", 2102 MethodType.methodType(void.class, char.class, char.class, char.class, 2103 char.class, char.class, char.class, char.class, 2104 char.class, char.class, char.class)); 2105 mh = MethodHandles.explicitCastArguments( 2106 target, MethodType.methodType(void.class, char.class, boolean.class, byte.class, 2107 char.class, short.class, int.class, long.class, 2108 float.class, double.class, Character.class)); 2109 mh.invokeExact((char) 0x5555, true, (byte) 0x5555, (char) 0x5555, (short) 0x5555, 2110 (int) 0x5555, (long) 0x5555, (float) 0x5555, (double) 0x5555, 2111 Character.valueOf((char) 0x5555)); 2112 try { 2113 mh.invoke((char) 0x5555, false, (byte) 0x5555, (char) 0x5555, (short) 0x5555, 2114 (int) 0x5555, (long) 0x5555, (float) 0x5555, (double) 0x5555, 2115 Integer.valueOf((int) 0x5555)); 2116 fail(); 2117 } catch (ClassCastException e) { 2118 } 2119 2120 target = MethodHandles.lookup().findStatic( 2121 MethodHandleCombinersTest.class, "checkShortCast_delegate", 2122 MethodType.methodType(void.class, short.class, short.class, short.class, 2123 short.class, short.class, short.class, short.class, 2124 short.class, short.class, short.class)); 2125 mh = MethodHandles.explicitCastArguments( 2126 target, MethodType.methodType(void.class, short.class, boolean.class, byte.class, 2127 char.class, short.class, int.class, long.class, 2128 float.class, double.class, Short.class)); 2129 mh.invokeExact((short) 0x3773, true, (byte) 0x3773, (char) 0x3773, (short) 0x3773, 2130 (int) 0x3773, (long) 0x3773, (float) 0x3773, (double) 0x3773, 2131 Short.valueOf((short) 0x3773)); 2132 try { 2133 mh.invoke((short) 0x3773, true, (byte) 0x3773, (char) 0x3773, (short) 0x3773, 2134 (int) 0x3773, (long) 0x3773, (float) 0x3773, (double) 0x3773, 2135 Long.valueOf((long) 0x3773)); 2136 fail(); 2137 } catch (ClassCastException e) { 2138 } 2139 2140 target = MethodHandles.lookup().findStatic( 2141 MethodHandleCombinersTest.class, "checkIntCast_delegate", 2142 MethodType.methodType(void.class, int.class, int.class, int.class, 2143 int.class, int.class, int.class, int.class, 2144 int.class, int.class, int.class)); 2145 mh = MethodHandles.explicitCastArguments( 2146 target, MethodType.methodType(void.class, int.class, boolean.class, byte.class, 2147 char.class, short.class, int.class, long.class, 2148 float.class, double.class, Integer.class)); 2149 mh.invokeExact((int) 0x3773470, false, (byte) 0x3773470, (char) 0x3773470, 2150 (short) 0x3773470, (int) 0x3773470, (long) 0x3773470, (float) 0x3773470, 2151 (double) 0x3773470, Integer.valueOf(0x3773470)); 2152 try { 2153 mh.invoke((int) 0x3773470, false, (byte) 0x3773470, (char) 0x3773470, 2154 (short) 0x3773470, (int) 0x3773470, (long) 0x3773470, (float) 0x3773470, 2155 (double) 0x3773470, Long.valueOf((long) 0x3773470)); 2156 fail(); 2157 } catch (ClassCastException e) { 2158 } 2159 2160 target = MethodHandles.lookup().findStatic( 2161 MethodHandleCombinersTest.class, "checkLongCast_delegate", 2162 MethodType.methodType(void.class, long.class, long.class, long.class, 2163 long.class, long.class, long.class, long.class, 2164 long.class, long.class, long.class)); 2165 mh = MethodHandles.explicitCastArguments( 2166 target, MethodType.methodType(void.class, long.class, boolean.class, byte.class, 2167 char.class, short.class, int.class, long.class, 2168 float.class, double.class, Long.class)); 2169 long longValue = 0x770000000l; 2170 mh.invokeExact((long) longValue, false, (byte) longValue, (char) longValue, 2171 (short) longValue, (int) longValue, (long) longValue, (float) longValue, 2172 (double) longValue, Long.valueOf(longValue)); 2173 try { 2174 mh.invoke((long) longValue, false, (byte) longValue, (char) longValue, 2175 (short) longValue, (int) longValue, (long) longValue, (float) longValue, 2176 (double) longValue, Integer.valueOf(3)); 2177 fail(); 2178 } catch (ClassCastException e) { 2179 } 2180 2181 target = MethodHandles.lookup().findStatic( 2182 MethodHandleCombinersTest.class, "checkFloatCast_delegate", 2183 MethodType.methodType(void.class, float.class, float.class, float.class, 2184 float.class, float.class, float.class, float.class, 2185 float.class, float.class, float.class)); 2186 mh = MethodHandles.explicitCastArguments( 2187 target, MethodType.methodType(void.class, float.class, boolean.class, byte.class, 2188 char.class, short.class, int.class, long.class, 2189 float.class, double.class, Float.class)); 2190 float floatValue = 33333.141f; 2191 mh.invokeExact(floatValue, true, (byte) floatValue, (char) floatValue, (short) floatValue, 2192 (int) floatValue, (long) floatValue, floatValue, (double) floatValue, 2193 Float.valueOf(floatValue)); 2194 try { 2195 mh.invoke(floatValue, true, (byte) floatValue, (char) floatValue, 2196 (short) floatValue, (int) floatValue, (long) floatValue, floatValue, 2197 (double) floatValue, Integer.valueOf((int) floatValue)); 2198 fail(); 2199 } catch (ClassCastException e) { 2200 } 2201 2202 target = MethodHandles.lookup().findStatic( 2203 MethodHandleCombinersTest.class, "checkDoubleCast_delegate", 2204 MethodType.methodType(void.class, double.class, double.class, double.class, 2205 double.class, double.class, double.class, double.class, 2206 double.class, double.class, double.class)); 2207 mh = MethodHandles.explicitCastArguments( 2208 target, MethodType.methodType(void.class, double.class, boolean.class, byte.class, 2209 char.class, short.class, int.class, long.class, 2210 float.class, double.class, Double.class)); 2211 double doubleValue = 33333333333.141; 2212 mh.invokeExact(doubleValue, true, (byte) doubleValue, (char) doubleValue, 2213 (short) doubleValue, (int) doubleValue, (long) doubleValue, 2214 (float) doubleValue, doubleValue, Double.valueOf(doubleValue)); 2215 try { 2216 mh.invoke(doubleValue, true, (byte) doubleValue, (char) doubleValue, 2217 (short) doubleValue, (int) doubleValue, (long) doubleValue, 2218 (float) doubleValue, (double) doubleValue, 2219 Integer.valueOf((int) doubleValue)); 2220 fail(); 2221 } catch (ClassCastException e) { 2222 } 2223 2224 target = MethodHandles.lookup().findStatic( 2225 MethodHandleCombinersTest.class, "checkBoxingCasts_delegate", 2226 MethodType.methodType(void.class, boolean.class, Boolean.class, Byte.class, 2227 Character.class, Short.class, Integer.class, Long.class, 2228 Float.class, Double.class)); 2229 mh = MethodHandles.explicitCastArguments( 2230 target, MethodType.methodType(void.class, boolean.class, boolean.class, byte.class, 2231 char.class, short.class, int.class, long.class, 2232 float.class, double.class)); 2233 mh.invokeExact(false, false, (byte) 0, (char) 0, (short) 0, 0, 0l, 0.0f, 0.0); 2234 mh.invokeExact(true, true, (byte) 1, (char) 1, (short) 1, 1, 1l, 1.0f, 1.0); 2235 mh.invoke(Boolean.valueOf(false), Boolean.valueOf(false), Byte.valueOf((byte) 0), 2236 Character.valueOf((char) 0), Short.valueOf((short) 0), Integer.valueOf(0), 2237 Long.valueOf(0l), Float.valueOf(0.0f), Double.valueOf(0.0)); 2238 mh.invoke(Boolean.valueOf(true), Boolean.valueOf(true), Byte.valueOf((byte) 1), 2239 Character.valueOf((char) 1), Short.valueOf((short) 1), Integer.valueOf(1), 2240 Long.valueOf(1l), Float.valueOf(1.0f), Double.valueOf(1.0)); 2241 mh = MethodHandles.explicitCastArguments( 2242 target, MethodType.methodType(void.class, double.class, boolean.class, byte.class, 2243 char.class, short.class, int.class, long.class, 2244 float.class, double.class)); 2245 mh.invokeExact(0.0, false, (byte) 0, (char) 0, (short) 0, 0, 0l, 0.0f, 0.0); 2246 } 2247 2248 static void returnVoid() {} 2249 2250 static boolean returnBoolean(boolean b) { return b; } 2251 2252 static Boolean returnBooleanObject(boolean b) { return b; } 2253 2254 public static void testExplicitCastReturnValues() throws Throwable { 2255 MethodHandle target = MethodHandles.lookup().findStatic( 2256 MethodHandleCombinersTest.class, "returnVoid", MethodType.methodType(void.class)); 2257 assertEquals(false, 2258 MethodHandles 2259 .explicitCastArguments(target, MethodType.methodType(boolean.class)) 2260 .invoke()); 2261 assertEquals(null, 2262 MethodHandles 2263 .explicitCastArguments(target, MethodType.methodType(Boolean.class)) 2264 .invoke()); 2265 assertEquals(0l, 2266 MethodHandles 2267 .explicitCastArguments(target, MethodType.methodType(long.class)) 2268 .invoke()); 2269 assertEquals(null, 2270 MethodHandles 2271 .explicitCastArguments(target, MethodType.methodType(Long.class)) 2272 .invoke()); 2273 2274 target = MethodHandles.lookup().findStatic( 2275 MethodHandleCombinersTest.class, "returnBoolean", 2276 MethodType.methodType(boolean.class, boolean.class)); 2277 assertEquals(false, 2278 MethodHandles 2279 .explicitCastArguments(target, 2280 MethodType.methodType(boolean.class, boolean.class)) 2281 .invoke(false)); 2282 assertEquals(true, 2283 MethodHandles 2284 .explicitCastArguments(target, 2285 MethodType.methodType(boolean.class, boolean.class)) 2286 .invoke(true)); 2287 assertEquals(Boolean.valueOf(false), 2288 MethodHandles 2289 .explicitCastArguments(target, 2290 MethodType.methodType(Boolean.class, boolean.class)) 2291 .invoke(false)); 2292 assertEquals(Boolean.valueOf(true), 2293 MethodHandles 2294 .explicitCastArguments(target, 2295 MethodType.methodType(Boolean.class, boolean.class)) 2296 .invoke(true)); 2297 assertEquals((byte) 0, 2298 MethodHandles 2299 .explicitCastArguments(target, 2300 MethodType.methodType(byte.class, boolean.class)) 2301 .invoke(false)); 2302 assertEquals((byte) 1, 2303 MethodHandles 2304 .explicitCastArguments(target, 2305 MethodType.methodType(byte.class, boolean.class)) 2306 .invoke(true)); 2307 try { 2308 assertEquals(Byte.valueOf((byte) 0), 2309 MethodHandles 2310 .explicitCastArguments(target, 2311 MethodType.methodType(Byte.class, boolean.class)) 2312 .invoke(false)); 2313 fail(); 2314 } catch (ClassCastException e) { 2315 } 2316 2317 try { 2318 assertEquals(Byte.valueOf((byte) 1), 2319 MethodHandles 2320 .explicitCastArguments(target, 2321 MethodType.methodType(Byte.class, boolean.class)) 2322 .invoke(true)); 2323 } catch (ClassCastException e) { 2324 } 2325 2326 target = MethodHandles.lookup().findStatic( 2327 MethodHandleCombinersTest.class, "returnBooleanObject", 2328 MethodType.methodType(Boolean.class, boolean.class)); 2329 assertEquals(false, 2330 (boolean) MethodHandles 2331 .explicitCastArguments(target, 2332 MethodType.methodType(boolean.class, boolean.class)) 2333 .invokeExact(false)); 2334 assertEquals(true, 2335 (boolean) MethodHandles 2336 .explicitCastArguments(target, 2337 MethodType.methodType(boolean.class, boolean.class)) 2338 .invokeExact(true)); 2339 } 2340} 2341