blob: 3c6f119f4a8b1327c4fbec6078e40c982098f89d [file] [log] [blame]
Narayan Kamath000e1882016-10-24 17:14:25 +01001/*
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
17import java.lang.invoke.MethodHandle;
18import java.lang.invoke.MethodHandles;
19import java.lang.invoke.MethodHandles.Lookup;
20import java.lang.invoke.MethodType;
21import java.lang.invoke.WrongMethodTypeException;
Narayan Kamath000e1882016-10-24 17:14:25 +010022
23public class Main {
Narayan Kamath000e1882016-10-24 17:14:25 +010024 public static void main(String[] args) throws Throwable {
25 testThrowException();
Narayan Kamath96120f42016-11-01 09:40:23 +000026 testDropArguments();
27 testCatchException();
28 testGuardWithTest();
Narayan Kamath3314dbb2016-11-03 18:01:32 +000029 testArrayElementGetter();
30 testArrayElementSetter();
31 testIdentity();
32 testConstant();
Narayan Kamath8677d0b2016-11-04 14:41:19 +000033 testBindTo();
Narayan Kamath000e1882016-10-24 17:14:25 +010034 }
35
36 public static void testThrowException() throws Throwable {
37 MethodHandle handle = MethodHandles.throwException(String.class,
38 IllegalArgumentException.class);
39
40 if (handle.type().returnType() != String.class) {
41 System.out.println("Unexpected return type for handle: " + handle +
42 " [ " + handle.type() + "]");
43 }
44
Narayan Kamath96120f42016-11-01 09:40:23 +000045 final IllegalArgumentException iae = new IllegalArgumentException("boo!");
Narayan Kamath000e1882016-10-24 17:14:25 +010046 try {
Narayan Kamath96120f42016-11-01 09:40:23 +000047 handle.invoke(iae);
Narayan Kamath000e1882016-10-24 17:14:25 +010048 System.out.println("Expected an exception of type: java.lang.IllegalArgumentException");
49 } catch (IllegalArgumentException expected) {
Narayan Kamath96120f42016-11-01 09:40:23 +000050 if (expected != iae) {
51 System.out.println("Wrong exception: expected " + iae + " but was " + expected);
52 }
Narayan Kamath000e1882016-10-24 17:14:25 +010053 }
54 }
Narayan Kamath96120f42016-11-01 09:40:23 +000055
56 public static void dropArguments_delegate(String message, long message2) {
57 System.out.println("Message: " + message + ", Message2: " + message2);
58 }
59
60 public static void testDropArguments() throws Throwable {
61 MethodHandle delegate = MethodHandles.lookup().findStatic(Main.class,
62 "dropArguments_delegate",
63 MethodType.methodType(void.class, new Class<?>[] { String.class, long.class }));
64
65 MethodHandle transform = MethodHandles.dropArguments(delegate, 0, int.class, Object.class);
66
67 // The transformer will accept two additional arguments at position zero.
68 try {
69 transform.invokeExact("foo", 42l);
70 fail();
71 } catch (WrongMethodTypeException expected) {
72 }
73
74 transform.invokeExact(45, new Object(), "foo", 42l);
75 transform.invoke(45, new Object(), "foo", 42l);
76
77 // Additional arguments at position 1.
78 transform = MethodHandles.dropArguments(delegate, 1, int.class, Object.class);
79 transform.invokeExact("foo", 45, new Object(), 42l);
80 transform.invoke("foo", 45, new Object(), 42l);
81
82 // Additional arguments at position 2.
83 transform = MethodHandles.dropArguments(delegate, 2, int.class, Object.class);
84 transform.invokeExact("foo", 42l, 45, new Object());
85 transform.invoke("foo", 42l, 45, new Object());
86
87 // Note that we still perform argument conversions even for the arguments that
88 // are subsequently dropped.
89 try {
90 transform.invoke("foo", 42l, 45l, new Object());
91 fail();
92 } catch (WrongMethodTypeException expected) {
93 } catch (IllegalArgumentException expected) {
94 // TODO(narayan): We currently throw the wrong type of exception here,
95 // it's IAE and should be WMTE instead.
96 }
97
Narayan Kamath0a8485e2016-11-02 18:47:11 +000098 // Check that asType works as expected.
99 transform = MethodHandles.dropArguments(delegate, 0, int.class, Object.class);
100 transform = transform.asType(MethodType.methodType(void.class,
101 new Class<?>[] { short.class, Object.class, String.class, long.class }));
102 transform.invokeExact((short) 45, new Object(), "foo", 42l);
103
Narayan Kamath96120f42016-11-01 09:40:23 +0000104 // Invalid argument location, should not be allowed.
105 try {
106 MethodHandles.dropArguments(delegate, -1, int.class, Object.class);
107 fail();
108 } catch (IllegalArgumentException expected) {
109 }
110
111 // Invalid argument location, should not be allowed.
112 try {
113 MethodHandles.dropArguments(delegate, 3, int.class, Object.class);
114 fail();
115 } catch (IllegalArgumentException expected) {
116 }
117
118 try {
119 MethodHandles.dropArguments(delegate, 1, void.class);
120 fail();
121 } catch (IllegalArgumentException expected) {
122 }
123 }
124
125 public static String testCatchException_target(String arg1, long arg2, String exceptionMessage)
126 throws Throwable {
127 if (exceptionMessage != null) {
128 throw new IllegalArgumentException(exceptionMessage);
129 }
130
131 System.out.println("Target: Arg1: " + arg1 + ", Arg2: " + arg2);
132 return "target";
133 }
134
135 public static String testCatchException_handler(IllegalArgumentException iae, String arg1, long arg2,
136 String exMsg) {
137 System.out.println("Handler: " + iae + ", Arg1: " + arg1 + ", Arg2: " + arg2 + ", ExMsg: " + exMsg);
138 return "handler1";
139 }
140
141 public static String testCatchException_handler2(IllegalArgumentException iae, String arg1) {
142 System.out.println("Handler: " + iae + ", Arg1: " + arg1);
143 return "handler2";
144 }
145
146 public static void testCatchException() throws Throwable {
147 MethodHandle target = MethodHandles.lookup().findStatic(Main.class,
148 "testCatchException_target",
149 MethodType.methodType(String.class, new Class<?>[] { String.class, long.class, String.class }));
150
151 MethodHandle handler = MethodHandles.lookup().findStatic(Main.class,
152 "testCatchException_handler",
153 MethodType.methodType(String.class, new Class<?>[] { IllegalArgumentException.class,
154 String.class, long.class, String.class }));
155
156 MethodHandle adapter = MethodHandles.catchException(target, IllegalArgumentException.class,
157 handler);
158
159 String returnVal = null;
160
161 // These two should end up calling the target always. We're passing a null exception
162 // message here, which means the target will not throw.
163 returnVal = (String) adapter.invoke("foo", 42, null);
164 assertEquals("target", returnVal);
165 returnVal = (String) adapter.invokeExact("foo", 42l, (String) null);
166 assertEquals("target", returnVal);
167
168 // We're passing a non-null exception message here, which means the target will throw,
169 // which in turn means that the handler must be called for the next two invokes.
170 returnVal = (String) adapter.invoke("foo", 42, "exceptionMessage");
171 assertEquals("handler1", returnVal);
172 returnVal = (String) adapter.invokeExact("foo", 42l, "exceptionMessage");
173 assertEquals("handler1", returnVal);
174
175 handler = MethodHandles.lookup().findStatic(Main.class,
176 "testCatchException_handler2",
177 MethodType.methodType(String.class, new Class<?>[] { IllegalArgumentException.class,
178 String.class }));
179 adapter = MethodHandles.catchException(target, IllegalArgumentException.class, handler);
180
181 returnVal = (String) adapter.invoke("foo", 42, "exceptionMessage");
182 assertEquals("handler2", returnVal);
183 returnVal = (String) adapter.invokeExact("foo", 42l, "exceptionMessage");
184 assertEquals("handler2", returnVal);
185
186 // Test that the type of the invoke doesn't matter. Here we call
187 // IllegalArgumentException.toString() on the exception that was thrown by
188 // the target.
189 handler = MethodHandles.lookup().findVirtual(IllegalArgumentException.class,
190 "toString", MethodType.methodType(String.class));
191 adapter = MethodHandles.catchException(target, IllegalArgumentException.class, handler);
192
193 returnVal = (String) adapter.invoke("foo", 42, "exceptionMessage");
194 assertEquals("java.lang.IllegalArgumentException: exceptionMessage", returnVal);
195 returnVal = (String) adapter.invokeExact("foo", 42l, "exceptionMessage2");
196 assertEquals("java.lang.IllegalArgumentException: exceptionMessage2", returnVal);
Narayan Kamath0a8485e2016-11-02 18:47:11 +0000197
198 // Check that asType works as expected.
199 adapter = MethodHandles.catchException(target, IllegalArgumentException.class,
200 handler);
201 adapter = adapter.asType(MethodType.methodType(String.class,
202 new Class<?>[] { String.class, int.class, String.class }));
203 returnVal = (String) adapter.invokeExact("foo", 42, "exceptionMessage");
204 assertEquals("java.lang.IllegalArgumentException: exceptionMessage", returnVal);
Narayan Kamath96120f42016-11-01 09:40:23 +0000205 }
206
207 public static boolean testGuardWithTest_test(String arg1, long arg2) {
208 return "target".equals(arg1) && 42 == arg2;
209 }
210
211 public static String testGuardWithTest_target(String arg1, long arg2, int arg3) {
212 System.out.println("target: " + arg1 + ", " + arg2 + ", " + arg3);
213 return "target";
214 }
215
216 public static String testGuardWithTest_fallback(String arg1, long arg2, int arg3) {
217 System.out.println("fallback: " + arg1 + ", " + arg2 + ", " + arg3);
218 return "fallback";
219 }
220
221 public static void testGuardWithTest() throws Throwable {
222 MethodHandle test = MethodHandles.lookup().findStatic(Main.class,
223 "testGuardWithTest_test",
224 MethodType.methodType(boolean.class, new Class<?>[] { String.class, long.class }));
225
226 final MethodType type = MethodType.methodType(String.class,
227 new Class<?>[] { String.class, long.class, int.class });
228
229 final MethodHandle target = MethodHandles.lookup().findStatic(Main.class,
230 "testGuardWithTest_target", type);
231 final MethodHandle fallback = MethodHandles.lookup().findStatic(Main.class,
232 "testGuardWithTest_fallback", type);
233
234 MethodHandle adapter = MethodHandles.guardWithTest(test, target, fallback);
235
236 String returnVal = null;
237
238 returnVal = (String) adapter.invoke("target", 42, 56);
239 assertEquals("target", returnVal);
240 returnVal = (String) adapter.invokeExact("target", 42l, 56);
241 assertEquals("target", returnVal);
242
243 returnVal = (String) adapter.invoke("fallback", 42l, 56);
244 assertEquals("fallback", returnVal);
245 returnVal = (String) adapter.invokeExact("target", 42l, 56);
246 assertEquals("target", returnVal);
Narayan Kamath0a8485e2016-11-02 18:47:11 +0000247
248 // Check that asType works as expected.
249 adapter = adapter.asType(MethodType.methodType(String.class,
250 new Class<?>[] { String.class, int.class, int.class }));
251 returnVal = (String) adapter.invokeExact("target", 42, 56);
252 assertEquals("target", returnVal);
Narayan Kamath96120f42016-11-01 09:40:23 +0000253 }
254
Narayan Kamath3314dbb2016-11-03 18:01:32 +0000255 public static void testArrayElementGetter() throws Throwable {
256 MethodHandle getter = MethodHandles.arrayElementGetter(int[].class);
257
258 {
259 int[] array = new int[1];
260 array[0] = 42;
261 int value = (int) getter.invoke(array, 0);
262 if (value != 42) {
263 System.out.println("Unexpected value: " + value);
264 }
265
266 try {
267 value = (int) getter.invoke(array, -1);
268 fail();
269 } catch (ArrayIndexOutOfBoundsException expected) {
270 }
271
272 try {
273 value = (int) getter.invoke(null, -1);
274 fail();
275 } catch (NullPointerException expected) {
276 }
277 }
278
279 {
280 getter = MethodHandles.arrayElementGetter(long[].class);
281 long[] array = new long[1];
282 array[0] = 42;
283 long value = (long) getter.invoke(array, 0);
284 if (value != 42l) {
285 System.out.println("Unexpected value: " + value);
286 }
287 }
288
289 {
290 getter = MethodHandles.arrayElementGetter(short[].class);
291 short[] array = new short[1];
292 array[0] = 42;
293 short value = (short) getter.invoke(array, 0);
294 if (value != 42l) {
295 System.out.println("Unexpected value: " + value);
296 }
297 }
298
299 {
300 getter = MethodHandles.arrayElementGetter(char[].class);
301 char[] array = new char[1];
302 array[0] = 42;
303 char value = (char) getter.invoke(array, 0);
304 if (value != 42l) {
305 System.out.println("Unexpected value: " + value);
306 }
307 }
308
309 {
310 getter = MethodHandles.arrayElementGetter(byte[].class);
311 byte[] array = new byte[1];
312 array[0] = (byte) 0x8;
313 byte value = (byte) getter.invoke(array, 0);
314 if (value != (byte) 0x8) {
315 System.out.println("Unexpected value: " + value);
316 }
317 }
318
319 {
320 getter = MethodHandles.arrayElementGetter(boolean[].class);
321 boolean[] array = new boolean[1];
322 array[0] = true;
323 boolean value = (boolean) getter.invoke(array, 0);
324 if (!value) {
325 System.out.println("Unexpected value: " + value);
326 }
327 }
328
329 {
330 getter = MethodHandles.arrayElementGetter(float[].class);
331 float[] array = new float[1];
332 array[0] = 42.0f;
333 float value = (float) getter.invoke(array, 0);
334 if (value != 42.0f) {
335 System.out.println("Unexpected value: " + value);
336 }
337 }
338
339 {
340 getter = MethodHandles.arrayElementGetter(double[].class);
341 double[] array = new double[1];
342 array[0] = 42.0;
343 double value = (double) getter.invoke(array, 0);
344 if (value != 42.0) {
345 System.out.println("Unexpected value: " + value);
346 }
347 }
348
349 {
350 getter = MethodHandles.arrayElementGetter(String[].class);
351 String[] array = new String[3];
352 array[0] = "42";
353 array[1] = "48";
354 array[2] = "54";
355 String value = (String) getter.invoke(array, 0);
356 assertEquals("42", value);
357 value = (String) getter.invoke(array, 1);
358 assertEquals("48", value);
359 value = (String) getter.invoke(array, 2);
360 assertEquals("54", value);
361 }
362 }
363
364 public static void testArrayElementSetter() throws Throwable {
365 MethodHandle setter = MethodHandles.arrayElementSetter(int[].class);
366
367 {
368 int[] array = new int[2];
369 setter.invoke(array, 0, 42);
370 setter.invoke(array, 1, 43);
371
372 if (array[0] != 42) {
373 System.out.println("Unexpected value: " + array[0]);
374 }
375 if (array[1] != 43) {
376 System.out.println("Unexpected value: " + array[1]);
377 }
378
379 try {
380 setter.invoke(array, -1, 42);
381 fail();
382 } catch (ArrayIndexOutOfBoundsException expected) {
383 }
384
385 try {
386 setter.invoke(null, 0, 42);
387 fail();
388 } catch (NullPointerException expected) {
389 }
390 }
391
392 {
393 setter = MethodHandles.arrayElementSetter(long[].class);
394 long[] array = new long[1];
395 setter.invoke(array, 0, 42l);
396 if (array[0] != 42l) {
397 System.out.println("Unexpected value: " + array[0]);
398 }
399 }
400
401 {
402 setter = MethodHandles.arrayElementSetter(short[].class);
403 short[] array = new short[1];
404 setter.invoke(array, 0, (short) 42);
405 if (array[0] != 42l) {
406 System.out.println("Unexpected value: " + array[0]);
407 }
408 }
409
410 {
411 setter = MethodHandles.arrayElementSetter(char[].class);
412 char[] array = new char[1];
413 setter.invoke(array, 0, (char) 42);
414 if (array[0] != 42) {
415 System.out.println("Unexpected value: " + array[0]);
416 }
417 }
418
419 {
420 setter = MethodHandles.arrayElementSetter(byte[].class);
421 byte[] array = new byte[1];
422 setter.invoke(array, 0, (byte) 0x8);
423 if (array[0] != (byte) 0x8) {
424 System.out.println("Unexpected value: " + array[0]);
425 }
426 }
427
428 {
429 setter = MethodHandles.arrayElementSetter(boolean[].class);
430 boolean[] array = new boolean[1];
431 setter.invoke(array, 0, true);
432 if (!array[0]) {
433 System.out.println("Unexpected value: " + array[0]);
434 }
435 }
436
437 {
438 setter = MethodHandles.arrayElementSetter(float[].class);
439 float[] array = new float[1];
440 setter.invoke(array, 0, 42.0f);
441 if (array[0] != 42.0f) {
442 System.out.println("Unexpected value: " + array[0]);
443 }
444 }
445
446 {
447 setter = MethodHandles.arrayElementSetter(double[].class);
448 double[] array = new double[1];
449 setter.invoke(array, 0, 42.0);
450 if (array[0] != 42.0) {
451 System.out.println("Unexpected value: " + array[0]);
452 }
453 }
454
455 {
456 setter = MethodHandles.arrayElementSetter(String[].class);
457 String[] array = new String[3];
458 setter.invoke(array, 0, "42");
459 setter.invoke(array, 1, "48");
460 setter.invoke(array, 2, "54");
461 assertEquals("42", array[0]);
462 assertEquals("48", array[1]);
463 assertEquals("54", array[2]);
464 }
465 }
466
467 public static void testIdentity() throws Throwable {
468 {
469 MethodHandle identity = MethodHandles.identity(boolean.class);
470 boolean value = (boolean) identity.invoke(false);
471 if (value) {
472 System.out.println("Unexpected value: " + value);
473 }
474 }
475
476 {
477 MethodHandle identity = MethodHandles.identity(byte.class);
478 byte value = (byte) identity.invoke((byte) 0x8);
479 if (value != (byte) 0x8) {
480 System.out.println("Unexpected value: " + value);
481 }
482 }
483
484 {
485 MethodHandle identity = MethodHandles.identity(char.class);
486 char value = (char) identity.invoke((char) -56);
487 if (value != (char) -56) {
488 System.out.println("Unexpected value: " + value);
489 }
490 }
491
492 {
493 MethodHandle identity = MethodHandles.identity(short.class);
494 short value = (short) identity.invoke((short) -59);
495 if (value != (short) -59) {
496 System.out.println("Unexpected value: " + value);
497 }
498 }
499
500 {
501 MethodHandle identity = MethodHandles.identity(int.class);
502 int value = (int) identity.invoke(52);
503 if (value != 52) {
504 System.out.println("Unexpected value: " + value);
505 }
506 }
507
508 {
509 MethodHandle identity = MethodHandles.identity(long.class);
510 long value = (long) identity.invoke(-76l);
511 if (value != (long) -76) {
512 System.out.println("Unexpected value: " + value);
513 }
514 }
515
516 {
517 MethodHandle identity = MethodHandles.identity(float.class);
518 float value = (float) identity.invoke(56.0f);
519 if (value != (float) 56.0f) {
520 System.out.println("Unexpected value: " + value);
521 }
522 }
523
524 {
525 MethodHandle identity = MethodHandles.identity(double.class);
526 double value = (double) identity.invoke((double) 72.0);
527 if (value != (double) 72.0) {
528 System.out.println("Unexpected value: " + value);
529 }
530 }
531
532 {
533 MethodHandle identity = MethodHandles.identity(String.class);
534 String value = (String) identity.invoke("bazman");
535 assertEquals("bazman", value);
536 }
537 }
538
539 public static void testConstant() throws Throwable {
540 // int constants.
541 {
542 MethodHandle constant = MethodHandles.constant(int.class, 56);
543 int value = (int) constant.invoke();
544 if (value != 56) {
545 System.out.println("Unexpected value: " + value);
546 }
547
548 // short constant values are converted to int.
549 constant = MethodHandles.constant(int.class, (short) 52);
550 value = (int) constant.invoke();
551 if (value != 52) {
552 System.out.println("Unexpected value: " + value);
553 }
554
555 // char constant values are converted to int.
556 constant = MethodHandles.constant(int.class, (char) 'b');
557 value = (int) constant.invoke();
558 if (value != (int) 'b') {
559 System.out.println("Unexpected value: " + value);
560 }
561
562 // int constant values are converted to int.
563 constant = MethodHandles.constant(int.class, (byte) 0x1);
564 value = (int) constant.invoke();
565 if (value != 1) {
566 System.out.println("Unexpected value: " + value);
567 }
568
569 // boolean, float, double and long primitive constants are not convertible
570 // to int, so the handle creation must fail with a CCE.
571 try {
572 MethodHandles.constant(int.class, false);
573 fail();
574 } catch (ClassCastException expected) {
575 }
576
577 try {
578 MethodHandles.constant(int.class, 0.1f);
579 fail();
580 } catch (ClassCastException expected) {
581 }
582
583 try {
584 MethodHandles.constant(int.class, 0.2);
585 fail();
586 } catch (ClassCastException expected) {
587 }
588
589 try {
590 MethodHandles.constant(int.class, 73l);
591 fail();
592 } catch (ClassCastException expected) {
593 }
594 }
595
596 // long constants.
597 {
598 MethodHandle constant = MethodHandles.constant(long.class, 56l);
599 long value = (long) constant.invoke();
600 if (value != 56l) {
601 System.out.println("Unexpected value: " + value);
602 }
603
604 constant = MethodHandles.constant(long.class, (int) 56);
605 value = (long) constant.invoke();
606 if (value != 56l) {
607 System.out.println("Unexpected value: " + value);
608 }
609 }
610
611 // byte constants.
612 {
613 MethodHandle constant = MethodHandles.constant(byte.class, (byte) 0x12);
614 byte value = (byte) constant.invoke();
615 if (value != (byte) 0x12) {
616 System.out.println("Unexpected value: " + value);
617 }
618 }
619
620 // boolean constants.
621 {
622 MethodHandle constant = MethodHandles.constant(boolean.class, true);
623 boolean value = (boolean) constant.invoke();
624 if (!value) {
625 System.out.println("Unexpected value: " + value);
626 }
627 }
628
629 // char constants.
630 {
631 MethodHandle constant = MethodHandles.constant(char.class, 'f');
632 char value = (char) constant.invoke();
633 if (value != 'f') {
634 System.out.println("Unexpected value: " + value);
635 }
636 }
637
638 // short constants.
639 {
640 MethodHandle constant = MethodHandles.constant(short.class, (short) 123);
641 short value = (short) constant.invoke();
642 if (value != (short) 123) {
643 System.out.println("Unexpected value: " + value);
644 }
645 }
646
647 // float constants.
648 {
649 MethodHandle constant = MethodHandles.constant(float.class, 56.0f);
650 float value = (float) constant.invoke();
651 if (value != 56.0f) {
652 System.out.println("Unexpected value: " + value);
653 }
654 }
655
656 // double constants.
657 {
658 MethodHandle constant = MethodHandles.constant(double.class, 256.0);
659 double value = (double) constant.invoke();
660 if (value != 256.0) {
661 System.out.println("Unexpected value: " + value);
662 }
663 }
664
665 // reference constants.
666 {
667 MethodHandle constant = MethodHandles.constant(String.class, "256.0");
668 String value = (String) constant.invoke();
669 assertEquals("256.0", value);
670 }
671 }
672
Narayan Kamath8677d0b2016-11-04 14:41:19 +0000673 public static void testBindTo() throws Throwable {
674 MethodHandle stringCharAt = MethodHandles.lookup().findVirtual(
675 String.class, "charAt", MethodType.methodType(char.class, int.class));
676
677 char value = (char) stringCharAt.invoke("foo", 0);
678 if (value != 'f') {
679 System.out.println("Unexpected value: " + value);
680 }
681
682 MethodHandle bound = stringCharAt.bindTo("foo");
683 value = (char) bound.invoke(0);
684 if (value != 'f') {
685 System.out.println("Unexpected value: " + value);
686 }
687
688 try {
689 stringCharAt.bindTo(new Object());
690 fail();
691 } catch (ClassCastException expected) {
692 }
693
694 bound = stringCharAt.bindTo(null);
695 try {
696 bound.invoke(0);
697 fail();
698 } catch (NullPointerException expected) {
699 }
700
701 MethodHandle integerParseInt = MethodHandles.lookup().findStatic(
702 Integer.class, "parseInt", MethodType.methodType(int.class, String.class));
703
704 bound = integerParseInt.bindTo("78452");
705 int intValue = (int) bound.invoke();
706 if (intValue != 78452) {
707 System.out.println("Unexpected value: " + intValue);
708 }
709 }
710
Narayan Kamath96120f42016-11-01 09:40:23 +0000711 public static void fail() {
712 System.out.println("FAIL");
713 Thread.dumpStack();
714 }
715
716 public static void assertEquals(String s1, String s2) {
717 if (s1 == s2) {
718 return;
719 }
720
721 if (s1 != null && s2 != null && s1.equals(s2)) {
722 return;
723 }
724
725 throw new AssertionError("assertEquals s1: " + s1 + ", s2: " + s2);
726 }
Narayan Kamath000e1882016-10-24 17:14:25 +0100727}
728
729