diff options
author | 2016-11-01 09:40:23 +0000 | |
---|---|---|
committer | 2016-11-02 11:09:26 +0000 | |
commit | 96120f4be0a03b8637d247848e9901093ceda3a5 (patch) | |
tree | 10afe2faa99acf11c1e9f12b2e29cd11537d4c3a | |
parent | 0fe4df18f61c7a764bc1c5eea50b19d6b1ff9b1c (diff) |
MethodHandles: Add tests for transforms in change 598d43d0dec5925c77
Test: make test-art-host
Bug: 30550796
Change-Id: I41e4c7f9398e5120b65577aa559c63fcc1d25508
-rw-r--r-- | test/957-methodhandle-transforms/expected.txt | 51 | ||||
-rw-r--r-- | test/957-methodhandle-transforms/src/Main.java | 313 | ||||
-rwxr-xr-x | test/958-methodhandle-emulated-stackframe/build | 25 | ||||
-rw-r--r-- | test/958-methodhandle-emulated-stackframe/expected.txt | 32 | ||||
-rw-r--r-- | test/958-methodhandle-emulated-stackframe/info.txt | 5 | ||||
-rwxr-xr-x | test/958-methodhandle-emulated-stackframe/run | 20 | ||||
-rw-r--r-- | test/958-methodhandle-emulated-stackframe/src/Main.java | 175 |
7 files changed, 453 insertions, 168 deletions
diff --git a/test/957-methodhandle-transforms/expected.txt b/test/957-methodhandle-transforms/expected.txt index 73a34bc41b..fc4fdd6070 100644 --- a/test/957-methodhandle-transforms/expected.txt +++ b/test/957-methodhandle-transforms/expected.txt @@ -1,35 +1,16 @@ ---- --- testDelegation ---- -boolean: false -char: h -short: 56 -int: 72 -long: 2147483689 -float: 0.56 -double: 100.0 -String: hello -Object: goodbye -boolean: false -char: h -short: 56 -int: 72 -long: 73 -float: 0.56 -double: 100.0 -String: hello -Object: goodbye -true -true -a -a -42 -42 -43 -43 -43.0 -43.0 -43.0 -43.0 -plank -plank +Message: foo, Message2: 42 +Message: foo, Message2: 42 +Message: foo, Message2: 42 +Message: foo, Message2: 42 +Message: foo, Message2: 42 +Message: foo, Message2: 42 +Target: Arg1: foo, Arg2: 42 +Target: Arg1: foo, Arg2: 42 +Handler: java.lang.IllegalArgumentException: exceptionMessage, Arg1: foo, Arg2: 42, ExMsg: exceptionMessage +Handler: java.lang.IllegalArgumentException: exceptionMessage, Arg1: foo, Arg2: 42, ExMsg: exceptionMessage +Handler: java.lang.IllegalArgumentException: exceptionMessage, Arg1: foo +Handler: java.lang.IllegalArgumentException: exceptionMessage, Arg1: foo +target: target, 42, 56 +target: target, 42, 56 +fallback: fallback, 42, 56 +target: target, 42, 56 diff --git a/test/957-methodhandle-transforms/src/Main.java b/test/957-methodhandle-transforms/src/Main.java index e9d313b874..4a27086924 100644 --- a/test/957-methodhandle-transforms/src/Main.java +++ b/test/957-methodhandle-transforms/src/Main.java @@ -19,182 +19,229 @@ import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles.Lookup; import java.lang.invoke.MethodType; import java.lang.invoke.WrongMethodTypeException; -import java.lang.invoke.Transformers.Transformer; - -import dalvik.system.EmulatedStackFrame; public class Main { - - public static void testDelegate_allTypes(boolean z, char a, short b, int c, long d, - float e, double f, String g, Object h) { - System.out.println("boolean: " + z); - System.out.println("char: " + a); - System.out.println("short: " + b); - System.out.println("int: " + c); - System.out.println("long: " + d); - System.out.println("float: " + e); - System.out.println("double: " + f); - System.out.println("String: " + g); - System.out.println("Object: " + h); - } - - public static boolean testDelegate_returnBoolean() { - return true; - } - - public static char testDelegate_returnChar() { - return 'a'; - } - - public static int testDelegate_returnInt() { - return 42; + public static void main(String[] args) throws Throwable { + testThrowException(); + testDropArguments(); + testCatchException(); + testGuardWithTest(); } - public static long testDelegate_returnLong() { - return 43; - } + public static void testThrowException() throws Throwable { + MethodHandle handle = MethodHandles.throwException(String.class, + IllegalArgumentException.class); - public static float testDelegate_returnFloat() { - return 43.0f; - } + if (handle.type().returnType() != String.class) { + System.out.println("Unexpected return type for handle: " + handle + + " [ " + handle.type() + "]"); + } - public static double testDelegate_returnDouble() { - return 43.0; + final IllegalArgumentException iae = new IllegalArgumentException("boo!"); + try { + handle.invoke(iae); + System.out.println("Expected an exception of type: java.lang.IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + if (expected != iae) { + System.out.println("Wrong exception: expected " + iae + " but was " + expected); + } + } } - public static String testDelegate_returnString() { - return "plank"; + public static void dropArguments_delegate(String message, long message2) { + System.out.println("Message: " + message + ", Message2: " + message2); } - public static class DelegatingTransformer extends Transformer { - private final MethodHandle delegate; + public static void testDropArguments() throws Throwable { + MethodHandle delegate = MethodHandles.lookup().findStatic(Main.class, + "dropArguments_delegate", + MethodType.methodType(void.class, new Class<?>[] { String.class, long.class })); - public DelegatingTransformer(MethodHandle delegate) { - super(delegate.type()); - this.delegate = delegate; - } + MethodHandle transform = MethodHandles.dropArguments(delegate, 0, int.class, Object.class); - @Override - public void transform(EmulatedStackFrame stackFrame) throws Throwable { - delegate.invoke(stackFrame); + // The transformer will accept two additional arguments at position zero. + try { + transform.invokeExact("foo", 42l); + fail(); + } catch (WrongMethodTypeException expected) { } - } - - public static void main(String[] args) throws Throwable { - testThrowException(); - - testDelegation(); - } - public static void testDelegation() throws Throwable { - System.out.println("---"); - System.out.println("-- testDelegation"); - System.out.println("---"); + transform.invokeExact(45, new Object(), "foo", 42l); + transform.invoke(45, new Object(), "foo", 42l); - MethodHandle specialFunctionHandle = MethodHandles.lookup().findStatic( - Main.class, "testDelegate_allTypes", MethodType.methodType(void.class, - new Class<?>[] { boolean.class, char.class, short.class, int.class, long.class, - float.class, double.class, String.class, Object.class })); + // Additional arguments at position 1. + transform = MethodHandles.dropArguments(delegate, 1, int.class, Object.class); + transform.invokeExact("foo", 45, new Object(), 42l); + transform.invoke("foo", 45, new Object(), 42l); - DelegatingTransformer delegate = new DelegatingTransformer(specialFunctionHandle); + // Additional arguments at position 2. + transform = MethodHandles.dropArguments(delegate, 2, int.class, Object.class); + transform.invokeExact("foo", 42l, 45, new Object()); + transform.invoke("foo", 42l, 45, new Object()); - // Test an exact invoke. - // - // Note that the shorter form below doesn't work and must be - // investigated on the jack side : b/32536744 - // - // delegate.invokeExact(false, 'h', (short) 56, 72, Integer.MAX_VALUE + 42l, - // 0.56f, 100.0d, "hello", (Object) "goodbye"); + // Note that we still perform argument conversions even for the arguments that + // are subsequently dropped. + try { + transform.invoke("foo", 42l, 45l, new Object()); + fail(); + } catch (WrongMethodTypeException expected) { + } catch (IllegalArgumentException expected) { + // TODO(narayan): We currently throw the wrong type of exception here, + // it's IAE and should be WMTE instead. + } - Object obj = "goodbye"; - delegate.invokeExact(false, 'h', (short) 56, 72, Integer.MAX_VALUE + 42l, - 0.56f, 100.0d, "hello", obj); + // Invalid argument location, should not be allowed. + try { + MethodHandles.dropArguments(delegate, -1, int.class, Object.class); + fail(); + } catch (IllegalArgumentException expected) { + } - // Test a non exact invoke with one int -> long conversion and a float -> double - // conversion. - delegate.invoke(false, 'h', (short) 56, 72, 73, - 0.56f, 100.0f, "hello", "goodbye"); + // Invalid argument location, should not be allowed. + try { + MethodHandles.dropArguments(delegate, 3, int.class, Object.class); + fail(); + } catch (IllegalArgumentException expected) { + } - // Should throw a WrongMethodTypeException if the types don't align. try { - delegate.invoke(false); - throw new AssertionError("Call to invoke unexpectedly succeeded"); - } catch (WrongMethodTypeException expected) { + MethodHandles.dropArguments(delegate, 1, void.class); + fail(); + } catch (IllegalArgumentException expected) { } + } - // Test return values. + public static String testCatchException_target(String arg1, long arg2, String exceptionMessage) + throws Throwable { + if (exceptionMessage != null) { + throw new IllegalArgumentException(exceptionMessage); + } - // boolean. - MethodHandle returner = MethodHandles.lookup().findStatic( - Main.class, "testDelegate_returnBoolean", MethodType.methodType(boolean.class)); - delegate = new DelegatingTransformer(returner); + System.out.println("Target: Arg1: " + arg1 + ", Arg2: " + arg2); + return "target"; + } - System.out.println((boolean) delegate.invoke()); - System.out.println((boolean) delegate.invokeExact()); + public static String testCatchException_handler(IllegalArgumentException iae, String arg1, long arg2, + String exMsg) { + System.out.println("Handler: " + iae + ", Arg1: " + arg1 + ", Arg2: " + arg2 + ", ExMsg: " + exMsg); + return "handler1"; + } - // char. - returner = MethodHandles.lookup().findStatic( - Main.class, "testDelegate_returnChar", MethodType.methodType(char.class)); - delegate = new DelegatingTransformer(returner); + public static String testCatchException_handler2(IllegalArgumentException iae, String arg1) { + System.out.println("Handler: " + iae + ", Arg1: " + arg1); + return "handler2"; + } - System.out.println((char) delegate.invoke()); - System.out.println((char) delegate.invokeExact()); + public static void testCatchException() throws Throwable { + MethodHandle target = MethodHandles.lookup().findStatic(Main.class, + "testCatchException_target", + MethodType.methodType(String.class, new Class<?>[] { String.class, long.class, String.class })); + + MethodHandle handler = MethodHandles.lookup().findStatic(Main.class, + "testCatchException_handler", + MethodType.methodType(String.class, new Class<?>[] { IllegalArgumentException.class, + String.class, long.class, String.class })); + + MethodHandle adapter = MethodHandles.catchException(target, IllegalArgumentException.class, + handler); + + String returnVal = null; + + // These two should end up calling the target always. We're passing a null exception + // message here, which means the target will not throw. + returnVal = (String) adapter.invoke("foo", 42, null); + assertEquals("target", returnVal); + returnVal = (String) adapter.invokeExact("foo", 42l, (String) null); + assertEquals("target", returnVal); + + // We're passing a non-null exception message here, which means the target will throw, + // which in turn means that the handler must be called for the next two invokes. + returnVal = (String) adapter.invoke("foo", 42, "exceptionMessage"); + assertEquals("handler1", returnVal); + returnVal = (String) adapter.invokeExact("foo", 42l, "exceptionMessage"); + assertEquals("handler1", returnVal); + + handler = MethodHandles.lookup().findStatic(Main.class, + "testCatchException_handler2", + MethodType.methodType(String.class, new Class<?>[] { IllegalArgumentException.class, + String.class })); + adapter = MethodHandles.catchException(target, IllegalArgumentException.class, handler); + + returnVal = (String) adapter.invoke("foo", 42, "exceptionMessage"); + assertEquals("handler2", returnVal); + returnVal = (String) adapter.invokeExact("foo", 42l, "exceptionMessage"); + assertEquals("handler2", returnVal); + + // Test that the type of the invoke doesn't matter. Here we call + // IllegalArgumentException.toString() on the exception that was thrown by + // the target. + handler = MethodHandles.lookup().findVirtual(IllegalArgumentException.class, + "toString", MethodType.methodType(String.class)); + adapter = MethodHandles.catchException(target, IllegalArgumentException.class, handler); + + returnVal = (String) adapter.invoke("foo", 42, "exceptionMessage"); + assertEquals("java.lang.IllegalArgumentException: exceptionMessage", returnVal); + returnVal = (String) adapter.invokeExact("foo", 42l, "exceptionMessage2"); + assertEquals("java.lang.IllegalArgumentException: exceptionMessage2", returnVal); + } - // int. - returner = MethodHandles.lookup().findStatic( - Main.class, "testDelegate_returnInt", MethodType.methodType(int.class)); - delegate = new DelegatingTransformer(returner); + public static boolean testGuardWithTest_test(String arg1, long arg2) { + return "target".equals(arg1) && 42 == arg2; + } - System.out.println((int) delegate.invoke()); - System.out.println((int) delegate.invokeExact()); + public static String testGuardWithTest_target(String arg1, long arg2, int arg3) { + System.out.println("target: " + arg1 + ", " + arg2 + ", " + arg3); + return "target"; + } - // long. - returner = MethodHandles.lookup().findStatic( - Main.class, "testDelegate_returnLong", MethodType.methodType(long.class)); - delegate = new DelegatingTransformer(returner); + public static String testGuardWithTest_fallback(String arg1, long arg2, int arg3) { + System.out.println("fallback: " + arg1 + ", " + arg2 + ", " + arg3); + return "fallback"; + } - System.out.println((long) delegate.invoke()); - System.out.println((long) delegate.invokeExact()); + public static void testGuardWithTest() throws Throwable { + MethodHandle test = MethodHandles.lookup().findStatic(Main.class, + "testGuardWithTest_test", + MethodType.methodType(boolean.class, new Class<?>[] { String.class, long.class })); - // float. - returner = MethodHandles.lookup().findStatic( - Main.class, "testDelegate_returnFloat", MethodType.methodType(float.class)); - delegate = new DelegatingTransformer(returner); + final MethodType type = MethodType.methodType(String.class, + new Class<?>[] { String.class, long.class, int.class }); - System.out.println((float) delegate.invoke()); - System.out.println((float) delegate.invokeExact()); + final MethodHandle target = MethodHandles.lookup().findStatic(Main.class, + "testGuardWithTest_target", type); + final MethodHandle fallback = MethodHandles.lookup().findStatic(Main.class, + "testGuardWithTest_fallback", type); - // double. - returner = MethodHandles.lookup().findStatic( - Main.class, "testDelegate_returnDouble", MethodType.methodType(double.class)); - delegate = new DelegatingTransformer(returner); + MethodHandle adapter = MethodHandles.guardWithTest(test, target, fallback); - System.out.println((double) delegate.invoke()); - System.out.println((double) delegate.invokeExact()); + String returnVal = null; - // references. - returner = MethodHandles.lookup().findStatic( - Main.class, "testDelegate_returnString", MethodType.methodType(String.class)); - delegate = new DelegatingTransformer(returner); + returnVal = (String) adapter.invoke("target", 42, 56); + assertEquals("target", returnVal); + returnVal = (String) adapter.invokeExact("target", 42l, 56); + assertEquals("target", returnVal); - System.out.println((String) delegate.invoke()); - System.out.println((String) delegate.invokeExact()); + returnVal = (String) adapter.invoke("fallback", 42l, 56); + assertEquals("fallback", returnVal); + returnVal = (String) adapter.invokeExact("target", 42l, 56); + assertEquals("target", returnVal); } - public static void testThrowException() throws Throwable { - MethodHandle handle = MethodHandles.throwException(String.class, - IllegalArgumentException.class); + public static void fail() { + System.out.println("FAIL"); + Thread.dumpStack(); + } - if (handle.type().returnType() != String.class) { - System.out.println("Unexpected return type for handle: " + handle + - " [ " + handle.type() + "]"); + public static void assertEquals(String s1, String s2) { + if (s1 == s2) { + return; } - try { - handle.invoke(); - System.out.println("Expected an exception of type: java.lang.IllegalArgumentException"); - } catch (IllegalArgumentException expected) { + if (s1 != null && s2 != null && s1.equals(s2)) { + return; } + + throw new AssertionError("assertEquals s1: " + s1 + ", s2: " + s2); } } diff --git a/test/958-methodhandle-emulated-stackframe/build b/test/958-methodhandle-emulated-stackframe/build new file mode 100755 index 0000000000..a423ca6b4e --- /dev/null +++ b/test/958-methodhandle-emulated-stackframe/build @@ -0,0 +1,25 @@ +#!/bin/bash +# +# Copyright 2016 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# make us exit on a failure +set -e + +if [[ $@ != *"--jvm"* ]]; then + # Don't do anything with jvm. + export USE_JACK=true +fi + +./default-build "$@" --experimental method-handles diff --git a/test/958-methodhandle-emulated-stackframe/expected.txt b/test/958-methodhandle-emulated-stackframe/expected.txt new file mode 100644 index 0000000000..5f3825962d --- /dev/null +++ b/test/958-methodhandle-emulated-stackframe/expected.txt @@ -0,0 +1,32 @@ +boolean: false +char: h +short: 56 +int: 72 +long: 2147483689 +float: 0.56 +double: 100.0 +String: hello +Object: goodbye +boolean: false +char: h +short: 56 +int: 72 +long: 73 +float: 0.56 +double: 100.0 +String: hello +Object: goodbye +true +true +a +a +42 +42 +43 +43 +43.0 +43.0 +43.0 +43.0 +plank +plank diff --git a/test/958-methodhandle-emulated-stackframe/info.txt b/test/958-methodhandle-emulated-stackframe/info.txt new file mode 100644 index 0000000000..bec2324e76 --- /dev/null +++ b/test/958-methodhandle-emulated-stackframe/info.txt @@ -0,0 +1,5 @@ +Tests for dalvik.system.EmulatedStackFrame, which is used to implement +MethodHandle transformations. This is a separate test because it tests +an implementation detail and hence cannot be used with --mode=jvm. + +NOTE: needs to run under ART or a Java 8 Language runtime and compiler. diff --git a/test/958-methodhandle-emulated-stackframe/run b/test/958-methodhandle-emulated-stackframe/run new file mode 100755 index 0000000000..a9f182288c --- /dev/null +++ b/test/958-methodhandle-emulated-stackframe/run @@ -0,0 +1,20 @@ +#!/bin/bash +# +# Copyright 2016 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# make us exit on a failure +set -e + +./default-run "$@" --experimental method-handles diff --git a/test/958-methodhandle-emulated-stackframe/src/Main.java b/test/958-methodhandle-emulated-stackframe/src/Main.java new file mode 100644 index 0000000000..f739d47d08 --- /dev/null +++ b/test/958-methodhandle-emulated-stackframe/src/Main.java @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodHandles.Lookup; +import java.lang.invoke.MethodType; +import java.lang.invoke.WrongMethodTypeException; +import java.lang.invoke.Transformers.Transformer; + +import dalvik.system.EmulatedStackFrame; + +public class Main { + + public static void testDelegate_allTypes(boolean z, char a, short b, int c, long d, + float e, double f, String g, Object h) { + System.out.println("boolean: " + z); + System.out.println("char: " + a); + System.out.println("short: " + b); + System.out.println("int: " + c); + System.out.println("long: " + d); + System.out.println("float: " + e); + System.out.println("double: " + f); + System.out.println("String: " + g); + System.out.println("Object: " + h); + } + + public static boolean testDelegate_returnBoolean() { + return true; + } + + public static char testDelegate_returnChar() { + return 'a'; + } + + public static int testDelegate_returnInt() { + return 42; + } + + public static long testDelegate_returnLong() { + return 43; + } + + public static float testDelegate_returnFloat() { + return 43.0f; + } + + public static double testDelegate_returnDouble() { + return 43.0; + } + + public static String testDelegate_returnString() { + return "plank"; + } + + public static class DelegatingTransformer extends Transformer { + private final MethodHandle delegate; + + public DelegatingTransformer(MethodHandle delegate) { + super(delegate.type()); + this.delegate = delegate; + } + + @Override + public void transform(EmulatedStackFrame stackFrame) throws Throwable { + delegate.invoke(stackFrame); + } + } + + public static void main(String[] args) throws Throwable { + MethodHandle specialFunctionHandle = MethodHandles.lookup().findStatic( + Main.class, "testDelegate_allTypes", MethodType.methodType(void.class, + new Class<?>[] { boolean.class, char.class, short.class, int.class, long.class, + float.class, double.class, String.class, Object.class })); + + DelegatingTransformer delegate = new DelegatingTransformer(specialFunctionHandle); + + // Test an exact invoke. + // + // Note that the shorter form below doesn't work and must be + // investigated on the jack side : b/32536744 + // + // delegate.invokeExact(false, 'h', (short) 56, 72, Integer.MAX_VALUE + 42l, + // 0.56f, 100.0d, "hello", (Object) "goodbye"); + + Object obj = "goodbye"; + delegate.invokeExact(false, 'h', (short) 56, 72, Integer.MAX_VALUE + 42l, + 0.56f, 100.0d, "hello", obj); + + // Test a non exact invoke with one int -> long conversion and a float -> double + // conversion. + delegate.invoke(false, 'h', (short) 56, 72, 73, + 0.56f, 100.0f, "hello", "goodbye"); + + // Should throw a WrongMethodTypeException if the types don't align. + try { + delegate.invoke(false); + throw new AssertionError("Call to invoke unexpectedly succeeded"); + } catch (WrongMethodTypeException expected) { + } + + // Test return values. + + // boolean. + MethodHandle returner = MethodHandles.lookup().findStatic( + Main.class, "testDelegate_returnBoolean", MethodType.methodType(boolean.class)); + delegate = new DelegatingTransformer(returner); + + System.out.println((boolean) delegate.invoke()); + System.out.println((boolean) delegate.invokeExact()); + + // char. + returner = MethodHandles.lookup().findStatic( + Main.class, "testDelegate_returnChar", MethodType.methodType(char.class)); + delegate = new DelegatingTransformer(returner); + + System.out.println((char) delegate.invoke()); + System.out.println((char) delegate.invokeExact()); + + // int. + returner = MethodHandles.lookup().findStatic( + Main.class, "testDelegate_returnInt", MethodType.methodType(int.class)); + delegate = new DelegatingTransformer(returner); + + System.out.println((int) delegate.invoke()); + System.out.println((int) delegate.invokeExact()); + + // long. + returner = MethodHandles.lookup().findStatic( + Main.class, "testDelegate_returnLong", MethodType.methodType(long.class)); + delegate = new DelegatingTransformer(returner); + + System.out.println((long) delegate.invoke()); + System.out.println((long) delegate.invokeExact()); + + // float. + returner = MethodHandles.lookup().findStatic( + Main.class, "testDelegate_returnFloat", MethodType.methodType(float.class)); + delegate = new DelegatingTransformer(returner); + + System.out.println((float) delegate.invoke()); + System.out.println((float) delegate.invokeExact()); + + // double. + returner = MethodHandles.lookup().findStatic( + Main.class, "testDelegate_returnDouble", MethodType.methodType(double.class)); + delegate = new DelegatingTransformer(returner); + + System.out.println((double) delegate.invoke()); + System.out.println((double) delegate.invokeExact()); + + // references. + returner = MethodHandles.lookup().findStatic( + Main.class, "testDelegate_returnString", MethodType.methodType(String.class)); + delegate = new DelegatingTransformer(returner); + + System.out.println((String) delegate.invoke()); + System.out.println((String) delegate.invokeExact()); + } +} + + |