blob: d0c658f819a71cf8fe63b94de7009f6004336e11 [file] [log] [blame]
Narayan Kamath9bdaeeb2016-10-20 10:57:45 +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;
Orion Hodson0d781e62016-11-04 11:09:53 +000022import java.nio.charset.Charset;
23import java.nio.charset.StandardCharsets;
Narayan Kamath9bdaeeb2016-10-20 10:57:45 +010024
Narayan Kamathe5eb5742016-11-02 14:16:27 +000025import java.lang.reflect.Constructor;
26import java.lang.reflect.Field;
27import java.lang.reflect.Method;
28
Narayan Kamath9bdaeeb2016-10-20 10:57:45 +010029public class Main {
30
31 public static class A {
32 public void foo() {
33 System.out.println("foo_A");
34 }
35
36 public static final Lookup lookup = MethodHandles.lookup();
37 }
38
39 public static class B extends A {
40 public void foo() {
41 System.out.println("foo_B");
42 }
43
44 public static final Lookup lookup = MethodHandles.lookup();
45 }
46
47 public static class C extends B {
48 public static final Lookup lookup = MethodHandles.lookup();
49 }
50
51 public static class D {
52 private final void privateRyan() {
53 System.out.println("privateRyan_D");
54 }
55
56 public static final Lookup lookup = MethodHandles.lookup();
57 }
58
59 public static class E extends D {
60 public static final Lookup lookup = MethodHandles.lookup();
61 }
62
63 public static void main(String[] args) throws Throwable {
64 testfindSpecial_invokeSuperBehaviour();
65 testfindSpecial_invokeDirectBehaviour();
Narayan Kamath3e0dce02016-10-31 13:55:55 +000066 testExceptionDetailMessages();
Narayan Kamath94bee022016-11-01 10:57:15 +000067 testfindVirtual();
Narayan Kamathe5eb5742016-11-02 14:16:27 +000068 testUnreflects();
Narayan Kamath0a8485e2016-11-02 18:47:11 +000069 testAsType();
Orion Hodson0d781e62016-11-04 11:09:53 +000070 testConstructors();
71 testStringConstructors();
Narayan Kamath9bdaeeb2016-10-20 10:57:45 +010072 }
73
74 public static void testfindSpecial_invokeSuperBehaviour() throws Throwable {
75 // This is equivalent to an invoke-super instruction where the referrer
76 // is B.class.
77 MethodHandle mh1 = B.lookup.findSpecial(A.class /* refC */, "foo",
78 MethodType.methodType(void.class), B.class /* specialCaller */);
79
80 A aInstance = new A();
81 B bInstance = new B();
82 C cInstance = new C();
83
84 // This should be as if an invoke-super was called from one of B's methods.
85 mh1.invokeExact(bInstance);
86 mh1.invoke(bInstance);
87
88 // This should not work. The receiver type in the handle will be suitably
89 // restricted to B and subclasses.
90 try {
91 mh1.invoke(aInstance);
92 System.out.println("mh1.invoke(aInstance) should not succeeed");
93 } catch (ClassCastException expected) {
94 }
95
96 try {
97 mh1.invokeExact(aInstance);
98 System.out.println("mh1.invoke(aInstance) should not succeeed");
99 } catch (WrongMethodTypeException expected) {
Narayan Kamath9bdaeeb2016-10-20 10:57:45 +0100100 }
101
102 // This should *still* be as if an invoke-super was called from one of C's
103 // methods, despite the fact that we're operating on a C.
104 mh1.invoke(cInstance);
105
106 // Now that C is the special caller, the next invoke will call B.foo.
107 MethodHandle mh2 = C.lookup.findSpecial(A.class /* refC */, "foo",
108 MethodType.methodType(void.class), C.class /* specialCaller */);
109 mh2.invokeExact(cInstance);
110
111 // Shouldn't allow invoke-super semantics from an unrelated special caller.
112 try {
113 C.lookup.findSpecial(A.class, "foo",
114 MethodType.methodType(void.class), D.class /* specialCaller */);
115 System.out.println("findSpecial(A.class, foo, .. D.class) unexpectedly succeeded.");
116 } catch (IllegalAccessException expected) {
117 }
118 }
119
120 public static void testfindSpecial_invokeDirectBehaviour() throws Throwable {
121 D dInstance = new D();
122
123 MethodHandle mh3 = D.lookup.findSpecial(D.class, "privateRyan",
124 MethodType.methodType(void.class), D.class /* specialCaller */);
125 mh3.invoke(dInstance);
126
127 // The private method shouldn't be accessible from any special caller except
128 // itself...
129 try {
130 D.lookup.findSpecial(D.class, "privateRyan", MethodType.methodType(void.class), C.class);
131 System.out.println("findSpecial(privateRyan, C.class) unexpectedly succeeded");
132 } catch (IllegalAccessException expected) {
133 }
134
135 // ... or from any lookup context except its own.
136 try {
137 E.lookup.findSpecial(D.class, "privateRyan", MethodType.methodType(void.class), E.class);
138 System.out.println("findSpecial(privateRyan, E.class) unexpectedly succeeded");
139 } catch (IllegalAccessException expected) {
140 }
141 }
Narayan Kamath3e0dce02016-10-31 13:55:55 +0000142
143 public static void testExceptionDetailMessages() throws Throwable {
144 MethodHandle handle = MethodHandles.lookup().findVirtual(String.class, "concat",
145 MethodType.methodType(String.class, String.class));
146
147 try {
148 handle.invokeExact("a", new Object());
149 System.out.println("invokeExact(\"a\", new Object()) unexpectedly succeeded.");
150 } catch (WrongMethodTypeException ex) {
151 System.out.println("Received exception: " + ex.getMessage());
152 }
153 }
Narayan Kamath94bee022016-11-01 10:57:15 +0000154
155 public interface Foo {
156 public String foo();
157 }
158
159 public interface Bar extends Foo {
160 public String bar();
161 }
162
163 public static class BarSuper {
164 public String superPublicMethod() {
165 return "superPublicMethod";
166 }
167
168 public String superProtectedMethod() {
169 return "superProtectedMethod";
170 }
171
172 String superPackageMethod() {
173 return "superPackageMethod";
174 }
175 }
176
177 public static class BarImpl extends BarSuper implements Bar {
178 public BarImpl() {
179 }
180
181 @Override
182 public String foo() {
183 return "foo";
184 }
185
186 @Override
187 public String bar() {
188 return "bar";
189 }
190
191 private String privateMethod() { return "privateMethod"; }
192
193 public static String staticMethod() { return null; }
194
195 static final MethodHandles.Lookup lookup = MethodHandles.lookup();
196 }
197
198 public static void testfindVirtual() throws Throwable {
199 // Virtual lookups on static methods should not succeed.
200 try {
201 MethodHandles.lookup().findVirtual(
202 BarImpl.class, "staticMethod", MethodType.methodType(String.class));
203 System.out.println("findVirtual(staticMethod) unexpectedly succeeded");
204 } catch (IllegalAccessException expected) {
205 }
206
207 // Virtual lookups on private methods should not succeed, unless the Lookup
208 // context had sufficient privileges.
209 try {
210 MethodHandles.lookup().findVirtual(
211 BarImpl.class, "privateMethod", MethodType.methodType(String.class));
212 System.out.println("findVirtual(privateMethod) unexpectedly succeeded");
213 } catch (IllegalAccessException expected) {
214 }
215
216 // Virtual lookup on a private method with a context that *does* have sufficient
217 // privileges.
218 MethodHandle mh = BarImpl.lookup.findVirtual(
219 BarImpl.class, "privateMethod", MethodType.methodType(String.class));
220 String str = (String) mh.invoke(new BarImpl());
221 if (!"privateMethod".equals(str)) {
222 System.out.println("Unexpected return value for BarImpl#privateMethod: " + str);
223 }
224
225 // Find virtual must find interface methods defined by interfaces implemented
226 // by the class.
227 mh = MethodHandles.lookup().findVirtual(BarImpl.class, "foo",
228 MethodType.methodType(String.class));
229 str = (String) mh.invoke(new BarImpl());
230 if (!"foo".equals(str)) {
231 System.out.println("Unexpected return value for BarImpl#foo: " + str);
232 }
233
234 // .. and their super-interfaces.
235 mh = MethodHandles.lookup().findVirtual(BarImpl.class, "bar",
236 MethodType.methodType(String.class));
237 str = (String) mh.invoke(new BarImpl());
238 if (!"bar".equals(str)) {
239 System.out.println("Unexpected return value for BarImpl#bar: " + str);
240 }
241
242 // TODO(narayan): Fix this case, we're using the wrong ArtMethod for the
243 // invoke resulting in a failing check in the interpreter.
244 //
245 // mh = MethodHandles.lookup().findVirtual(Bar.class, "bar",
246 // MethodType.methodType(String.class));
247 // str = (String) mh.invoke(new BarImpl());
248 // if (!"bar".equals(str)) {
249 // System.out.println("Unexpected return value for BarImpl#bar: " + str);
250 // }
251
252 // We should also be able to lookup public / protected / package methods in
253 // the super class, given sufficient access privileges.
254 mh = MethodHandles.lookup().findVirtual(BarImpl.class, "superPublicMethod",
255 MethodType.methodType(String.class));
256 str = (String) mh.invoke(new BarImpl());
257 if (!"superPublicMethod".equals(str)) {
258 System.out.println("Unexpected return value for BarImpl#superPublicMethod: " + str);
259 }
260
261 mh = MethodHandles.lookup().findVirtual(BarImpl.class, "superProtectedMethod",
262 MethodType.methodType(String.class));
263 str = (String) mh.invoke(new BarImpl());
264 if (!"superProtectedMethod".equals(str)) {
265 System.out.println("Unexpected return value for BarImpl#superProtectedMethod: " + str);
266 }
267
268 mh = MethodHandles.lookup().findVirtual(BarImpl.class, "superPackageMethod",
269 MethodType.methodType(String.class));
270 str = (String) mh.invoke(new BarImpl());
271 if (!"superPackageMethod".equals(str)) {
272 System.out.println("Unexpected return value for BarImpl#superPackageMethod: " + str);
273 }
274 }
Narayan Kamathe5eb5742016-11-02 14:16:27 +0000275
276 static class UnreflectTester {
277 public String publicField;
278 private String privateField;
279
280 public static String publicStaticField = "publicStaticValue";
281 private static String privateStaticField = "privateStaticValue";
282
283 private UnreflectTester(String val) {
284 publicField = val;
285 privateField = val;
286 }
287
288 // NOTE: The boolean constructor argument only exists to give this a
289 // different signature.
290 public UnreflectTester(String val, boolean unused) {
291 this(val);
292 }
293
294 private static String privateStaticMethod() {
295 return "privateStaticMethod";
296 }
297
298 private String privateMethod() {
299 return "privateMethod";
300 }
301
302 public static String publicStaticMethod() {
303 return "publicStaticMethod";
304 }
305
306 public String publicMethod() {
307 return "publicMethod";
308 }
309 }
310
311 public static void testUnreflects() throws Throwable {
312 UnreflectTester instance = new UnreflectTester("unused");
313 Method publicMethod = UnreflectTester.class.getMethod("publicMethod");
314
315 MethodHandle mh = MethodHandles.lookup().unreflect(publicMethod);
316 assertEquals("publicMethod", (String) mh.invoke(instance));
317 assertEquals("publicMethod", (String) mh.invokeExact(instance));
318
319 Method publicStaticMethod = UnreflectTester.class.getMethod("publicStaticMethod");
320 mh = MethodHandles.lookup().unreflect(publicStaticMethod);
321 assertEquals("publicStaticMethod", (String) mh.invoke());
322 assertEquals("publicStaticMethod", (String) mh.invokeExact());
323
324 Method privateMethod = UnreflectTester.class.getDeclaredMethod("privateMethod");
325 try {
326 mh = MethodHandles.lookup().unreflect(privateMethod);
327 fail();
328 } catch (IllegalAccessException expected) {}
329
330 privateMethod.setAccessible(true);
331 mh = MethodHandles.lookup().unreflect(privateMethod);
332 assertEquals("privateMethod", (String) mh.invoke(instance));
333 assertEquals("privateMethod", (String) mh.invokeExact(instance));
334
335 Method privateStaticMethod = UnreflectTester.class.getDeclaredMethod("privateStaticMethod");
336 try {
337 mh = MethodHandles.lookup().unreflect(privateStaticMethod);
338 fail();
339 } catch (IllegalAccessException expected) {}
340
341 privateStaticMethod.setAccessible(true);
342 mh = MethodHandles.lookup().unreflect(privateStaticMethod);
343 assertEquals("privateStaticMethod", (String) mh.invoke());
344 assertEquals("privateStaticMethod", (String) mh.invokeExact());
345
346 Constructor privateConstructor = UnreflectTester.class.getDeclaredConstructor(String.class);
347 try {
348 mh = MethodHandles.lookup().unreflectConstructor(privateConstructor);
349 fail();
350 } catch (IllegalAccessException expected) {}
351
352 privateConstructor.setAccessible(true);
353 mh = MethodHandles.lookup().unreflectConstructor(privateConstructor);
Orion Hodson0d781e62016-11-04 11:09:53 +0000354 instance = (UnreflectTester) mh.invokeExact("abc");
355 assertEquals("abc", instance.publicField);
356 instance = (UnreflectTester) mh.invoke("def");
357 assertEquals("def", instance.publicField);
Narayan Kamathe5eb5742016-11-02 14:16:27 +0000358 Constructor publicConstructor = UnreflectTester.class.getConstructor(String.class,
359 boolean.class);
360 mh = MethodHandles.lookup().unreflectConstructor(publicConstructor);
Orion Hodson0d781e62016-11-04 11:09:53 +0000361 instance = (UnreflectTester) mh.invokeExact("abc", false);
362 assertEquals("abc", instance.publicField);
363 instance = (UnreflectTester) mh.invoke("def", true);
364 assertEquals("def", instance.publicField);
Narayan Kamathe5eb5742016-11-02 14:16:27 +0000365
366 // TODO(narayan): Non exact invokes for field sets/gets are not implemented yet.
367 //
368 // assertEquals("instanceValue", (String) mh.invoke(new UnreflectTester("instanceValue")));
369 Field publicField = UnreflectTester.class.getField("publicField");
370 mh = MethodHandles.lookup().unreflectGetter(publicField);
371 instance = new UnreflectTester("instanceValue");
372 assertEquals("instanceValue", (String) mh.invokeExact(instance));
373
374 mh = MethodHandles.lookup().unreflectSetter(publicField);
375 instance = new UnreflectTester("instanceValue");
376 mh.invokeExact(instance, "updatedInstanceValue");
377 assertEquals("updatedInstanceValue", instance.publicField);
378
379 Field publicStaticField = UnreflectTester.class.getField("publicStaticField");
380 mh = MethodHandles.lookup().unreflectGetter(publicStaticField);
381 UnreflectTester.publicStaticField = "updatedStaticValue";
382 assertEquals("updatedStaticValue", (String) mh.invokeExact());
383
384 mh = MethodHandles.lookup().unreflectSetter(publicStaticField);
385 UnreflectTester.publicStaticField = "updatedStaticValue";
386 mh.invokeExact("updatedStaticValue2");
387 assertEquals("updatedStaticValue2", UnreflectTester.publicStaticField);
388
389 Field privateField = UnreflectTester.class.getDeclaredField("privateField");
390 try {
391 mh = MethodHandles.lookup().unreflectGetter(privateField);
392 fail();
393 } catch (IllegalAccessException expected) {
394 }
395 try {
396 mh = MethodHandles.lookup().unreflectSetter(privateField);
397 fail();
398 } catch (IllegalAccessException expected) {
399 }
400
401 privateField.setAccessible(true);
402
403 mh = MethodHandles.lookup().unreflectGetter(privateField);
404 instance = new UnreflectTester("instanceValue");
405 assertEquals("instanceValue", (String) mh.invokeExact(instance));
406
407 mh = MethodHandles.lookup().unreflectSetter(privateField);
408 instance = new UnreflectTester("instanceValue");
409 mh.invokeExact(instance, "updatedInstanceValue");
410 assertEquals("updatedInstanceValue", instance.privateField);
411
412 Field privateStaticField = UnreflectTester.class.getDeclaredField("privateStaticField");
413 try {
414 mh = MethodHandles.lookup().unreflectGetter(privateStaticField);
415 fail();
416 } catch (IllegalAccessException expected) {
417 }
418 try {
419 mh = MethodHandles.lookup().unreflectSetter(privateStaticField);
420 fail();
421 } catch (IllegalAccessException expected) {
422 }
423
424 privateStaticField.setAccessible(true);
425 mh = MethodHandles.lookup().unreflectGetter(privateStaticField);
426 privateStaticField.set(null, "updatedStaticValue");
427 assertEquals("updatedStaticValue", (String) mh.invokeExact());
428
429 mh = MethodHandles.lookup().unreflectSetter(privateStaticField);
430 privateStaticField.set(null, "updatedStaticValue");
431 mh.invokeExact("updatedStaticValue2");
432 assertEquals("updatedStaticValue2", (String) privateStaticField.get(null));
433 }
434
Narayan Kamath0a8485e2016-11-02 18:47:11 +0000435 // This method only exists to fool Jack's handling of types. See b/32536744.
436 public static CharSequence getSequence() {
437 return "foo";
438 }
439
440 public static void testAsType() throws Throwable {
441 // The type of this handle is (String, String)String.
442 MethodHandle mh = MethodHandles.lookup().findVirtual(String.class,
443 "concat", MethodType.methodType(String.class, String.class));
444
445 // Change it to (CharSequence, String)Object.
446 MethodHandle asType = mh.asType(
447 MethodType.methodType(Object.class, CharSequence.class, String.class));
448
449 Object obj = asType.invokeExact((CharSequence) getSequence(), "bar");
450 assertEquals("foobar", (String) obj);
451
452 // Should fail due to a wrong return type.
453 try {
454 String str = (String) asType.invokeExact((CharSequence) getSequence(), "bar");
455 fail();
456 } catch (WrongMethodTypeException expected) {
457 }
458
459 // Should fail due to a wrong argument type (String instead of Charsequence).
460 try {
461 String str = (String) asType.invokeExact("baz", "bar");
462 fail();
463 } catch (WrongMethodTypeException expected) {
464 }
465
466 // Calls to asType should fail if the types are not convertible.
467 //
468 // Bad return type conversion.
469 try {
470 mh.asType(MethodType.methodType(int.class, String.class, String.class));
471 fail();
472 } catch (WrongMethodTypeException expected) {
473 }
474
475 // Bad argument conversion.
476 try {
477 mh.asType(MethodType.methodType(String.class, int.class, String.class));
478 fail();
479 } catch (WrongMethodTypeException expected) {
480 }
481 }
482
Narayan Kamathe5eb5742016-11-02 14:16:27 +0000483 public static void assertEquals(String s1, String s2) {
484 if (s1 == s2) {
485 return;
486 }
487
488 if (s1 != null && s2 != null && s1.equals(s2)) {
489 return;
490 }
491
492 throw new AssertionError("assertEquals s1: " + s1 + ", s2: " + s2);
493 }
494
495 public static void fail() {
496 System.out.println("fail");
497 Thread.dumpStack();
498 }
Orion Hodson0d781e62016-11-04 11:09:53 +0000499
500 public static void fail(String message) {
501 System.out.println("fail: " + message);
502 Thread.dumpStack();
503 }
504
505 public static void testConstructors() throws Throwable {
506 MethodHandle mh =
507 MethodHandles.lookup().findConstructor(Float.class,
508 MethodType.methodType(void.class,
509 float.class));
510 Float value = (Float) mh.invokeExact(0.33f);
511 if (value.floatValue() != 0.33f) {
512 fail("Unexpected float value from invokeExact " + value.floatValue());
513 }
514
515 value = (Float) mh.invoke(3.34f);
516 if (value.floatValue() != 3.34f) {
517 fail("Unexpected float value from invoke " + value.floatValue());
518 }
519
520 mh = MethodHandles.lookup().findConstructor(Double.class,
521 MethodType.methodType(void.class, String.class));
522 Double d = (Double) mh.invoke("8.45e3");
523 if (d.doubleValue() != 8.45e3) {
524 fail("Unexpected double value from Double(String) " + value.doubleValue());
525 }
526
527 mh = MethodHandles.lookup().findConstructor(Double.class,
528 MethodType.methodType(void.class, double.class));
529 d = (Double) mh.invoke(8.45e3);
530 if (d.doubleValue() != 8.45e3) {
531 fail("Unexpected double value from Double(double) " + value.doubleValue());
532 }
533
534 // Primitive type
535 try {
536 mh = MethodHandles.lookup().findConstructor(int.class, MethodType.methodType(void.class));
537 fail("Unexpected lookup success for primitive constructor");
538 } catch (NoSuchMethodException e) {}
539
540 // Interface
541 try {
542 mh = MethodHandles.lookup().findConstructor(Readable.class,
543 MethodType.methodType(void.class));
544 fail("Unexpected lookup success for interface constructor");
545 } catch (NoSuchMethodException e) {}
546
547 // Abstract
548 mh = MethodHandles.lookup().findConstructor(Process.class, MethodType.methodType(void.class));
549 try {
550 mh.invoke();
551 fail("Unexpected ability to instantiate an abstract class");
552 } catch (InstantiationException e) {}
553
554 // Non-existent
555 try {
556 MethodHandle bad = MethodHandles.lookup().findConstructor(
557 String.class, MethodType.methodType(String.class, Float.class));
558 fail("Unexpected success for non-existent constructor");
559 } catch (NoSuchMethodException e) {}
560
561 // Non-void constructor search. (I)I instead of (I)V.
562 try {
563 MethodHandle foo = MethodHandles.lookup().findConstructor(
564 Integer.class, MethodType.methodType(Integer.class, Integer.class));
565 fail("Unexpected success for non-void type for findConstructor");
566 } catch (NoSuchMethodException e) {}
567 }
568
569 public static void testStringConstructors() throws Throwable {
570 final String testPattern = "The system as we know it is broken";
571
572 // String()
573 MethodHandle mh = MethodHandles.lookup().findConstructor(
574 String.class, MethodType.methodType(void.class));
575 String s = (String) mh.invokeExact();
576 if (!s.equals("")) {
577 fail("Unexpected empty string constructor result: '" + s + "'");
578 }
579
580 // String(String)
581 mh = MethodHandles.lookup().findConstructor(
582 String.class, MethodType.methodType(void.class, String.class));
583 s = (String) mh.invokeExact(testPattern);
584 if (!s.equals(testPattern)) {
585 fail("Unexpected string constructor result: '" + s + "'");
586 }
587
588 // String(char[])
589 mh = MethodHandles.lookup().findConstructor(
590 String.class, MethodType.methodType(void.class, char[].class));
591 s = (String) mh.invokeExact(testPattern.toCharArray());
592 if (!s.equals(testPattern)) {
593 fail("Unexpected string constructor result: '" + s + "'");
594 }
595
596 // String(char[], int, int)
597 mh = MethodHandles.lookup().findConstructor(
598 String.class, MethodType.methodType(void.class, char[].class, int.class, int.class));
599 s = (String) mh.invokeExact(new char [] { 'a', 'b', 'c', 'd', 'e'}, 2, 3);
600 if (!s.equals("cde")) {
601 fail("Unexpected string constructor result: '" + s + "'");
602 }
603
604 // String(int[] codePoints, int offset, int count)
605 StringBuffer sb = new StringBuffer(testPattern);
606 int[] codePoints = new int[sb.codePointCount(0, sb.length())];
607 for (int i = 0; i < sb.length(); ++i) {
608 codePoints[i] = sb.codePointAt(i);
609 }
610 mh = MethodHandles.lookup().findConstructor(
611 String.class, MethodType.methodType(void.class, int[].class, int.class, int.class));
612 s = (String) mh.invokeExact(codePoints, 0, codePoints.length);
613 if (!s.equals(testPattern)) {
614 fail("Unexpected string constructor result: '" + s + "'");
615 }
616
617 // String(byte ascii[], int hibyte, int offset, int count)
618 byte [] ascii = testPattern.getBytes(StandardCharsets.US_ASCII);
619 mh = MethodHandles.lookup().findConstructor(
620 String.class, MethodType.methodType(void.class, byte[].class, int.class, int.class));
621 s = (String) mh.invokeExact(ascii, 0, ascii.length);
622 if (!s.equals(testPattern)) {
623 fail("Unexpected string constructor result: '" + s + "'");
624 }
625
626 // String(byte bytes[], int offset, int length, String charsetName)
627 mh = MethodHandles.lookup().findConstructor(
628 String.class,
629 MethodType.methodType(void.class, byte[].class, int.class, int.class, String.class));
630 s = (String) mh.invokeExact(ascii, 0, 5, StandardCharsets.US_ASCII.name());
631 if (!s.equals(testPattern.substring(0, 5))) {
632 fail("Unexpected string constructor result: '" + s + "'");
633 }
634
635 // String(byte bytes[], int offset, int length, Charset charset)
636 mh = MethodHandles.lookup().findConstructor(
637 String.class,
638 MethodType.methodType(void.class, byte[].class, int.class, int.class, Charset.class));
639 s = (String) mh.invokeExact(ascii, 0, 5, StandardCharsets.US_ASCII);
640 if (!s.equals(testPattern.substring(0, 5))) {
641 fail("Unexpected string constructor result: '" + s + "'");
642 }
643
644 // String(byte bytes[], String charsetName)
645 mh = MethodHandles.lookup().findConstructor(
646 String.class,
647 MethodType.methodType(void.class, byte[].class, String.class));
648 s = (String) mh.invokeExact(ascii, StandardCharsets.US_ASCII.name());
649 if (!s.equals(testPattern)) {
650 fail("Unexpected string constructor result: '" + s + "'");
651 }
652
653 // String(byte bytes[], Charset charset)
654 mh = MethodHandles.lookup().findConstructor(
655 String.class, MethodType.methodType(void.class, byte[].class, Charset.class));
656 s = (String) mh.invokeExact(ascii, StandardCharsets.US_ASCII);
657 if (!s.equals(testPattern)) {
658 fail("Unexpected string constructor result: '" + s + "'");
659 }
660
661 // String(byte bytes[], int offset, int length)
662 mh = MethodHandles.lookup().findConstructor(
663 String.class, MethodType.methodType(void.class, byte[].class, int.class, int.class));
664 s = (String) mh.invokeExact(ascii, 1, ascii.length - 2);
665 s = testPattern.charAt(0) + s + testPattern.charAt(testPattern.length() - 1);
666 if (!s.equals(testPattern)) {
667 fail("Unexpected string constructor result: '" + s + "'");
668 }
669
670 // String(byte bytes[])
671 mh = MethodHandles.lookup().findConstructor(
672 String.class, MethodType.methodType(void.class, byte[].class));
673 s = (String) mh.invokeExact(ascii);
674 if (!s.equals(testPattern)) {
675 fail("Unexpected string constructor result: '" + s + "'");
676 }
677
678 // String(StringBuffer buffer)
679 mh = MethodHandles.lookup().findConstructor(
680 String.class, MethodType.methodType(void.class, StringBuffer.class));
681 s = (String) mh.invokeExact(sb);
682 if (!s.equals(testPattern)) {
683 fail("Unexpected string constructor result: '" + s + "'");
684 }
685
686 System.out.println("String constructors done.");
687 }
Narayan Kamath9bdaeeb2016-10-20 10:57:45 +0100688}
689
690