1 /* 2 * Copyright (C) 2016 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 17 package libcore.java.lang.invoke; 18 19 import junit.framework.TestCase; 20 21 import java.lang.invoke.MethodHandle; 22 import java.lang.invoke.MethodHandleInfo; 23 import java.lang.invoke.MethodHandles; 24 import java.lang.invoke.MethodHandles.Lookup; 25 import java.lang.invoke.MethodType; 26 import java.lang.invoke.WrongMethodTypeException; 27 import java.lang.reflect.Constructor; 28 import java.lang.reflect.Field; 29 import java.lang.reflect.Method; 30 import java.nio.charset.Charset; 31 import java.nio.charset.StandardCharsets; 32 import java.util.ArrayList; 33 import java.util.Arrays; 34 import java.util.List; 35 import java.util.Vector; 36 37 import static java.lang.invoke.MethodHandles.Lookup.*; 38 39 public class MethodHandlesTest extends TestCase { 40 private static final int ALL_LOOKUP_MODES = (PUBLIC | PRIVATE | PACKAGE | PROTECTED); 41 42 public void test_publicLookupClassAndModes() { 43 MethodHandles.Lookup publicLookup = MethodHandles.publicLookup(); 44 assertSame(Object.class, publicLookup.lookupClass()); 45 assertEquals(PUBLIC, publicLookup.lookupModes()); 46 } 47 48 public void test_defaultLookupClassAndModes() { 49 MethodHandles.Lookup defaultLookup = MethodHandles.lookup(); 50 assertSame(MethodHandlesTest.class, defaultLookup.lookupClass()); 51 assertEquals(ALL_LOOKUP_MODES, defaultLookup.lookupModes()); 52 } 53 54 public void test_LookupIn() { 55 MethodHandles.Lookup defaultLookup = MethodHandles.lookup(); 56 57 // A class in the same package loses the privilege to lookup protected and private 58 // members. 59 MethodHandles.Lookup siblingLookup = defaultLookup.in(PackageSibling.class); 60 assertEquals(ALL_LOOKUP_MODES & ~(PROTECTED | PRIVATE), siblingLookup.lookupModes()); 61 62 // The new lookup isn't in the same package, so it loses all its privileges except 63 // for public. 64 MethodHandles.Lookup nonSibling = defaultLookup.in(Vector.class); 65 assertEquals(PUBLIC, nonSibling.lookupModes()); 66 67 // Special case, sibling inner classes in the same parent class 68 MethodHandles.Lookup inner2 = Inner1.lookup.in(Inner2.class); 69 assertEquals(PUBLIC | PRIVATE | PACKAGE, inner2.lookupModes()); 70 71 try { 72 MethodHandles.lookup().in(null); 73 fail(); 74 } catch (NullPointerException expected) { 75 } 76 77 // Callers cannot change the lookup context to anything within the java.lang.invoke package. 78 try { 79 MethodHandles.lookup().in(MethodHandle.class); 80 fail(); 81 } catch (IllegalArgumentException expected) { 82 } 83 } 84 85 public void test_findStatic() throws Exception { 86 MethodHandles.Lookup defaultLookup = MethodHandles.lookup(); 87 88 // Handle for String String#valueOf(char[]). 89 MethodHandle handle = defaultLookup.findStatic(String.class, "valueOf", 90 MethodType.methodType(String.class, char[].class)); 91 assertNotNull(handle); 92 93 assertEquals(String.class, handle.type().returnType()); 94 assertEquals(1, handle.type().parameterCount()); 95 assertEquals(char[].class, handle.type().parameterArray()[0]); 96 assertEquals(MethodHandle.INVOKE_STATIC, handle.getHandleKind()); 97 98 MethodHandles.Lookup inUtil = defaultLookup.in(Vector.class); 99 100 // Package private in a public class in a different package from the lookup. 101 try { 102 inUtil.findStatic(MethodHandlesTest.class, "packagePrivateStaticMethod", 103 MethodType.methodType(void.class)); 104 fail(); 105 } catch (IllegalAccessException expected) { 106 } 107 108 // Protected in a public class in a different package from the lookup. 109 try { 110 inUtil.findStatic(MethodHandlesTest.class, "protectedStaticMethod", 111 MethodType.methodType(void.class)); 112 fail(); 113 } catch (IllegalAccessException expected) { 114 } 115 116 // Private in a public class in a different package from the lookup. 117 try { 118 inUtil.findStatic(MethodHandlesTest.class, "privateStaticMethod", 119 MethodType.methodType(void.class)); 120 fail(); 121 } catch (IllegalAccessException expected) { 122 } 123 124 // Public method in a package private class in a different package from the lookup. 125 try { 126 inUtil.findStatic(PackageSibling.class, "publicStaticMethod", 127 MethodType.methodType(void.class)); 128 fail(); 129 } catch (IllegalAccessException expected) { 130 } 131 132 // Public virtual method should not discoverable via findStatic. 133 try { 134 inUtil.findStatic(MethodHandlesTest.class, "publicMethod", 135 MethodType.methodType(void.class)); 136 fail(); 137 } catch (IllegalAccessException expected) { 138 } 139 } 140 141 public void test_findConstructor() throws Exception { 142 MethodHandles.Lookup defaultLookup = MethodHandles.lookup(); 143 144 // Handle for String.<init>(String). The requested type of the constructor declares 145 // a void return type (to match the bytecode) but the handle that's created will declare 146 // a return type that's equal to the type being constructed. 147 MethodHandle handle = defaultLookup.findConstructor(String.class, 148 MethodType.methodType(void.class, String.class)); 149 assertNotNull(handle); 150 151 assertEquals(String.class, handle.type().returnType()); 152 assertEquals(1, handle.type().parameterCount()); 153 154 assertEquals(String.class, handle.type().parameterArray()[0]); 155 assertEquals(MethodHandle.INVOKE_DIRECT, handle.getHandleKind()); 156 157 MethodHandles.Lookup inUtil = defaultLookup.in(Vector.class); 158 159 // Package private in a public class in a different package from the lookup. 160 try { 161 inUtil.findConstructor(ConstructorTest.class, 162 MethodType.methodType(void.class, String.class, int.class)); 163 fail(); 164 } catch (IllegalAccessException expected) { 165 } 166 167 // Protected in a public class in a different package from the lookup. 168 try { 169 inUtil.findConstructor(ConstructorTest.class, 170 MethodType.methodType(void.class, String.class)); 171 fail(); 172 } catch (IllegalAccessException expected) { 173 } 174 175 // Private in a public class in a different package from the lookup. 176 try { 177 inUtil.findConstructor(ConstructorTest.class, 178 MethodType.methodType(void.class, String.class, char.class)); 179 fail(); 180 } catch (IllegalAccessException expected) { 181 } 182 183 // Protected constructor in a package private class in a different package from the lookup. 184 try { 185 inUtil.findConstructor(PackageSibling.class, 186 MethodType.methodType(void.class, String.class)); 187 fail(); 188 } catch (IllegalAccessException expected) { 189 } 190 191 // Public constructor in a package private class in a different package from the lookup. 192 try { 193 inUtil.findConstructor(PackageSibling.class, 194 MethodType.methodType(void.class, String.class, char.class)); 195 fail(); 196 } catch (IllegalAccessException expected) { 197 } 198 } 199 200 public void test_findVirtual() throws Exception { 201 MethodHandles.Lookup defaultLookup = MethodHandles.lookup(); 202 203 // String.replaceAll(String, String); 204 MethodHandle handle = defaultLookup.findVirtual(String.class, "replaceAll", 205 MethodType.methodType(String.class, String.class, String.class)); 206 assertNotNull(handle); 207 208 assertEquals(String.class, handle.type().returnType()); 209 // Note that the input type was (String,String)String but the handle's type is 210 // (String, String, String)String - since it's a non static call, we prepend the 211 // receiver to the type. 212 assertEquals(3, handle.type().parameterCount()); 213 MethodType expectedType = MethodType.methodType(String.class, 214 new Class<?>[] { String.class, String.class, String.class}); 215 216 assertEquals(expectedType, handle.type()); 217 assertEquals(MethodHandle.INVOKE_VIRTUAL, handle.getHandleKind()); 218 219 MethodHandles.Lookup inUtil = defaultLookup.in(Vector.class); 220 221 // Package private in a public class in a different package from the lookup. 222 try { 223 inUtil.findVirtual(MethodHandlesTest.class, "packagePrivateMethod", 224 MethodType.methodType(void.class)); 225 fail(); 226 } catch (IllegalAccessException expected) { 227 } 228 229 // Protected in a public class in a different package from the lookup. 230 try { 231 inUtil.findVirtual(MethodHandlesTest.class, "protectedMethod", 232 MethodType.methodType(void.class)); 233 fail(); 234 } catch (IllegalAccessException expected) { 235 } 236 237 // Protected in a public class in a different package from the lookup. 238 try { 239 inUtil.findVirtual(MethodHandlesTest.class, "privateMethod", 240 MethodType.methodType(void.class)); 241 fail(); 242 } catch (IllegalAccessException expected) { 243 } 244 245 // Public method in a package private class in a different package from the lookup. 246 try { 247 inUtil.findVirtual(PackageSibling.class, "publicMethod", 248 MethodType.methodType(void.class)); 249 fail(); 250 } catch (IllegalAccessException expected) { 251 } 252 253 // Public static method should not discoverable via findVirtual. 254 try { 255 inUtil.findVirtual(MethodHandlesTest.class, "publicStaticMethod", 256 MethodType.methodType(void.class)); 257 fail(); 258 } catch (IllegalAccessException expected) { 259 } 260 } 261 262 public static class A { 263 public boolean aCalled; 264 265 public A() {} 266 267 public void foo() { 268 aCalled = true; 269 } 270 271 public static final Lookup lookup = MethodHandles.lookup(); 272 } 273 274 public static class B extends A { 275 public boolean bCalled; 276 277 public void foo() { 278 bCalled = true; 279 } 280 281 public static final Lookup lookup = MethodHandles.lookup(); 282 } 283 284 public static class C extends B { 285 public static final Lookup lookup = MethodHandles.lookup(); 286 } 287 288 public static class D { 289 public boolean privateDCalled; 290 291 private final void privateRyan() { 292 privateDCalled = true; 293 } 294 295 public static final Lookup lookup = MethodHandles.lookup(); 296 } 297 298 public static class E extends D { 299 public static final Lookup lookup = MethodHandles.lookup(); 300 } 301 302 public void testfindSpecial_invokeSuperBehaviour() throws Throwable { 303 // This is equivalent to an invoke-super instruction where the referrer 304 // is B.class. 305 MethodHandle mh1 = B.lookup.findSpecial(A.class /* refC */, "foo", 306 MethodType.methodType(void.class), B.class /* specialCaller */); 307 308 // This should be as if an invoke-super was called from one of B's methods. 309 B bInstance = new B(); 310 mh1.invokeExact(bInstance); 311 assertTrue(bInstance.aCalled); 312 313 bInstance = new B(); 314 mh1.invoke(bInstance); 315 assertTrue(bInstance.aCalled); 316 317 // This should not work. The receiver type in the handle will be suitably 318 // restricted to B and subclasses. 319 try { 320 mh1.invoke(new A()); 321 fail(); 322 } catch (ClassCastException expected) { 323 } 324 325 try { 326 mh1.invokeExact(new A()); 327 fail(); 328 } catch (WrongMethodTypeException expected) { 329 } 330 331 332 // This should *still* be as if an invoke-super was called from one of B's 333 // methods, despite the fact that we're operating on a C. 334 C cInstance = new C(); 335 mh1.invoke(cInstance); 336 assertTrue(cInstance.aCalled); 337 338 // Now that C is the special caller, the next invoke will call B.foo. 339 MethodHandle mh2 = C.lookup.findSpecial(A.class /* refC */, "foo", 340 MethodType.methodType(void.class), C.class /* specialCaller */); 341 cInstance = new C(); 342 mh2.invokeExact(cInstance); 343 assertTrue(cInstance.bCalled); 344 345 // Shouldn't allow invoke-super semantics from an unrelated special caller. 346 try { 347 C.lookup.findSpecial(A.class, "foo", 348 MethodType.methodType(void.class), D.class /* specialCaller */); 349 fail(); 350 } catch (IllegalAccessException expected) { 351 } 352 353 // Check return type matches for find. 354 try { 355 B.lookup.findSpecial(A.class /* refC */, "foo", 356 MethodType.methodType(int.class), B.class /* specialCaller */); 357 fail(); 358 } catch (NoSuchMethodException e) {} 359 // Check constructors 360 try { 361 B.lookup.findSpecial(A.class /* refC */, "<init>", 362 MethodType.methodType(void.class), B.class /* specialCaller */); 363 fail(); 364 } catch (NoSuchMethodException e) {} 365 } 366 367 public void testfindSpecial_invokeDirectBehaviour() throws Throwable { 368 D dInstance = new D(); 369 370 MethodHandle mh3 = D.lookup.findSpecial(D.class, "privateRyan", 371 MethodType.methodType(void.class), D.class /* specialCaller */); 372 mh3.invoke(dInstance); 373 374 // The private method shouldn't be accessible from any special caller except 375 // itself... 376 try { 377 D.lookup.findSpecial(D.class, "privateRyan", MethodType.methodType(void.class), 378 C.class); 379 fail(); 380 } catch (IllegalAccessException expected) { 381 } 382 383 // ... or from any lookup context except its own. 384 try { 385 E.lookup.findSpecial(D.class, "privateRyan", MethodType.methodType(void.class), 386 E.class); 387 fail(); 388 } catch (IllegalAccessException expected) { 389 } 390 } 391 392 public void testExceptionDetailMessages() throws Throwable { 393 MethodHandle handle = MethodHandles.lookup().findVirtual(String.class, "concat", 394 MethodType.methodType(String.class, String.class)); 395 396 try { 397 handle.invokeExact("a", new Object()); 398 fail(); 399 } catch (WrongMethodTypeException ex) { 400 assertEquals( 401 "Expected (java.lang.String, java.lang.String)java.lang.String " + 402 "but was (java.lang.String, java.lang.Object)void", 403 ex.getMessage()); 404 } 405 } 406 407 public interface Foo { 408 public String foo(); 409 } 410 411 public interface Bar extends Foo { 412 public String bar(); 413 } 414 415 public static abstract class BarAbstractSuper { 416 public abstract String abstractSuperPublicMethod(); 417 } 418 419 public static class BarSuper extends BarAbstractSuper { 420 public String superPublicMethod() { 421 return "superPublicMethod"; 422 } 423 424 protected String superProtectedMethod() { 425 return "superProtectedMethod"; 426 } 427 428 String superPackageMethod() { 429 return "superPackageMethod"; 430 } 431 432 public String abstractSuperPublicMethod() { 433 return "abstractSuperPublicMethod"; 434 } 435 } 436 437 public static class BarImpl extends BarSuper implements Bar { 438 public BarImpl() { 439 } 440 441 @Override 442 public String foo() { 443 return "foo"; 444 } 445 446 @Override 447 public String bar() { 448 return "bar"; 449 } 450 451 public String add(int x, int y) { 452 return Arrays.toString(new int[] { x, y }); 453 } 454 455 private String privateMethod() { return "privateMethod"; } 456 457 public static String staticMethod() { return staticString; } 458 459 private static String staticString; 460 461 { 462 // Static constructor 463 staticString = Long.toString(System.currentTimeMillis()); 464 } 465 466 static final MethodHandles.Lookup lookup = MethodHandles.lookup(); 467 } 468 469 public void testfindVirtual() throws Throwable { 470 // Virtual lookups on static methods should not succeed. 471 try { 472 MethodHandles.lookup().findVirtual( 473 BarImpl.class, "staticMethod", MethodType.methodType(String.class)); 474 fail(); 475 } catch (IllegalAccessException expected) { 476 } 477 478 // Virtual lookups on private methods should not succeed, unless the Lookup 479 // context had sufficient privileges. 480 try { 481 MethodHandles.lookup().findVirtual( 482 BarImpl.class, "privateMethod", MethodType.methodType(String.class)); 483 fail(); 484 } catch (IllegalAccessException expected) { 485 } 486 487 // Virtual lookup on a private method with a context that *does* have sufficient 488 // privileges. 489 MethodHandle mh = BarImpl.lookup.findVirtual( 490 BarImpl.class, "privateMethod", MethodType.methodType(String.class)); 491 String str = (String) mh.invoke(new BarImpl()); 492 assertEquals("privateMethod", str); 493 494 // Find virtual must find interface methods defined by interfaces implemented 495 // by the class. 496 mh = MethodHandles.lookup().findVirtual(BarImpl.class, "foo", 497 MethodType.methodType(String.class)); 498 str = (String) mh.invoke(new BarImpl()); 499 assertEquals("foo", str); 500 501 // Find virtual should check rtype. 502 try { 503 MethodHandles.lookup().findVirtual(BarImpl.class, "foo", 504 MethodType.methodType(void.class)); 505 fail(); 506 } catch (NoSuchMethodException expected) { 507 } 508 509 // And ptypes 510 mh = MethodHandles.lookup().findVirtual( 511 BarImpl.class, "add", MethodType.methodType(String.class, int.class, int.class)); 512 try { 513 MethodHandles.lookup().findVirtual( 514 BarImpl.class, "add", 515 MethodType.methodType(String.class, Integer.class, int.class)); 516 } catch (NoSuchMethodException expected) { 517 } 518 519 // .. and their super-interfaces. 520 mh = MethodHandles.lookup().findVirtual(BarImpl.class, "bar", 521 MethodType.methodType(String.class)); 522 str = (String) mh.invoke(new BarImpl()); 523 assertEquals("bar", str); 524 525 526 mh = MethodHandles.lookup().findVirtual(BarImpl.class, "bar", 527 MethodType.methodType(String.class)); 528 str = (String) mh.invoke(new BarImpl()); 529 assertEquals("bar", str); 530 531 mh = MethodHandles.lookup().findVirtual(BarAbstractSuper.class, "abstractSuperPublicMethod", 532 MethodType.methodType(String.class)); 533 str = (String) mh.invoke(new BarImpl()); 534 assertEquals("abstractSuperPublicMethod", str); 535 536 // We should also be able to lookup public / protected / package methods in 537 // the super class, given sufficient access privileges. 538 mh = MethodHandles.lookup().findVirtual(BarImpl.class, "superPublicMethod", 539 MethodType.methodType(String.class)); 540 str = (String) mh.invoke(new BarImpl()); 541 assertEquals("superPublicMethod", str); 542 543 mh = MethodHandles.lookup().findVirtual(BarImpl.class, "superProtectedMethod", 544 MethodType.methodType(String.class)); 545 str = (String) mh.invoke(new BarImpl()); 546 assertEquals("superProtectedMethod", str); 547 548 mh = MethodHandles.lookup().findVirtual(BarImpl.class, "superPackageMethod", 549 MethodType.methodType(String.class)); 550 str = (String) mh.invoke(new BarImpl()); 551 assertEquals("superPackageMethod", str); 552 553 try { 554 MethodHandles.lookup().findVirtual(BarImpl.class, "<init>", 555 MethodType.methodType(void.class)); 556 fail(); 557 } catch (NoSuchMethodException expected) { 558 } 559 } 560 561 public void testfindStatic() throws Throwable { 562 MethodHandles.lookup().findStatic(BarImpl.class, "staticMethod", 563 MethodType.methodType(String.class)); 564 try { 565 MethodHandles.lookup().findStatic(BarImpl.class, "staticMethod", 566 MethodType.methodType(void.class)); 567 fail(); 568 } catch (NoSuchMethodException expected) { 569 } 570 571 try { 572 MethodHandles.lookup().findStatic(BarImpl.class, "staticMethod", 573 MethodType.methodType(String.class, int.class)); 574 fail(); 575 } catch (NoSuchMethodException expected) { 576 } 577 578 try { 579 MethodHandles.lookup().findStatic(BarImpl.class, "<clinit>", 580 MethodType.methodType(void.class)); 581 fail(); 582 } catch (NoSuchMethodException expected) { 583 } 584 585 try { 586 MethodHandles.lookup().findStatic(BarImpl.class, "<init>", 587 MethodType.methodType(void.class)); 588 fail(); 589 } catch (NoSuchMethodException expected) { 590 } 591 } 592 593 static class UnreflectTesterBase { 594 public String overridenMethod() { 595 return "Base"; 596 } 597 } 598 599 static class UnreflectTester extends UnreflectTesterBase { 600 public String publicField; 601 private String privateField; 602 603 public static String publicStaticField = "publicStaticValue"; 604 private static String privateStaticField = "privateStaticValue"; 605 606 private UnreflectTester(String val) { 607 publicField = val; 608 privateField = val; 609 } 610 611 // NOTE: The boolean constructor argument only exists to give this a 612 // different signature. 613 public UnreflectTester(String val, boolean unused) { 614 this(val); 615 } 616 617 private static String privateStaticMethod() { 618 return "privateStaticMethod"; 619 } 620 621 private String privateMethod() { 622 return "privateMethod"; 623 } 624 625 public static String publicStaticMethod() { 626 return "publicStaticMethod"; 627 } 628 629 public String publicMethod() { 630 return "publicMethod"; 631 } 632 633 public String publicVarArgsMethod(String... args) { 634 return "publicVarArgsMethod"; 635 } 636 637 @Override 638 public String overridenMethod() { 639 return "Override"; 640 } 641 642 public static final Lookup lookup = MethodHandles.lookup(); 643 } 644 645 public void testUnreflects_publicMethods() throws Throwable { 646 UnreflectTester instance = new UnreflectTester("unused"); 647 Method publicMethod = UnreflectTester.class.getMethod("publicMethod"); 648 649 MethodHandle mh = MethodHandles.lookup().unreflect(publicMethod); 650 assertEquals("publicMethod", (String) mh.invoke(instance)); 651 assertEquals("publicMethod", (String) mh.invokeExact(instance)); 652 653 Method publicStaticMethod = UnreflectTester.class.getMethod("publicStaticMethod"); 654 mh = MethodHandles.lookup().unreflect(publicStaticMethod); 655 assertEquals("publicStaticMethod", (String) mh.invoke()); 656 assertEquals("publicStaticMethod", (String) mh.invokeExact()); 657 } 658 659 public void testUnreflects_privateMethods() throws Throwable { 660 Method privateMethod = UnreflectTester.class.getDeclaredMethod("privateMethod"); 661 662 try { 663 MethodHandles.lookup().unreflect(privateMethod); 664 fail(); 665 } catch (IllegalAccessException expected) { 666 } 667 668 UnreflectTester instance = new UnreflectTester("unused"); 669 MethodHandle mh = UnreflectTester.lookup.unreflectSpecial(privateMethod, 670 UnreflectTester.class); 671 assertEquals("privateMethod", (String) mh.invoke(instance)); 672 assertEquals("privateMethod", (String) mh.invokeExact(instance)); 673 674 privateMethod.setAccessible(true); 675 mh = MethodHandles.lookup().unreflect(privateMethod); 676 assertEquals("privateMethod", (String) mh.invoke(instance)); 677 assertEquals("privateMethod", (String) mh.invokeExact(instance)); 678 679 Method privateStaticMethod = UnreflectTester.class.getDeclaredMethod("privateStaticMethod"); 680 try { 681 MethodHandles.lookup().unreflect(privateStaticMethod); 682 fail(); 683 } catch (IllegalAccessException expected) { 684 } 685 686 try { 687 mh = UnreflectTester.lookup.unreflectSpecial(privateStaticMethod, 688 UnreflectTester.class); 689 fail(); 690 } catch (IllegalAccessException expected) { 691 } 692 693 privateStaticMethod.setAccessible(true); 694 mh = MethodHandles.lookup().unreflect(privateStaticMethod); 695 assertEquals("privateStaticMethod", (String) mh.invoke()); 696 assertEquals("privateStaticMethod", (String) mh.invokeExact()); 697 } 698 699 public void testUnreflectSpecial_superCalls() throws Throwable { 700 Method overridenMethod = UnreflectTester.class.getMethod("overridenMethod"); 701 UnreflectTester instance = new UnreflectTester("unused"); 702 MethodHandle mh = UnreflectTester.lookup.unreflectSpecial(overridenMethod, 703 UnreflectTester.class); 704 assertEquals("Base", (String) mh.invoke(instance)); 705 } 706 707 public void testUnreflects_constructors() throws Throwable { 708 Constructor privateConstructor = UnreflectTester.class.getDeclaredConstructor(String.class); 709 710 try { 711 MethodHandles.lookup().unreflectConstructor(privateConstructor); 712 fail(); 713 } catch (IllegalAccessException expected) { 714 } 715 716 privateConstructor.setAccessible(true); 717 MethodHandle mh = MethodHandles.lookup().unreflectConstructor(privateConstructor); 718 UnreflectTester instance = (UnreflectTester) mh.invokeExact("abc"); 719 assertEquals("abc", instance.publicField); 720 instance = (UnreflectTester) mh.invoke("def"); 721 assertEquals("def", instance.publicField); 722 Constructor publicConstructor = UnreflectTester.class.getConstructor(String.class, 723 boolean.class); 724 mh = MethodHandles.lookup().unreflectConstructor(publicConstructor); 725 instance = (UnreflectTester) mh.invokeExact("abc", false); 726 assertEquals("abc", instance.publicField); 727 instance = (UnreflectTester) mh.invoke("def", true); 728 assertEquals("def", instance.publicField); 729 } 730 731 public void testUnreflects_publicFields() throws Throwable { 732 Field publicField = UnreflectTester.class.getField("publicField"); 733 MethodHandle mh = MethodHandles.lookup().unreflectGetter(publicField); 734 UnreflectTester instance = new UnreflectTester("instanceValue"); 735 assertEquals("instanceValue", (String) mh.invokeExact(instance)); 736 737 mh = MethodHandles.lookup().unreflectSetter(publicField); 738 instance = new UnreflectTester("instanceValue"); 739 mh.invokeExact(instance, "updatedInstanceValue"); 740 assertEquals("updatedInstanceValue", instance.publicField); 741 742 Field publicStaticField = UnreflectTester.class.getField("publicStaticField"); 743 mh = MethodHandles.lookup().unreflectGetter(publicStaticField); 744 UnreflectTester.publicStaticField = "updatedStaticValue"; 745 assertEquals("updatedStaticValue", (String) mh.invokeExact()); 746 747 mh = MethodHandles.lookup().unreflectSetter(publicStaticField); 748 UnreflectTester.publicStaticField = "updatedStaticValue"; 749 mh.invokeExact("updatedStaticValue2"); 750 assertEquals("updatedStaticValue2", UnreflectTester.publicStaticField); 751 } 752 753 public void testUnreflects_privateFields() throws Throwable { 754 Field privateField = UnreflectTester.class.getDeclaredField("privateField"); 755 try { 756 MethodHandles.lookup().unreflectGetter(privateField); 757 fail(); 758 } catch (IllegalAccessException expected) { 759 } 760 try { 761 MethodHandles.lookup().unreflectSetter(privateField); 762 fail(); 763 } catch (IllegalAccessException expected) { 764 } 765 766 privateField.setAccessible(true); 767 768 MethodHandle mh = MethodHandles.lookup().unreflectGetter(privateField); 769 UnreflectTester instance = new UnreflectTester("instanceValue"); 770 assertEquals("instanceValue", (String) mh.invokeExact(instance)); 771 772 mh = MethodHandles.lookup().unreflectSetter(privateField); 773 instance = new UnreflectTester("instanceValue"); 774 mh.invokeExact(instance, "updatedInstanceValue"); 775 assertEquals("updatedInstanceValue", instance.privateField); 776 777 Field privateStaticField = UnreflectTester.class.getDeclaredField("privateStaticField"); 778 try { 779 MethodHandles.lookup().unreflectGetter(privateStaticField); 780 fail(); 781 } catch (IllegalAccessException expected) { 782 } 783 try { 784 MethodHandles.lookup().unreflectSetter(privateStaticField); 785 fail(); 786 } catch (IllegalAccessException expected) { 787 } 788 789 privateStaticField.setAccessible(true); 790 mh = MethodHandles.lookup().unreflectGetter(privateStaticField); 791 privateStaticField.set(null, "updatedStaticValue"); 792 assertEquals("updatedStaticValue", (String) mh.invokeExact()); 793 794 mh = MethodHandles.lookup().unreflectSetter(privateStaticField); 795 privateStaticField.set(null, "updatedStaticValue"); 796 mh.invokeExact("updatedStaticValue2"); 797 assertEquals("updatedStaticValue2", (String) privateStaticField.get(null)); 798 } 799 800 // This method only exists to fool Jack's handling of types. See b/32536744. 801 public static CharSequence getSequence() { 802 return "foo"; 803 } 804 805 public void testAsType() throws Throwable { 806 // The type of this handle is (String, String)String. 807 MethodHandle mh = MethodHandles.lookup().findVirtual(String.class, 808 "concat", MethodType.methodType(String.class, String.class)); 809 810 // Change it to (CharSequence, String)Object. 811 MethodHandle asType = mh.asType( 812 MethodType.methodType(Object.class, CharSequence.class, String.class)); 813 814 Object obj = asType.invokeExact((CharSequence) getSequence(), "bar"); 815 assertEquals("foobar", (String) obj); 816 817 // Should fail due to a wrong return type. 818 try { 819 String str = (String) asType.invokeExact((CharSequence) getSequence(), "bar"); 820 fail(); 821 } catch (WrongMethodTypeException expected) { 822 } 823 824 // Should fail due to a wrong argument type (String instead of Charsequence). 825 try { 826 String str = (String) asType.invokeExact("baz", "bar"); 827 fail(); 828 } catch (WrongMethodTypeException expected) { 829 } 830 831 // Calls to asType should fail if the types are not convertible. 832 // 833 // Bad return type conversion. 834 try { 835 mh.asType(MethodType.methodType(int.class, String.class, String.class)); 836 fail(); 837 } catch (WrongMethodTypeException expected) { 838 } 839 840 // Bad argument conversion. 841 try { 842 mh.asType(MethodType.methodType(String.class, int.class, String.class)); 843 fail(); 844 } catch (WrongMethodTypeException expected) { 845 } 846 } 847 848 public void testConstructors() throws Throwable { 849 MethodHandle mh = 850 MethodHandles.lookup().findConstructor(Float.class, 851 MethodType.methodType(void.class, 852 float.class)); 853 Float value = (Float) mh.invokeExact(0.33f); 854 assertEquals(0.33f, value); 855 856 value = (Float) mh.invoke(3.34f); 857 assertEquals(3.34f, value); 858 859 mh = MethodHandles.lookup().findConstructor(Double.class, 860 MethodType.methodType(void.class, String.class)); 861 Double d = (Double) mh.invoke("8.45e3"); 862 assertEquals(8.45e3, d); 863 864 mh = MethodHandles.lookup().findConstructor(Double.class, 865 MethodType.methodType(void.class, double.class)); 866 d = (Double) mh.invoke(8.45e3); 867 assertEquals(8.45e3, d); 868 869 // Primitive type 870 try { 871 mh = MethodHandles.lookup().findConstructor(int.class, MethodType.methodType(void.class)); 872 fail("Unexpected lookup success for primitive constructor"); 873 } catch (NoSuchMethodException expected) { 874 } 875 876 // Interface 877 try { 878 mh = MethodHandles.lookup().findConstructor(Readable.class, 879 MethodType.methodType(void.class)); 880 fail("Unexpected lookup success for interface constructor"); 881 } catch (NoSuchMethodException expected) { 882 } 883 884 // Abstract 885 mh = MethodHandles.lookup().findConstructor(Process.class, MethodType.methodType(void.class)); 886 try { 887 mh.invoke(); 888 fail("Unexpected ability to instantiate an abstract class"); 889 } catch (InstantiationException expected) { 890 } 891 892 // Non-existent 893 try { 894 MethodHandles.lookup().findConstructor( 895 String.class, MethodType.methodType(String.class, Float.class)); 896 fail("Unexpected success for non-existent constructor"); 897 } catch (NoSuchMethodException expected) { 898 } 899 900 // Non-void constructor search. (I)I instead of (I)V. 901 try { 902 MethodHandles.lookup().findConstructor( 903 Integer.class, MethodType.methodType(Integer.class, Integer.class)); 904 fail("Unexpected success for non-void type for findConstructor"); 905 } catch (NoSuchMethodException expected) { 906 } 907 908 // Array class constructor. 909 try { 910 MethodHandles.lookup().findConstructor( 911 Object[].class, MethodType.methodType(void.class)); 912 fail("Unexpected success for array class type for findConstructor"); 913 } catch (NoSuchMethodException expected) { 914 } 915 } 916 917 public void testStringConstructors() throws Throwable { 918 final String testPattern = "The system as we know it is broken"; 919 920 // String() 921 MethodHandle mh = MethodHandles.lookup().findConstructor( 922 String.class, MethodType.methodType(void.class)); 923 String s = (String) mh.invokeExact(); 924 assertEquals("", s); 925 926 // String(String) 927 mh = MethodHandles.lookup().findConstructor( 928 String.class, MethodType.methodType(void.class, String.class)); 929 s = (String) mh.invokeExact(testPattern); 930 assertEquals(testPattern, s); 931 932 933 // String(char[]) 934 mh = MethodHandles.lookup().findConstructor( 935 String.class, MethodType.methodType(void.class, char[].class)); 936 s = (String) mh.invokeExact(testPattern.toCharArray()); 937 assertEquals(testPattern, s); 938 939 // String(char[], int, int) 940 mh = MethodHandles.lookup().findConstructor( 941 String.class, MethodType.methodType(void.class, char[].class, int.class, int.class)); 942 s = (String) mh.invokeExact(new char [] { 'a', 'b', 'c', 'd', 'e'}, 2, 3); 943 assertEquals("cde", s); 944 945 // String(int[] codePoints, int offset, int count) 946 StringBuffer sb = new StringBuffer(testPattern); 947 int[] codePoints = new int[sb.codePointCount(0, sb.length())]; 948 for (int i = 0; i < sb.length(); ++i) { 949 codePoints[i] = sb.codePointAt(i); 950 } 951 mh = MethodHandles.lookup().findConstructor( 952 String.class, MethodType.methodType(void.class, int[].class, int.class, int.class)); 953 s = (String) mh.invokeExact(codePoints, 0, codePoints.length); 954 assertEquals(testPattern, s); 955 956 // String(byte ascii[], int hibyte, int offset, int count) 957 byte [] ascii = testPattern.getBytes(StandardCharsets.US_ASCII); 958 mh = MethodHandles.lookup().findConstructor( 959 String.class, MethodType.methodType(void.class, byte[].class, int.class, int.class)); 960 s = (String) mh.invokeExact(ascii, 0, ascii.length); 961 assertEquals(testPattern, s); 962 963 // String(byte bytes[], int offset, int length, String charsetName) 964 mh = MethodHandles.lookup().findConstructor( 965 String.class, 966 MethodType.methodType(void.class, byte[].class, int.class, int.class, String.class)); 967 s = (String) mh.invokeExact(ascii, 0, 5, StandardCharsets.US_ASCII.name()); 968 assertEquals(testPattern.substring(0, 5), s); 969 970 // String(byte bytes[], int offset, int length, Charset charset) 971 mh = MethodHandles.lookup().findConstructor( 972 String.class, 973 MethodType.methodType(void.class, byte[].class, int.class, int.class, Charset.class)); 974 s = (String) mh.invokeExact(ascii, 0, 5, StandardCharsets.US_ASCII); 975 assertEquals(testPattern.substring(0, 5), s); 976 977 // String(byte bytes[], String charsetName) 978 mh = MethodHandles.lookup().findConstructor( 979 String.class, 980 MethodType.methodType(void.class, byte[].class, String.class)); 981 s = (String) mh.invokeExact(ascii, StandardCharsets.US_ASCII.name()); 982 assertEquals(testPattern, s); 983 984 // String(byte bytes[], Charset charset) 985 mh = MethodHandles.lookup().findConstructor( 986 String.class, MethodType.methodType(void.class, byte[].class, Charset.class)); 987 s = (String) mh.invokeExact(ascii, StandardCharsets.US_ASCII); 988 assertEquals(testPattern, s); 989 990 // String(byte bytes[], int offset, int length) 991 mh = MethodHandles.lookup().findConstructor( 992 String.class, MethodType.methodType(void.class, byte[].class, int.class, int.class)); 993 s = (String) mh.invokeExact(ascii, 1, ascii.length - 2); 994 s = testPattern.charAt(0) + s + testPattern.charAt(testPattern.length() - 1); 995 assertEquals(testPattern, s); 996 997 // String(byte bytes[]) 998 mh = MethodHandles.lookup().findConstructor( 999 String.class, MethodType.methodType(void.class, byte[].class)); 1000 s = (String) mh.invokeExact(ascii); 1001 assertEquals(testPattern, s); 1002 1003 // String(StringBuffer buffer) 1004 mh = MethodHandles.lookup().findConstructor( 1005 String.class, MethodType.methodType(void.class, StringBuffer.class)); 1006 s = (String) mh.invokeExact(sb); 1007 assertEquals(testPattern, s); 1008 } 1009 1010 public void testReferenceReturnValueConversions() throws Throwable { 1011 MethodHandle mh = MethodHandles.lookup().findStatic( 1012 Float.class, "valueOf", MethodType.methodType(Float.class, String.class)); 1013 1014 // No conversion 1015 Float f = (Float) mh.invokeExact("1.375"); 1016 assertEquals(1.375f, f); 1017 1018 f = (Float) mh.invoke("1.875"); 1019 assertEquals(1.875f, f); 1020 1021 // Bad conversion 1022 try { 1023 int i = (int) mh.invokeExact("7.77"); 1024 fail(); 1025 } catch (WrongMethodTypeException expected) { 1026 } 1027 1028 try { 1029 int i = (int) mh.invoke("7.77"); 1030 fail(); 1031 } catch (WrongMethodTypeException expected) { 1032 } 1033 1034 // Assignment to super-class. 1035 Number n = (Number) mh.invoke("1.11"); 1036 try { 1037 Number o = (Number) mh.invokeExact("1.11"); 1038 fail(); 1039 } catch (WrongMethodTypeException expected) { 1040 } 1041 1042 // Assignment to widened boxed primitive class. 1043 try { 1044 Double u = (Double) mh.invoke("1.11"); 1045 fail(); 1046 } catch (ClassCastException expected) { 1047 } 1048 1049 try { 1050 Double v = (Double) mh.invokeExact("1.11"); 1051 fail(); 1052 } catch (WrongMethodTypeException expected) { 1053 } 1054 1055 // Unboxed 1056 float p = (float) mh.invoke("1.11"); 1057 assertEquals(1.11f, p); 1058 1059 // Unboxed and widened 1060 double d = (double) mh.invoke("2.5"); 1061 assertEquals(2.5, d); 1062 1063 // Interface 1064 Comparable<Float> c = (Comparable<Float>) mh.invoke("2.125"); 1065 assertEquals(0, c.compareTo(Float.valueOf(2.125f))); 1066 } 1067 1068 public void testPrimitiveReturnValueConversions() throws Throwable { 1069 MethodHandle mh = MethodHandles.lookup().findStatic( 1070 Math.class, "min", MethodType.methodType(int.class, int.class, int.class)); 1071 1072 final int SMALL = -8972; 1073 final int LARGE = 7932529; 1074 1075 // No conversion 1076 if ((int) mh.invokeExact(LARGE, SMALL) != SMALL) { 1077 fail(); 1078 } else if ((int) mh.invoke(LARGE, SMALL) != SMALL) { 1079 fail(); 1080 } else if ((int) mh.invokeExact(SMALL, LARGE) != SMALL) { 1081 fail(); 1082 } else if ((int) mh.invoke(SMALL, LARGE) != SMALL) { 1083 fail(); 1084 } 1085 1086 // int -> long 1087 try { 1088 long l = (long) mh.invokeExact(LARGE, SMALL); 1089 fail(); 1090 } catch (WrongMethodTypeException expected) { 1091 } 1092 1093 assertEquals((long) SMALL, (long) mh.invoke(LARGE, SMALL)); 1094 1095 // int -> short 1096 try { 1097 short s = (short) mh.invokeExact(LARGE, SMALL); 1098 fail(); 1099 } catch (WrongMethodTypeException expected) { 1100 } 1101 1102 // int -> Integer 1103 try { 1104 Integer i = (Integer) mh.invokeExact(LARGE, SMALL); 1105 fail(); 1106 } catch (WrongMethodTypeException expected) { 1107 } 1108 1109 assertEquals(Integer.valueOf(SMALL), (Integer) mh.invoke(LARGE, SMALL)); 1110 1111 // int -> Long 1112 try { 1113 Long l = (Long) mh.invokeExact(LARGE, SMALL); 1114 fail(); 1115 } catch (WrongMethodTypeException expected) { 1116 } 1117 1118 try { 1119 Long l = (Long) mh.invoke(LARGE, SMALL); 1120 fail(); 1121 } catch (WrongMethodTypeException expected) { 1122 } 1123 1124 // int -> Short 1125 try { 1126 Short s = (Short) mh.invokeExact(LARGE, SMALL); 1127 fail(); 1128 } catch (WrongMethodTypeException expected) { 1129 } 1130 1131 try { 1132 Short s = (Short) mh.invoke(LARGE, SMALL); 1133 fail(); 1134 } catch (WrongMethodTypeException expected) { 1135 } 1136 1137 // int -> Process 1138 try { 1139 Process p = (Process) mh.invokeExact(LARGE, SMALL); 1140 fail(); 1141 } catch (WrongMethodTypeException expected) { 1142 } 1143 1144 try { 1145 Process p = (Process) mh.invoke(LARGE, SMALL); 1146 fail(); 1147 } catch (WrongMethodTypeException expected) { 1148 } 1149 1150 // void -> Object 1151 mh = MethodHandles.lookup().findStatic(System.class, "gc", MethodType.methodType(void.class)); 1152 Object o = (Object) mh.invoke(); 1153 assertNull(o); 1154 1155 // void -> long 1156 long l = (long) mh.invoke(); 1157 assertEquals(0, l); 1158 1159 // boolean -> Boolean 1160 mh = MethodHandles.lookup().findStatic(Boolean.class, "parseBoolean", 1161 MethodType.methodType(boolean.class, String.class)); 1162 Boolean z = (Boolean) mh.invoke("True"); 1163 assertTrue(z); 1164 1165 // boolean -> int 1166 try { 1167 int dummy = (int) mh.invoke("True"); 1168 fail(); 1169 } catch (WrongMethodTypeException expected) { 1170 } 1171 1172 // boolean -> Integer 1173 try { 1174 Integer dummy = (Integer) mh.invoke("True"); 1175 fail(); 1176 } catch (WrongMethodTypeException expected) { 1177 } 1178 1179 // Boolean -> boolean 1180 mh = MethodHandles.lookup().findStatic(Boolean.class, "valueOf", 1181 MethodType.methodType(Boolean.class, boolean.class)); 1182 boolean w = (boolean) mh.invoke(false); 1183 assertFalse(w); 1184 1185 // Boolean -> int 1186 try { 1187 int dummy = (int) mh.invoke(false); 1188 fail(); 1189 } catch (WrongMethodTypeException expected) { 1190 } 1191 1192 // Boolean -> Integer 1193 try { 1194 Integer dummy = (Integer) mh.invoke("True"); 1195 fail(); 1196 } catch (WrongMethodTypeException expected) { 1197 } 1198 } 1199 1200 public static class BaseVariableArityTester { 1201 public String update(Float f0, Float... floats) { 1202 return "base " + f0 + ", " + Arrays.toString(floats); 1203 } 1204 } 1205 1206 public static class VariableArityTester extends BaseVariableArityTester { 1207 private String lastResult; 1208 1209 // Constructors 1210 public VariableArityTester() {} 1211 public VariableArityTester(boolean... booleans) { update(booleans); } 1212 public VariableArityTester(byte... bytes) { update(bytes); } 1213 public VariableArityTester(char... chars) { update(chars); } 1214 public VariableArityTester(short... shorts) { update(shorts); } 1215 public VariableArityTester(int... ints) { update(ints); } 1216 public VariableArityTester(long... longs) { update(longs); } 1217 public VariableArityTester(float... floats) { update(floats); } 1218 public VariableArityTester(double... doubles) { update(doubles); } 1219 public VariableArityTester(Float f0, Float... floats) { update(f0, floats); } 1220 public VariableArityTester(String s0, String... strings) { update(s0, strings); } 1221 public VariableArityTester(char c, Number... numbers) { update(c, numbers); } 1222 @SafeVarargs 1223 public VariableArityTester(ArrayList<Integer> l0, ArrayList<Integer>... lists) { 1224 update(l0, lists); 1225 } 1226 public VariableArityTester(List<?> l0, List<?>... lists) { update(l0, lists); } 1227 1228 // Methods 1229 public String update(boolean... booleans) { return lastResult = tally(booleans); } 1230 public String update(byte... bytes) { return lastResult = tally(bytes); } 1231 public String update(char... chars) { return lastResult = tally(chars); } 1232 public String update(short... shorts) { return lastResult = tally(shorts); } 1233 public String update(int... ints) { 1234 lastResult = tally(ints); 1235 return lastResult; 1236 } 1237 public String update(long... longs) { return lastResult = tally(longs); } 1238 public String update(float... floats) { return lastResult = tally(floats); } 1239 public String update(double... doubles) { return lastResult = tally(doubles); } 1240 @Override 1241 public String update(Float f0, Float... floats) { return lastResult = tally(f0, floats); } 1242 public String update(String s0, String... strings) { return lastResult = tally(s0, strings); } 1243 public String update(char c, Number... numbers) { return lastResult = tally(c, numbers); } 1244 @SafeVarargs 1245 public final String update(ArrayList<Integer> l0, ArrayList<Integer>... lists) { 1246 lastResult = tally(l0, lists); 1247 return lastResult; 1248 } 1249 public String update(List l0, List... lists) { return lastResult = tally(l0, lists); } 1250 1251 public String arrayMethod(Object[] o) { 1252 return Arrays.deepToString(o); 1253 } 1254 1255 public String lastResult() { return lastResult; } 1256 1257 // Static Methods 1258 public static String tally(boolean... booleans) { return Arrays.toString(booleans); } 1259 public static String tally(byte... bytes) { return Arrays.toString(bytes); } 1260 public static String tally(char... chars) { return Arrays.toString(chars); } 1261 public static String tally(short... shorts) { return Arrays.toString(shorts); } 1262 public static String tally(int... ints) { return Arrays.toString(ints); } 1263 public static String tally(long... longs) { return Arrays.toString(longs); } 1264 public static String tally(float... floats) { return Arrays.toString(floats); } 1265 public static String tally(double... doubles) { return Arrays.toString(doubles); } 1266 public static String tally(Float f0, Float... floats) { 1267 return f0 + ", " + Arrays.toString(floats); 1268 } 1269 public static String tally(String s0, String... strings) { 1270 return s0 + ", " + Arrays.toString(strings); 1271 } 1272 public static String tally(char c, Number... numbers) { 1273 return c + ", " + Arrays.toString(numbers); 1274 } 1275 @SafeVarargs 1276 public static String tally(ArrayList<Integer> l0, ArrayList<Integer>... lists) { 1277 return Arrays.toString(l0.toArray()) + ", " + Arrays.deepToString(lists); 1278 } 1279 public static String tally(List l0, List... lists) { 1280 return Arrays.deepToString(l0.toArray()) + ", " + Arrays.deepToString(lists); 1281 } 1282 public static void foo(int... ints) {} 1283 public static long sumToPrimitive(int... ints) { 1284 long result = 0; 1285 for (int i : ints) result += i; 1286 return result; 1287 } 1288 public static Long sumToReference(int... ints) { 1289 return new Long(sumToPrimitive(ints)); 1290 } 1291 public static MethodHandles.Lookup lookup() { 1292 return MethodHandles.lookup(); 1293 } 1294 } 1295 1296 // This method only exists to fool Jack's handling of types. See b/32536744. 1297 public static Object getAsObject(String[] strings) { 1298 return (Object) strings; 1299 } 1300 1301 public void testVariableArity_boolean() throws Throwable { 1302 MethodHandle mh; 1303 VariableArityTester vat = new VariableArityTester(); 1304 1305 assertEquals("[1]", vat.update(1)); 1306 assertEquals("[1, 1]", vat.update(1, 1)); 1307 assertEquals("[1, 1, 1]", vat.update(1, 1, 1)); 1308 1309 // Methods - boolean 1310 mh = MethodHandles.lookup().findVirtual(VariableArityTester.class, "update", 1311 MethodType.methodType(String.class, boolean[].class)); 1312 assertTrue(mh.isVarargsCollector()); 1313 assertFalse(mh.asFixedArity().isVarargsCollector()); 1314 assertEquals("[]", mh.invoke(vat)); 1315 assertEquals("[true, false, true]", mh.invoke(vat, true, false, true)); 1316 assertEquals("[true, false, true]", mh.invoke(vat, new boolean[]{true, false, true})); 1317 assertEquals("[false, true]", mh.invoke(vat, Boolean.valueOf(false), Boolean.valueOf(true))); 1318 try { 1319 mh.invoke(vat, true, true, 0); 1320 fail(); 1321 } catch (WrongMethodTypeException e) { 1322 } 1323 try { 1324 assertEquals("[false, true]", mh.invoke(vat, Boolean.valueOf(false), (Boolean) null)); 1325 fail(); 1326 } catch (NullPointerException e) { 1327 } 1328 } 1329 1330 public void testVariableArity_byte() throws Throwable { 1331 VariableArityTester vat = new VariableArityTester(); 1332 1333 // Methods - byte 1334 MethodHandle mh = MethodHandles.lookup().findVirtual(VariableArityTester.class, "update", 1335 MethodType.methodType(String.class, byte[].class)); 1336 assertTrue(mh.isVarargsCollector()); 1337 assertEquals("[]", mh.invoke(vat)); 1338 assertEquals("[32, 64, 97]", mh.invoke(vat, (byte) 32, Byte.valueOf((byte) 64), (byte) 97)); 1339 assertEquals("[32, 64, 97]", mh.invoke(vat, new byte[]{(byte) 32, (byte) 64, (byte) 97})); 1340 try { 1341 mh.invoke(vat, (byte) 1, Integer.valueOf(3), (byte) 0); 1342 fail(); 1343 } catch (WrongMethodTypeException e) { 1344 } 1345 } 1346 1347 public void testVariableArity_char() throws Throwable { 1348 MethodHandle mh; 1349 VariableArityTester vat = new VariableArityTester(); 1350 1351 // Methods - char 1352 mh = MethodHandles.lookup().findVirtual(VariableArityTester.class, "update", 1353 MethodType.methodType(String.class, char[].class)); 1354 assertTrue(mh.isVarargsCollector()); 1355 assertEquals("[]", mh.invoke(vat)); 1356 assertEquals("[A, B, C]", mh.invoke(vat, 'A', Character.valueOf('B'), 'C')); 1357 assertEquals("[W, X, Y, Z]", mh.invoke(vat, new char[]{'W', 'X', 'Y', 'Z'})); 1358 } 1359 1360 public void testVariableArity_short() throws Throwable { 1361 MethodHandle mh; 1362 VariableArityTester vat = new VariableArityTester(); 1363 1364 // Methods - short 1365 mh = MethodHandles.lookup().findVirtual(VariableArityTester.class, "update", 1366 MethodType.methodType(String.class, short[].class)); 1367 assertTrue(mh.isVarargsCollector()); 1368 assertEquals("[]", mh.invoke(vat)); 1369 assertEquals("[32767, -32768, 0]", 1370 mh.invoke(vat, Short.MAX_VALUE, Short.MIN_VALUE, Short.valueOf((short) 0))); 1371 assertEquals("[1, -1]", mh.invoke(vat, new short[]{(short) 1, (short) -1})); 1372 } 1373 1374 public void testVariableArity_int() throws Throwable { 1375 MethodHandle mh; 1376 VariableArityTester vat = new VariableArityTester(); 1377 1378 // Methods - int 1379 mh = MethodHandles.lookup().findVirtual(VariableArityTester.class, "update", 1380 MethodType.methodType(String.class, int[].class)); 1381 assertTrue(mh.isVarargsCollector()); 1382 assertEquals("[]", mh.invoke(vat)); 1383 assertEquals("[0, 2147483647, -2147483648, 0]", 1384 mh.invoke(vat, Integer.valueOf(0), Integer.MAX_VALUE, Integer.MIN_VALUE, 0)); 1385 assertEquals("[0, -1, 1, 0]", mh.invoke(vat, new int[]{0, -1, 1, 0})); 1386 1387 assertEquals("[5, 4, 3, 2, 1]", (String) mh.invokeExact(vat, new int[]{5, 4, 3, 2, 1})); 1388 try { 1389 assertEquals("[5, 4, 3, 2, 1]", (String) mh.invokeExact(vat, 5, 4, 3, 2, 1)); 1390 fail(); 1391 } catch (WrongMethodTypeException expected) { 1392 } 1393 assertEquals("[5, 4, 3, 2, 1]", (String) mh.invoke(vat, 5, 4, 3, 2, 1)); 1394 } 1395 1396 public void testVariableArity_long() throws Throwable { 1397 VariableArityTester vat = new VariableArityTester(); 1398 1399 // Methods - long 1400 MethodHandle mh = MethodHandles.lookup().findVirtual(VariableArityTester.class, "update", 1401 MethodType.methodType(String.class, long[].class)); 1402 1403 assertTrue(mh.isVarargsCollector()); 1404 assertEquals("[]", mh.invoke(vat)); 1405 assertEquals("[0, 9223372036854775807, -9223372036854775808]", 1406 mh.invoke(vat, Long.valueOf(0), Long.MAX_VALUE, Long.MIN_VALUE)); 1407 assertEquals("[0, -1, 1, 0]", mh.invoke(vat, new long[]{0, -1, 1, 0})); 1408 } 1409 1410 public void testVariableArity_float() throws Throwable { 1411 MethodHandle mh; 1412 VariableArityTester vat = new VariableArityTester(); 1413 1414 // Methods - float 1415 mh = MethodHandles.lookup().findVirtual(VariableArityTester.class, "update", 1416 MethodType.methodType(String.class, float[].class)); 1417 assertTrue(mh.isVarargsCollector()); 1418 assertEquals("[]", mh.invoke(vat)); 1419 assertEquals("[0.0, 1.25, -1.25]", 1420 mh.invoke(vat, 0.0f, Float.valueOf(1.25f), Float.valueOf(-1.25f))); 1421 assertEquals("[0.0, -1.0, 1.0, 0.0]", 1422 mh.invoke(vat, new float[]{0.0f, -1.0f, 1.0f, 0.0f})); 1423 } 1424 1425 public void testVariableArity_double() throws Throwable { 1426 VariableArityTester vat = new VariableArityTester(); 1427 1428 // Methods - double 1429 MethodHandle mh = MethodHandles.lookup().findVirtual(VariableArityTester.class, "update", 1430 MethodType.methodType(String.class, double[].class)); 1431 assertTrue(mh.isVarargsCollector()); 1432 assertEquals("[]", mh.invoke(vat)); 1433 assertEquals("[0.0, 1.25, -1.25]", 1434 mh.invoke(vat, 0.0, Double.valueOf(1.25), Double.valueOf(-1.25))); 1435 assertEquals("[0.0, -1.0, 1.0, 0.0]", 1436 mh.invoke(vat, new double[]{0.0, -1.0, 1.0, 0.0})); 1437 mh.invoke(vat, 0.3f, 1.33, 1.33); 1438 } 1439 1440 public void testVariableArity_String() throws Throwable { 1441 VariableArityTester vat = new VariableArityTester(); 1442 1443 // Methods - String 1444 MethodHandle mh = MethodHandles.lookup(). 1445 findVirtual(VariableArityTester.class, "update", 1446 MethodType.methodType(String.class, String.class, String[].class)); 1447 assertTrue(mh.isVarargsCollector()); 1448 assertEquals("Echidna, []", mh.invoke(vat, "Echidna")); 1449 assertEquals("Bongo, [Jerboa, Okapi]", 1450 mh.invoke(vat, "Bongo", "Jerboa", "Okapi")); 1451 } 1452 1453 public void testVariableArity_Float() throws Throwable { 1454 VariableArityTester vat = new VariableArityTester(); 1455 1456 // Methods - Float 1457 MethodHandle mh = MethodHandles.lookup(). 1458 findVirtual(VariableArityTester.class, "update", 1459 MethodType.methodType(String.class, Float.class, Float[].class)); 1460 1461 assertTrue(mh.isVarargsCollector()); 1462 assertEquals("9.99, [0.0, 0.1, 1.1]", 1463 (String) mh.invoke(vat, 1464 Float.valueOf(9.99f), 1465 new Float[]{ Float.valueOf(0.0f), Float.valueOf(0.1f), Float.valueOf(1.1f)})); 1466 assertEquals("9.99, [0.0, 0.1, 1.1]", 1467 (String) mh.invoke(vat, Float.valueOf(9.99f), Float.valueOf(0.0f), 1468 Float.valueOf(0.1f), Float.valueOf(1.1f))); 1469 assertEquals("9.99, [0.0, 0.1, 1.1]", 1470 (String) mh.invoke(vat, Float.valueOf(9.99f), 0.0f, 0.1f, 1.1f)); 1471 try { 1472 assertEquals("9.99, [77.0, 33.0, 64.0]", 1473 (String) mh.invoke(vat, Float.valueOf(9.99f), 77, 33, 64)); 1474 fail(); 1475 } catch (WrongMethodTypeException expected) { 1476 } 1477 1478 assertEquals("9.99, [0.0, 0.1, 1.1]", 1479 (String) mh.invokeExact(vat, Float.valueOf(9.99f), 1480 new Float[]{Float.valueOf(0.0f), 1481 Float.valueOf(0.1f), 1482 Float.valueOf(1.1f)})); 1483 assertEquals("9.99, [0.0, null, 1.1]", 1484 (String) mh.invokeExact(vat, Float.valueOf(9.99f), 1485 new Float[]{Float.valueOf(0.0f), 1486 null, 1487 Float.valueOf(1.1f)})); 1488 try { 1489 assertEquals("9.99, [0.0, 0.1, 1.1]", 1490 (String) mh.invokeExact(vat, Float.valueOf(9.99f), 0.0f, 0.1f, 1.1f)); 1491 fail(); 1492 } catch (WrongMethodTypeException expected) { 1493 } 1494 } 1495 1496 public void testVariableArity_Number() throws Throwable { 1497 MethodHandle mh; 1498 VariableArityTester vat = new VariableArityTester(); 1499 1500 // Methods - Number 1501 mh = MethodHandles.lookup(). 1502 findVirtual(VariableArityTester.class, "update", 1503 MethodType.methodType(String.class, char.class, Number[].class)); 1504 assertTrue(mh.isVarargsCollector()); 1505 assertFalse(mh.asFixedArity().isVarargsCollector()); 1506 assertEquals("x, []", (String) mh.invoke(vat, 'x')); 1507 assertEquals("x, [3.141]", (String) mh.invoke(vat, 'x', 3.141)); 1508 assertEquals("x, [null, 3.131, 37]", 1509 (String) mh.invoke(vat, 'x', null, 3.131, new Integer(37))); 1510 try { 1511 assertEquals("x, [null, 3.131, bad, 37]", 1512 (String) mh.invoke(vat, 'x', null, 3.131, "bad", new Integer(37))); 1513 assertTrue(false); 1514 fail(); 1515 } catch (ClassCastException e) { 1516 } 1517 try { 1518 assertEquals("x, [null, 3.131, bad, 37]", 1519 (String) mh.invoke( 1520 vat, 'x', (Process) null, 3.131, "bad", new Integer(37))); 1521 assertTrue(false); 1522 fail(); 1523 } catch (ClassCastException e) { 1524 } 1525 } 1526 1527 public void testVariableArity_arrayMethod() throws Throwable { 1528 MethodHandle mh; 1529 VariableArityTester vat = new VariableArityTester(); 1530 1531 // Methods - an array method that is not variable arity. 1532 mh = MethodHandles.lookup().findVirtual( 1533 VariableArityTester.class, "arrayMethod", 1534 MethodType.methodType(String.class, Object[].class)); 1535 assertFalse(mh.isVarargsCollector()); 1536 mh.invoke(vat, new Object[]{"123"}); 1537 try { 1538 assertEquals("-", mh.invoke(vat, new Float(3), new Float(4))); 1539 fail(); 1540 } catch (WrongMethodTypeException e) { 1541 } 1542 mh = mh.asVarargsCollector(Object[].class); 1543 assertTrue(mh.isVarargsCollector()); 1544 assertEquals("[3.0, 4.0]", (String) mh.invoke(vat, new Float(3), new Float(4))); 1545 } 1546 1547 public void testVariableArity_booleanConstructors() throws Throwable { 1548 // Constructors - default 1549 MethodHandle mh = MethodHandles.lookup().findConstructor( 1550 VariableArityTester.class, MethodType.methodType(void.class)); 1551 assertFalse(mh.isVarargsCollector()); 1552 1553 // Constructors - boolean 1554 mh = MethodHandles.lookup().findConstructor( 1555 VariableArityTester.class, MethodType.methodType(void.class, boolean[].class)); 1556 assertTrue(mh.isVarargsCollector()); 1557 assertEquals("[true, true, false]", 1558 ((VariableArityTester) mh.invoke(new boolean[]{true, true, false})).lastResult()); 1559 assertEquals("[true, true, false]", 1560 ((VariableArityTester) mh.invoke(true, true, false)).lastResult()); 1561 try { 1562 assertEquals("[true, true, false]", 1563 ((VariableArityTester) mh.invokeExact(true, true, false)).lastResult()); 1564 fail(); 1565 } catch (WrongMethodTypeException expected) { 1566 } 1567 } 1568 1569 public void testVariableArity_byteConstructors() throws Throwable { 1570 // Constructors - byte 1571 MethodHandle mh = MethodHandles.lookup().findConstructor( 1572 VariableArityTester.class, MethodType.methodType(void.class, byte[].class)); 1573 assertTrue(mh.isVarargsCollector()); 1574 assertEquals("[55, 66, 60]", 1575 ((VariableArityTester) 1576 mh.invoke(new byte[]{(byte) 55, (byte) 66, (byte) 60})).lastResult()); 1577 assertEquals("[55, 66, 60]", 1578 ((VariableArityTester) mh.invoke( 1579 (byte) 55, (byte) 66, (byte) 60)).lastResult()); 1580 try { 1581 assertEquals("[55, 66, 60]", 1582 ((VariableArityTester) mh.invokeExact( 1583 (byte) 55, (byte) 66, (byte) 60)).lastResult()); 1584 fail(); 1585 } catch (WrongMethodTypeException expected) { 1586 } 1587 try { 1588 assertEquals("[3, 3]", 1589 ((VariableArityTester) mh.invoke( 1590 new Number[]{Byte.valueOf((byte) 3), (byte) 3})).lastResult()); 1591 fail(); 1592 } catch (WrongMethodTypeException expected) { 1593 } 1594 } 1595 1596 public void testVariableArity_stringConstructors() throws Throwable { 1597 // Constructors - String (have a different path than other reference types). 1598 MethodHandle mh = MethodHandles.lookup().findConstructor( 1599 VariableArityTester.class, 1600 MethodType.methodType(void.class, String.class, String[].class)); 1601 assertTrue(mh.isVarargsCollector()); 1602 assertEquals("x, []", ((VariableArityTester) mh.invoke("x")).lastResult()); 1603 assertEquals("x, [y]", ((VariableArityTester) mh.invoke("x", "y")).lastResult()); 1604 assertEquals("x, [y, z]", 1605 ((VariableArityTester) mh.invoke("x", new String[]{"y", "z"})).lastResult()); 1606 try { 1607 assertEquals("x, [y]", ((VariableArityTester) mh.invokeExact("x", "y")).lastResult()); 1608 fail(); 1609 } catch (WrongMethodTypeException expected) { 1610 } 1611 assertEquals("x, [null, z]", 1612 ((VariableArityTester) mh.invoke("x", new String[]{null, "z"})).lastResult()); 1613 } 1614 1615 public void testVariableArity_numberConstructors() throws Throwable { 1616 // Constructors - Number 1617 MethodHandle mh = MethodHandles.lookup().findConstructor( 1618 VariableArityTester.class, MethodType.methodType(void.class, char.class, Number[].class)); 1619 assertTrue(mh.isVarargsCollector()); 1620 assertFalse(mh.asFixedArity().isVarargsCollector()); 1621 assertEquals("x, []", ((VariableArityTester) mh.invoke('x')).lastResult()); 1622 assertEquals("x, [3.141]", ((VariableArityTester) mh.invoke('x', 3.141)).lastResult()); 1623 assertEquals("x, [null, 3.131, 37]", 1624 ((VariableArityTester) mh.invoke('x', null, 3.131, new Integer(37))).lastResult()); 1625 try { 1626 assertEquals("x, [null, 3.131, bad, 37]", 1627 ((VariableArityTester) mh.invoke( 1628 'x', null, 3.131, "bad", new Integer(37))).lastResult()); 1629 fail(); 1630 } catch (ClassCastException expected) { 1631 } 1632 try { 1633 assertEquals("x, [null, 3.131, bad, 37]", 1634 ((VariableArityTester) mh.invoke( 1635 'x', (Process) null, 3.131, "bad", new Integer(37))).lastResult()); 1636 fail(); 1637 } catch (ClassCastException expected) { 1638 } 1639 } 1640 1641 public void testVariableArity_floatConstructors() throws Throwable { 1642 // Static Methods - Float 1643 MethodHandle mh = MethodHandles.lookup(). 1644 findStatic(VariableArityTester.class, "tally", 1645 MethodType.methodType(String.class, Float.class, Float[].class)); 1646 assertTrue(mh.isVarargsCollector()); 1647 assertEquals("9.99, [0.0, 0.1, 1.1]", 1648 (String) mh.invoke(Float.valueOf(9.99f), 1649 new Float[]{Float.valueOf(0.0f), 1650 Float.valueOf(0.1f), 1651 Float.valueOf(1.1f)})); 1652 assertEquals("9.99, [0.0, 0.1, 1.1]", 1653 (String) mh.invoke(Float.valueOf(9.99f), Float.valueOf(0.0f), 1654 Float.valueOf(0.1f), Float.valueOf(1.1f))); 1655 assertEquals("9.99, [0.0, 0.1, 1.1]", 1656 (String) mh.invoke(Float.valueOf(9.99f), 0.0f, 0.1f, 1.1f)); 1657 try { 1658 assertEquals("9.99, [77.0, 33.0, 64.0]", 1659 (String) mh.invoke(Float.valueOf(9.99f), 77, 33, 64)); 1660 fail(); 1661 } catch (WrongMethodTypeException expected) { 1662 } 1663 assertEquals("9.99, [0.0, 0.1, 1.1]", 1664 (String) mh.invokeExact(Float.valueOf(9.99f), 1665 new Float[]{Float.valueOf(0.0f), 1666 Float.valueOf(0.1f), 1667 Float.valueOf(1.1f)})); 1668 assertEquals("9.99, [0.0, null, 1.1]", 1669 (String) mh.invokeExact(Float.valueOf(9.99f), 1670 new Float[]{Float.valueOf(0.0f), 1671 null, 1672 Float.valueOf(1.1f)})); 1673 try { 1674 assertEquals("9.99, [0.0, 0.1, 1.1]", 1675 (String) mh.invokeExact(Float.valueOf(9.99f), 0.0f, 0.1f, 1.1f)); 1676 fail(); 1677 } catch (WrongMethodTypeException expected) { 1678 } 1679 } 1680 1681 public void testVariableArity_specialMethods() throws Throwable { 1682 VariableArityTester vat = new VariableArityTester(); 1683 1684 // Special methods - Float 1685 MethodHandle mh = VariableArityTester.lookup(). 1686 findSpecial(BaseVariableArityTester.class, "update", 1687 MethodType.methodType(String.class, Float.class, Float[].class), 1688 VariableArityTester.class); 1689 assertTrue(mh.isVarargsCollector()); 1690 assertEquals("base 9.99, [0.0, 0.1, 1.1]", 1691 (String) mh.invoke(vat, 1692 Float.valueOf(9.99f), 1693 new Float[]{Float.valueOf(0.0f), 1694 Float.valueOf(0.1f), 1695 Float.valueOf(1.1f)})); 1696 assertEquals("base 9.99, [0.0, 0.1, 1.1]", 1697 (String) mh.invoke(vat, Float.valueOf(9.99f), Float.valueOf(0.0f), 1698 Float.valueOf(0.1f), Float.valueOf(1.1f))); 1699 } 1700 1701 public void testVariableArity_returnValueConversions() throws Throwable { 1702 VariableArityTester vat = new VariableArityTester(); 1703 1704 // Return value conversions. 1705 MethodHandle mh = MethodHandles.lookup().findVirtual(VariableArityTester.class, "update", 1706 MethodType.methodType(String.class, int[].class)); 1707 assertEquals("[1, 2, 3]", (String) mh.invoke(vat, 1, 2, 3)); 1708 assertEquals("[1, 2, 3]", (Object) mh.invoke(vat, 1, 2, 3)); 1709 try { 1710 assertEquals("[1, 2, 3, 4]", (long) mh.invoke(vat, 1, 2, 3)); 1711 fail(); 1712 } catch (WrongMethodTypeException expected) { 1713 } 1714 assertEquals("[1, 2, 3]", vat.lastResult()); 1715 mh = MethodHandles.lookup().findStatic(VariableArityTester.class, "sumToPrimitive", 1716 MethodType.methodType(long.class, int[].class)); 1717 assertEquals(10l, (long) mh.invoke(1, 2, 3, 4)); 1718 assertEquals(Long.valueOf(10l), (Long) mh.invoke(1, 2, 3, 4)); 1719 mh = MethodHandles.lookup().findStatic(VariableArityTester.class, "sumToReference", 1720 MethodType.methodType(Long.class, int[].class)); 1721 Object o = mh.invoke(1, 2, 3, 4); 1722 long l = (long) mh.invoke(1, 2, 3, 4); 1723 assertEquals(10l, (long) mh.invoke(1, 2, 3, 4)); 1724 assertEquals(Long.valueOf(10l), (Long) mh.invoke(1, 2, 3, 4)); 1725 try { 1726 // WrongMethodTypeException should be raised before invoke here. 1727 assertEquals(Long.valueOf(10l), (Byte) mh.invoke(1, 2, 3, 4)); 1728 fail(); 1729 } catch (ClassCastException expected) { 1730 } 1731 try { 1732 // WrongMethodTypeException should be raised before invoke here. 1733 byte b = (byte) mh.invoke(1, 2, 3, 4); 1734 fail(); 1735 } catch (WrongMethodTypeException expected) { 1736 } 1737 } 1738 1739 public void testVariableArity_returnVoid() throws Throwable { 1740 // Return void produces 0 / null. 1741 MethodHandle mh = MethodHandles.lookup().findStatic(VariableArityTester.class, "foo", 1742 MethodType.methodType(void.class, int[].class)); 1743 assertEquals(null, (Object) mh.invoke(3, 2, 1)); 1744 assertEquals(0l, (long) mh.invoke(1, 2, 3)); 1745 } 1746 1747 public void testVariableArity_combinators() throws Throwable { 1748 VariableArityTester vat = new VariableArityTester(); 1749 1750 // Combinators 1751 MethodHandle mh = MethodHandles.lookup().findVirtual(VariableArityTester.class, "update", 1752 MethodType.methodType(String.class, boolean[].class)); 1753 assertTrue(mh.isVarargsCollector()); 1754 mh = mh.bindTo(vat); 1755 assertFalse(mh.isVarargsCollector()); 1756 mh = mh.asVarargsCollector(boolean[].class); 1757 assertTrue(mh.isVarargsCollector()); 1758 assertEquals("[]", mh.invoke()); 1759 assertEquals("[true, false, true]", mh.invoke(true, false, true)); 1760 assertEquals("[true, false, true]", mh.invoke(new boolean[] { true, false, true})); 1761 assertEquals("[false, true]", mh.invoke(Boolean.valueOf(false), Boolean.valueOf(true))); 1762 try { 1763 mh.invoke(true, true, 0); 1764 fail(); 1765 } catch (WrongMethodTypeException e) {} 1766 } 1767 1768 // The same tests as the above, except that we use use MethodHandles.bind instead of 1769 // MethodHandle.bindTo. 1770 public void testVariableArity_MethodHandles_bind() throws Throwable { 1771 VariableArityTester vat = new VariableArityTester(); 1772 MethodHandle mh = MethodHandles.lookup().bind(vat, "update", 1773 MethodType.methodType(String.class, boolean[].class)); 1774 assertTrue(mh.isVarargsCollector()); 1775 1776 assertEquals("[]", mh.invoke()); 1777 assertEquals("[true, false, true]", mh.invoke(true, false, true)); 1778 assertEquals("[true, false, true]", mh.invoke(new boolean[] { true, false, true})); 1779 assertEquals("[false, true]", mh.invoke(Boolean.valueOf(false), Boolean.valueOf(true))); 1780 1781 try { 1782 mh.invoke(true, true, 0); 1783 fail(); 1784 } catch (WrongMethodTypeException e) {} 1785 } 1786 1787 public void testRevealDirect() throws Throwable { 1788 // Test with a virtual method : 1789 MethodType type = MethodType.methodType(String.class); 1790 MethodHandle handle = MethodHandles.lookup().findVirtual( 1791 UnreflectTester.class, "publicMethod", type); 1792 1793 // Comparisons with an equivalent member obtained via reflection : 1794 MethodHandleInfo info = MethodHandles.lookup().revealDirect(handle); 1795 Method meth = UnreflectTester.class.getMethod("publicMethod"); 1796 1797 assertEquals(MethodHandleInfo.REF_invokeVirtual, info.getReferenceKind()); 1798 assertEquals("publicMethod", info.getName()); 1799 assertTrue(UnreflectTester.class == info.getDeclaringClass()); 1800 assertFalse(info.isVarArgs()); 1801 assertEquals(meth, info.reflectAs(Method.class, MethodHandles.lookup())); 1802 assertEquals(type, info.getMethodType()); 1803 1804 // Resolution via a public lookup should fail because the method in question 1805 // isn't public. 1806 try { 1807 info.reflectAs(Method.class, MethodHandles.publicLookup()); 1808 fail(); 1809 } catch (IllegalArgumentException expected) { 1810 } 1811 1812 // Test with a static method : 1813 handle = MethodHandles.lookup().findStatic(UnreflectTester.class, 1814 "publicStaticMethod", 1815 MethodType.methodType(String.class)); 1816 1817 info = MethodHandles.lookup().revealDirect(handle); 1818 meth = UnreflectTester.class.getMethod("publicStaticMethod"); 1819 assertEquals(MethodHandleInfo.REF_invokeStatic, info.getReferenceKind()); 1820 assertEquals("publicStaticMethod", info.getName()); 1821 assertTrue(UnreflectTester.class == info.getDeclaringClass()); 1822 assertFalse(info.isVarArgs()); 1823 assertEquals(meth, info.reflectAs(Method.class, MethodHandles.lookup())); 1824 assertEquals(type, info.getMethodType()); 1825 1826 // Test with a var-args method : 1827 type = MethodType.methodType(String.class, String[].class); 1828 handle = MethodHandles.lookup().findVirtual(UnreflectTester.class, 1829 "publicVarArgsMethod", type); 1830 1831 info = MethodHandles.lookup().revealDirect(handle); 1832 meth = UnreflectTester.class.getMethod("publicVarArgsMethod", String[].class); 1833 assertEquals(MethodHandleInfo.REF_invokeVirtual, info.getReferenceKind()); 1834 assertEquals("publicVarArgsMethod", info.getName()); 1835 assertTrue(UnreflectTester.class == info.getDeclaringClass()); 1836 assertTrue(info.isVarArgs()); 1837 assertEquals(meth, info.reflectAs(Method.class, MethodHandles.lookup())); 1838 assertEquals(type, info.getMethodType()); 1839 1840 // Test with a constructor : 1841 Constructor cons = UnreflectTester.class.getConstructor(String.class, boolean.class); 1842 type = MethodType.methodType(void.class, String.class, boolean.class); 1843 handle = MethodHandles.lookup().findConstructor(UnreflectTester.class, type); 1844 1845 info = MethodHandles.lookup().revealDirect(handle); 1846 assertEquals(MethodHandleInfo.REF_newInvokeSpecial, info.getReferenceKind()); 1847 assertEquals("<init>", info.getName()); 1848 assertTrue(UnreflectTester.class == info.getDeclaringClass()); 1849 assertFalse(info.isVarArgs()); 1850 assertEquals(cons, info.reflectAs(Constructor.class, MethodHandles.lookup())); 1851 assertEquals(type, info.getMethodType()); 1852 1853 // Test with a static field : 1854 Field field = UnreflectTester.class.getField("publicStaticField"); 1855 1856 handle = MethodHandles.lookup().findStaticSetter( 1857 UnreflectTester.class, "publicStaticField", String.class); 1858 1859 info = MethodHandles.lookup().revealDirect(handle); 1860 assertEquals(MethodHandleInfo.REF_putStatic, info.getReferenceKind()); 1861 assertEquals("publicStaticField", info.getName()); 1862 assertTrue(UnreflectTester.class == info.getDeclaringClass()); 1863 assertFalse(info.isVarArgs()); 1864 assertEquals(field, info.reflectAs(Field.class, MethodHandles.lookup())); 1865 assertEquals(MethodType.methodType(void.class, String.class), info.getMethodType()); 1866 1867 // Test with a setter on the same field, the type of the handle should change 1868 // but everything else must remain the same. 1869 handle = MethodHandles.lookup().findStaticGetter( 1870 UnreflectTester.class, "publicStaticField", String.class); 1871 info = MethodHandles.lookup().revealDirect(handle); 1872 assertEquals(MethodHandleInfo.REF_getStatic, info.getReferenceKind()); 1873 assertEquals(field, info.reflectAs(Field.class, MethodHandles.lookup())); 1874 assertEquals(MethodType.methodType(String.class), info.getMethodType()); 1875 1876 // Test with an instance field : 1877 field = UnreflectTester.class.getField("publicField"); 1878 1879 handle = MethodHandles.lookup().findSetter( 1880 UnreflectTester.class, "publicField", String.class); 1881 1882 info = MethodHandles.lookup().revealDirect(handle); 1883 assertEquals(MethodHandleInfo.REF_putField, info.getReferenceKind()); 1884 assertEquals("publicField", info.getName()); 1885 assertTrue(UnreflectTester.class == info.getDeclaringClass()); 1886 assertFalse(info.isVarArgs()); 1887 assertEquals(field, info.reflectAs(Field.class, MethodHandles.lookup())); 1888 assertEquals(MethodType.methodType(void.class, String.class), info.getMethodType()); 1889 1890 // Test with a setter on the same field, the type of the handle should change 1891 // but everything else must remain the same. 1892 handle = MethodHandles.lookup().findGetter( 1893 UnreflectTester.class, "publicField", String.class); 1894 info = MethodHandles.lookup().revealDirect(handle); 1895 assertEquals(MethodHandleInfo.REF_getField, info.getReferenceKind()); 1896 assertEquals(field, info.reflectAs(Field.class, MethodHandles.lookup())); 1897 assertEquals(MethodType.methodType(String.class), info.getMethodType()); 1898 } 1899 1900 public void testReflectAs() throws Throwable { 1901 // Test with a virtual method : 1902 MethodType type = MethodType.methodType(String.class); 1903 MethodHandle handle = MethodHandles.lookup().findVirtual( 1904 UnreflectTester.class, "publicMethod", type); 1905 1906 Method reflected = MethodHandles.reflectAs(Method.class, handle); 1907 Method meth = UnreflectTester.class.getMethod("publicMethod"); 1908 assertEquals(meth, reflected); 1909 1910 try { 1911 MethodHandles.reflectAs(Field.class, handle); 1912 fail(); 1913 } catch (ClassCastException expected) { 1914 } 1915 1916 try { 1917 MethodHandles.reflectAs(Constructor.class, handle); 1918 fail(); 1919 } catch (ClassCastException expected) { 1920 } 1921 1922 // Test with a private instance method, unlike the "checked crack" (lol..) API exposed 1923 // by revealDirect, this doesn't perform any access checks. 1924 handle = UnreflectTester.lookup.findSpecial( 1925 UnreflectTester.class, "privateMethod", type, UnreflectTester.class); 1926 meth = UnreflectTester.class.getDeclaredMethod("privateMethod"); 1927 reflected = MethodHandles.reflectAs(Method.class, handle); 1928 assertEquals(meth, reflected); 1929 1930 // Test with a constructor : 1931 type = MethodType.methodType(void.class, String.class, boolean.class); 1932 handle = MethodHandles.lookup().findConstructor(UnreflectTester.class, type); 1933 1934 Constructor cons = UnreflectTester.class.getConstructor(String.class, boolean.class); 1935 Constructor reflectedCons = MethodHandles.reflectAs(Constructor.class, handle); 1936 assertEquals(cons, reflectedCons); 1937 1938 try { 1939 MethodHandles.reflectAs(Method.class, handle); 1940 fail(); 1941 } catch (ClassCastException expected) { 1942 } 1943 1944 // Test with an instance field : 1945 handle = MethodHandles.lookup().findSetter( 1946 UnreflectTester.class, "publicField", String.class); 1947 1948 Field field = UnreflectTester.class.getField("publicField"); 1949 Field reflectedField = MethodHandles.reflectAs(Field.class, handle); 1950 assertEquals(field, reflectedField); 1951 1952 try { 1953 MethodHandles.reflectAs(Method.class, handle); 1954 fail(); 1955 } catch (ClassCastException expected) { 1956 } 1957 1958 // Test with a non-direct method handle. 1959 try { 1960 MethodHandles.reflectAs(Method.class, MethodHandles.constant(String.class, "foo")); 1961 fail(); 1962 } catch (IllegalArgumentException expected) { 1963 } 1964 } 1965 1966 public static class Inner1 { 1967 public static MethodHandles.Lookup lookup = MethodHandles.lookup(); 1968 } 1969 1970 public static class Inner2 { 1971 } 1972 1973 private static void privateStaticMethod() {} 1974 public static void publicStaticMethod() {} 1975 static void packagePrivateStaticMethod() {} 1976 protected static void protectedStaticMethod() {} 1977 1978 public void publicMethod() {} 1979 private void privateMethod() {} 1980 void packagePrivateMethod() {} 1981 protected void protectedMethod() {} 1982 1983 public static class ConstructorTest { 1984 ConstructorTest(String unused, int unused2) {} 1985 protected ConstructorTest(String unused) {} 1986 private ConstructorTest(String unused, char unused2) {} 1987 } 1988 } 1989 1990 class PackageSibling { 1991 public void publicMethod() {} 1992 public static void publicStaticMethod() {} 1993 1994 protected PackageSibling(String unused) {} 1995 public PackageSibling(String unused, char unused2) {} 1996 } 1997 1998