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 import java.lang.invoke.MethodHandle; 18 import java.lang.invoke.MethodHandles; 19 import java.lang.invoke.MethodHandles.Lookup; 20 import java.lang.invoke.MethodType; 21 import java.lang.invoke.WrongMethodTypeException; 22 import java.lang.invoke.Transformers.Transformer; 23 24 import dalvik.system.EmulatedStackFrame; 25 26 public class Main { 27 testDelegate_allTypes(boolean z, char a, short b, int c, long d, float e, double f, String g, Object h)28 public static void testDelegate_allTypes(boolean z, char a, short b, int c, long d, 29 float e, double f, String g, Object h) { 30 System.out.println("boolean: " + z); 31 System.out.println("char: " + a); 32 System.out.println("short: " + b); 33 System.out.println("int: " + c); 34 System.out.println("long: " + d); 35 System.out.println("float: " + e); 36 System.out.println("double: " + f); 37 System.out.println("String: " + g); 38 System.out.println("Object: " + h); 39 } 40 testDelegate_returnBoolean()41 public static boolean testDelegate_returnBoolean() { 42 return true; 43 } 44 testDelegate_returnChar()45 public static char testDelegate_returnChar() { 46 return 'a'; 47 } 48 testDelegate_returnInt()49 public static int testDelegate_returnInt() { 50 return 42; 51 } 52 testDelegate_returnLong()53 public static long testDelegate_returnLong() { 54 return 43; 55 } 56 testDelegate_returnFloat()57 public static float testDelegate_returnFloat() { 58 return 43.0f; 59 } 60 testDelegate_returnDouble()61 public static double testDelegate_returnDouble() { 62 return 43.0; 63 } 64 testDelegate_returnString()65 public static String testDelegate_returnString() { 66 return "plank"; 67 } 68 69 public static class DelegatingTransformer extends Transformer { 70 private final MethodHandle delegate; 71 DelegatingTransformer(MethodHandle delegate)72 public DelegatingTransformer(MethodHandle delegate) { 73 super(delegate.type()); 74 this.delegate = delegate; 75 } 76 77 @Override transform(EmulatedStackFrame stackFrame)78 public void transform(EmulatedStackFrame stackFrame) throws Throwable { 79 delegate.invoke(stackFrame); 80 } 81 } 82 main(String[] args)83 public static void main(String[] args) throws Throwable { 84 MethodHandle specialFunctionHandle = MethodHandles.lookup().findStatic( 85 Main.class, "testDelegate_allTypes", MethodType.methodType(void.class, 86 new Class<?>[] { boolean.class, char.class, short.class, int.class, long.class, 87 float.class, double.class, String.class, Object.class })); 88 89 MethodHandle delegate = new DelegatingTransformer(specialFunctionHandle); 90 91 // Test an exact invoke. 92 // 93 // Note that the shorter form below doesn't work and must be 94 // investigated on the jack side : b/32536744 95 // 96 // delegate.invokeExact(false, 'h', (short) 56, 72, Integer.MAX_VALUE + 42l, 97 // 0.56f, 100.0d, "hello", (Object) "goodbye"); 98 99 Object obj = "goodbye"; 100 delegate.invokeExact(false, 'h', (short) 56, 72, Integer.MAX_VALUE + 42l, 101 0.56f, 100.0d, "hello", obj); 102 103 // Test a non exact invoke with one int -> long conversion and a float -> double 104 // conversion. 105 delegate.invoke(false, 'h', (short) 56, 72, 73, 106 0.56f, 100.0f, "hello", "goodbye"); 107 108 // Should throw a WrongMethodTypeException if the types don't align. 109 try { 110 delegate.invoke(false); 111 throw new AssertionError("Call to invoke unexpectedly succeeded"); 112 } catch (WrongMethodTypeException expected) { 113 } 114 115 // Test return values. 116 117 // boolean. 118 MethodHandle returner = MethodHandles.lookup().findStatic( 119 Main.class, "testDelegate_returnBoolean", MethodType.methodType(boolean.class)); 120 delegate = new DelegatingTransformer(returner); 121 122 System.out.println((boolean) delegate.invoke()); 123 System.out.println((boolean) delegate.invokeExact()); 124 125 // char. 126 returner = MethodHandles.lookup().findStatic( 127 Main.class, "testDelegate_returnChar", MethodType.methodType(char.class)); 128 delegate = new DelegatingTransformer(returner); 129 130 System.out.println((char) delegate.invoke()); 131 System.out.println((char) delegate.invokeExact()); 132 133 // int. 134 returner = MethodHandles.lookup().findStatic( 135 Main.class, "testDelegate_returnInt", MethodType.methodType(int.class)); 136 delegate = new DelegatingTransformer(returner); 137 138 System.out.println((int) delegate.invoke()); 139 System.out.println((int) delegate.invokeExact()); 140 141 // long. 142 returner = MethodHandles.lookup().findStatic( 143 Main.class, "testDelegate_returnLong", MethodType.methodType(long.class)); 144 delegate = new DelegatingTransformer(returner); 145 146 System.out.println((long) delegate.invoke()); 147 System.out.println((long) delegate.invokeExact()); 148 149 // float. 150 returner = MethodHandles.lookup().findStatic( 151 Main.class, "testDelegate_returnFloat", MethodType.methodType(float.class)); 152 delegate = new DelegatingTransformer(returner); 153 154 System.out.println((float) delegate.invoke()); 155 System.out.println((float) delegate.invokeExact()); 156 157 // double. 158 returner = MethodHandles.lookup().findStatic( 159 Main.class, "testDelegate_returnDouble", MethodType.methodType(double.class)); 160 delegate = new DelegatingTransformer(returner); 161 162 System.out.println((double) delegate.invoke()); 163 System.out.println((double) delegate.invokeExact()); 164 165 // references. 166 returner = MethodHandles.lookup().findStatic( 167 Main.class, "testDelegate_returnString", MethodType.methodType(String.class)); 168 delegate = new DelegatingTransformer(returner); 169 170 System.out.println((String) delegate.invoke()); 171 System.out.println((String) delegate.invokeExact()); 172 } 173 } 174 175 176