1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2016 The Android Open Source Project 3*795d594fSAndroid Build Coastguard Worker * 4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*795d594fSAndroid Build Coastguard Worker * 8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*795d594fSAndroid Build Coastguard Worker * 10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*795d594fSAndroid Build Coastguard Worker * limitations under the License. 15*795d594fSAndroid Build Coastguard Worker */ 16*795d594fSAndroid Build Coastguard Worker 17*795d594fSAndroid Build Coastguard Worker import java.lang.invoke.MethodHandle; 18*795d594fSAndroid Build Coastguard Worker import java.lang.invoke.MethodHandles; 19*795d594fSAndroid Build Coastguard Worker import java.lang.invoke.MethodHandles.Lookup; 20*795d594fSAndroid Build Coastguard Worker import java.lang.invoke.MethodType; 21*795d594fSAndroid Build Coastguard Worker import java.lang.invoke.VarHandle; 22*795d594fSAndroid Build Coastguard Worker import java.lang.invoke.WrongMethodTypeException; 23*795d594fSAndroid Build Coastguard Worker 24*795d594fSAndroid Build Coastguard Worker public class Main { main(String[] args)25*795d594fSAndroid Build Coastguard Worker public static void main(String[] args) throws Throwable { 26*795d594fSAndroid Build Coastguard Worker testThrowException(); 27*795d594fSAndroid Build Coastguard Worker testDropArguments(); 28*795d594fSAndroid Build Coastguard Worker testCatchException(); 29*795d594fSAndroid Build Coastguard Worker testGuardWithTest(); 30*795d594fSAndroid Build Coastguard Worker testArrayElementGetter(); 31*795d594fSAndroid Build Coastguard Worker testArrayElementSetter(); 32*795d594fSAndroid Build Coastguard Worker testIdentity(); 33*795d594fSAndroid Build Coastguard Worker testConstant(); 34*795d594fSAndroid Build Coastguard Worker testBindTo(); 35*795d594fSAndroid Build Coastguard Worker testFilterReturnValue(); 36*795d594fSAndroid Build Coastguard Worker testPermuteArguments(); 37*795d594fSAndroid Build Coastguard Worker testInvokers(); 38*795d594fSAndroid Build Coastguard Worker testSpreaders_reference(); 39*795d594fSAndroid Build Coastguard Worker testSpreaders_primitive(); 40*795d594fSAndroid Build Coastguard Worker testInvokeWithArguments(); 41*795d594fSAndroid Build Coastguard Worker testAsCollector(); 42*795d594fSAndroid Build Coastguard Worker testFilterArguments(); 43*795d594fSAndroid Build Coastguard Worker testCollectArguments(); 44*795d594fSAndroid Build Coastguard Worker testInsertArguments(); 45*795d594fSAndroid Build Coastguard Worker testFoldArguments(); 46*795d594fSAndroid Build Coastguard Worker } 47*795d594fSAndroid Build Coastguard Worker testThrowException()48*795d594fSAndroid Build Coastguard Worker public static void testThrowException() throws Throwable { 49*795d594fSAndroid Build Coastguard Worker MethodHandle handle = MethodHandles.throwException(String.class, 50*795d594fSAndroid Build Coastguard Worker IllegalArgumentException.class); 51*795d594fSAndroid Build Coastguard Worker 52*795d594fSAndroid Build Coastguard Worker if (handle.type().returnType() != String.class) { 53*795d594fSAndroid Build Coastguard Worker fail("Unexpected return type for handle: " + handle + 54*795d594fSAndroid Build Coastguard Worker " [ " + handle.type() + "]"); 55*795d594fSAndroid Build Coastguard Worker } 56*795d594fSAndroid Build Coastguard Worker 57*795d594fSAndroid Build Coastguard Worker final IllegalArgumentException iae = new IllegalArgumentException("boo!"); 58*795d594fSAndroid Build Coastguard Worker try { 59*795d594fSAndroid Build Coastguard Worker handle.invoke(iae); 60*795d594fSAndroid Build Coastguard Worker fail("Expected an exception of type: java.lang.IllegalArgumentException"); 61*795d594fSAndroid Build Coastguard Worker } catch (IllegalArgumentException expected) { 62*795d594fSAndroid Build Coastguard Worker if (expected != iae) { 63*795d594fSAndroid Build Coastguard Worker fail("Wrong exception: expected " + iae + " but was " + expected); 64*795d594fSAndroid Build Coastguard Worker } 65*795d594fSAndroid Build Coastguard Worker } 66*795d594fSAndroid Build Coastguard Worker } 67*795d594fSAndroid Build Coastguard Worker dropArguments_delegate(String message, long message2)68*795d594fSAndroid Build Coastguard Worker public static void dropArguments_delegate(String message, long message2) { 69*795d594fSAndroid Build Coastguard Worker System.out.println("Message: " + message + ", Message2: " + message2); 70*795d594fSAndroid Build Coastguard Worker } 71*795d594fSAndroid Build Coastguard Worker testDropArguments()72*795d594fSAndroid Build Coastguard Worker public static void testDropArguments() throws Throwable { 73*795d594fSAndroid Build Coastguard Worker MethodHandle delegate = MethodHandles.lookup().findStatic(Main.class, 74*795d594fSAndroid Build Coastguard Worker "dropArguments_delegate", 75*795d594fSAndroid Build Coastguard Worker MethodType.methodType(void.class, new Class<?>[] { String.class, long.class })); 76*795d594fSAndroid Build Coastguard Worker 77*795d594fSAndroid Build Coastguard Worker MethodHandle transform = MethodHandles.dropArguments(delegate, 0, int.class, Object.class); 78*795d594fSAndroid Build Coastguard Worker 79*795d594fSAndroid Build Coastguard Worker // The transformer will accept two additional arguments at position zero. 80*795d594fSAndroid Build Coastguard Worker try { 81*795d594fSAndroid Build Coastguard Worker transform.invokeExact("foo", 42l); 82*795d594fSAndroid Build Coastguard Worker fail(); 83*795d594fSAndroid Build Coastguard Worker } catch (WrongMethodTypeException expected) { 84*795d594fSAndroid Build Coastguard Worker } 85*795d594fSAndroid Build Coastguard Worker 86*795d594fSAndroid Build Coastguard Worker transform.invokeExact(45, new Object(), "foo", 42l); 87*795d594fSAndroid Build Coastguard Worker transform.invoke(45, new Object(), "foo", 42l); 88*795d594fSAndroid Build Coastguard Worker 89*795d594fSAndroid Build Coastguard Worker // Additional arguments at position 1. 90*795d594fSAndroid Build Coastguard Worker transform = MethodHandles.dropArguments(delegate, 1, int.class, Object.class); 91*795d594fSAndroid Build Coastguard Worker transform.invokeExact("foo", 45, new Object(), 42l); 92*795d594fSAndroid Build Coastguard Worker transform.invoke("foo", 45, new Object(), 42l); 93*795d594fSAndroid Build Coastguard Worker 94*795d594fSAndroid Build Coastguard Worker // Additional arguments at position 2. 95*795d594fSAndroid Build Coastguard Worker transform = MethodHandles.dropArguments(delegate, 2, int.class, Object.class); 96*795d594fSAndroid Build Coastguard Worker transform.invokeExact("foo", 42l, 45, new Object()); 97*795d594fSAndroid Build Coastguard Worker transform.invoke("foo", 42l, 45, new Object()); 98*795d594fSAndroid Build Coastguard Worker 99*795d594fSAndroid Build Coastguard Worker // Note that we still perform argument conversions even for the arguments that 100*795d594fSAndroid Build Coastguard Worker // are subsequently dropped. 101*795d594fSAndroid Build Coastguard Worker try { 102*795d594fSAndroid Build Coastguard Worker transform.invoke("foo", 42l, 45l, new Object()); 103*795d594fSAndroid Build Coastguard Worker fail(); 104*795d594fSAndroid Build Coastguard Worker } catch (WrongMethodTypeException expected) { 105*795d594fSAndroid Build Coastguard Worker } catch (IllegalArgumentException expected) { 106*795d594fSAndroid Build Coastguard Worker // TODO(narayan): We currently throw the wrong type of exception here, 107*795d594fSAndroid Build Coastguard Worker // it's IAE and should be WMTE instead. 108*795d594fSAndroid Build Coastguard Worker } 109*795d594fSAndroid Build Coastguard Worker 110*795d594fSAndroid Build Coastguard Worker // Check that asType works as expected. 111*795d594fSAndroid Build Coastguard Worker transform = MethodHandles.dropArguments(delegate, 0, int.class, Object.class); 112*795d594fSAndroid Build Coastguard Worker transform = transform.asType(MethodType.methodType(void.class, 113*795d594fSAndroid Build Coastguard Worker new Class<?>[] { short.class, Object.class, String.class, long.class })); 114*795d594fSAndroid Build Coastguard Worker transform.invokeExact((short) 45, new Object(), "foo", 42l); 115*795d594fSAndroid Build Coastguard Worker 116*795d594fSAndroid Build Coastguard Worker // Invalid argument location, should not be allowed. 117*795d594fSAndroid Build Coastguard Worker try { 118*795d594fSAndroid Build Coastguard Worker MethodHandles.dropArguments(delegate, -1, int.class, Object.class); 119*795d594fSAndroid Build Coastguard Worker fail(); 120*795d594fSAndroid Build Coastguard Worker } catch (IllegalArgumentException expected) { 121*795d594fSAndroid Build Coastguard Worker } 122*795d594fSAndroid Build Coastguard Worker 123*795d594fSAndroid Build Coastguard Worker // Invalid argument location, should not be allowed. 124*795d594fSAndroid Build Coastguard Worker try { 125*795d594fSAndroid Build Coastguard Worker MethodHandles.dropArguments(delegate, 3, int.class, Object.class); 126*795d594fSAndroid Build Coastguard Worker fail(); 127*795d594fSAndroid Build Coastguard Worker } catch (IllegalArgumentException expected) { 128*795d594fSAndroid Build Coastguard Worker } 129*795d594fSAndroid Build Coastguard Worker 130*795d594fSAndroid Build Coastguard Worker try { 131*795d594fSAndroid Build Coastguard Worker MethodHandles.dropArguments(delegate, 1, void.class); 132*795d594fSAndroid Build Coastguard Worker fail(); 133*795d594fSAndroid Build Coastguard Worker } catch (IllegalArgumentException expected) { 134*795d594fSAndroid Build Coastguard Worker } 135*795d594fSAndroid Build Coastguard Worker } 136*795d594fSAndroid Build Coastguard Worker testCatchException_target(String arg1, long arg2, String exceptionMessage)137*795d594fSAndroid Build Coastguard Worker public static String testCatchException_target(String arg1, long arg2, String exceptionMessage) 138*795d594fSAndroid Build Coastguard Worker throws Throwable { 139*795d594fSAndroid Build Coastguard Worker if (exceptionMessage != null) { 140*795d594fSAndroid Build Coastguard Worker throw new IllegalArgumentException(exceptionMessage); 141*795d594fSAndroid Build Coastguard Worker } 142*795d594fSAndroid Build Coastguard Worker 143*795d594fSAndroid Build Coastguard Worker System.out.println("Target: Arg1: " + arg1 + ", Arg2: " + arg2); 144*795d594fSAndroid Build Coastguard Worker return "target"; 145*795d594fSAndroid Build Coastguard Worker } 146*795d594fSAndroid Build Coastguard Worker testCatchException_handler(IllegalArgumentException iae, String arg1, long arg2, String exMsg)147*795d594fSAndroid Build Coastguard Worker public static String testCatchException_handler(IllegalArgumentException iae, String arg1, long arg2, 148*795d594fSAndroid Build Coastguard Worker String exMsg) { 149*795d594fSAndroid Build Coastguard Worker System.out.println("Handler: " + iae + ", Arg1: " + arg1 + ", Arg2: " + arg2 + ", ExMsg: " + exMsg); 150*795d594fSAndroid Build Coastguard Worker return "handler1"; 151*795d594fSAndroid Build Coastguard Worker } 152*795d594fSAndroid Build Coastguard Worker testCatchException_handler2(IllegalArgumentException iae, String arg1)153*795d594fSAndroid Build Coastguard Worker public static String testCatchException_handler2(IllegalArgumentException iae, String arg1) { 154*795d594fSAndroid Build Coastguard Worker System.out.println("Handler: " + iae + ", Arg1: " + arg1); 155*795d594fSAndroid Build Coastguard Worker return "handler2"; 156*795d594fSAndroid Build Coastguard Worker } 157*795d594fSAndroid Build Coastguard Worker testCatchException()158*795d594fSAndroid Build Coastguard Worker public static void testCatchException() throws Throwable { 159*795d594fSAndroid Build Coastguard Worker MethodHandle target = MethodHandles.lookup().findStatic(Main.class, 160*795d594fSAndroid Build Coastguard Worker "testCatchException_target", 161*795d594fSAndroid Build Coastguard Worker MethodType.methodType(String.class, new Class<?>[] { String.class, long.class, String.class })); 162*795d594fSAndroid Build Coastguard Worker 163*795d594fSAndroid Build Coastguard Worker MethodHandle handler = MethodHandles.lookup().findStatic(Main.class, 164*795d594fSAndroid Build Coastguard Worker "testCatchException_handler", 165*795d594fSAndroid Build Coastguard Worker MethodType.methodType(String.class, new Class<?>[] { IllegalArgumentException.class, 166*795d594fSAndroid Build Coastguard Worker String.class, long.class, String.class })); 167*795d594fSAndroid Build Coastguard Worker 168*795d594fSAndroid Build Coastguard Worker MethodHandle adapter = MethodHandles.catchException(target, IllegalArgumentException.class, 169*795d594fSAndroid Build Coastguard Worker handler); 170*795d594fSAndroid Build Coastguard Worker 171*795d594fSAndroid Build Coastguard Worker String returnVal = null; 172*795d594fSAndroid Build Coastguard Worker 173*795d594fSAndroid Build Coastguard Worker // These two should end up calling the target always. We're passing a null exception 174*795d594fSAndroid Build Coastguard Worker // message here, which means the target will not throw. 175*795d594fSAndroid Build Coastguard Worker returnVal = (String) adapter.invoke("foo", 42, null); 176*795d594fSAndroid Build Coastguard Worker assertEquals("target", returnVal); 177*795d594fSAndroid Build Coastguard Worker returnVal = (String) adapter.invokeExact("foo", 42l, (String) null); 178*795d594fSAndroid Build Coastguard Worker assertEquals("target", returnVal); 179*795d594fSAndroid Build Coastguard Worker 180*795d594fSAndroid Build Coastguard Worker // We're passing a non-null exception message here, which means the target will throw, 181*795d594fSAndroid Build Coastguard Worker // which in turn means that the handler must be called for the next two invokes. 182*795d594fSAndroid Build Coastguard Worker returnVal = (String) adapter.invoke("foo", 42, "exceptionMessage"); 183*795d594fSAndroid Build Coastguard Worker assertEquals("handler1", returnVal); 184*795d594fSAndroid Build Coastguard Worker returnVal = (String) adapter.invokeExact("foo", 42l, "exceptionMessage"); 185*795d594fSAndroid Build Coastguard Worker assertEquals("handler1", returnVal); 186*795d594fSAndroid Build Coastguard Worker 187*795d594fSAndroid Build Coastguard Worker handler = MethodHandles.lookup().findStatic(Main.class, 188*795d594fSAndroid Build Coastguard Worker "testCatchException_handler2", 189*795d594fSAndroid Build Coastguard Worker MethodType.methodType(String.class, new Class<?>[] { IllegalArgumentException.class, 190*795d594fSAndroid Build Coastguard Worker String.class })); 191*795d594fSAndroid Build Coastguard Worker adapter = MethodHandles.catchException(target, IllegalArgumentException.class, handler); 192*795d594fSAndroid Build Coastguard Worker 193*795d594fSAndroid Build Coastguard Worker returnVal = (String) adapter.invoke("foo", 42, "exceptionMessage"); 194*795d594fSAndroid Build Coastguard Worker assertEquals("handler2", returnVal); 195*795d594fSAndroid Build Coastguard Worker returnVal = (String) adapter.invokeExact("foo", 42l, "exceptionMessage"); 196*795d594fSAndroid Build Coastguard Worker assertEquals("handler2", returnVal); 197*795d594fSAndroid Build Coastguard Worker 198*795d594fSAndroid Build Coastguard Worker // Test that the type of the invoke doesn't matter. Here we call 199*795d594fSAndroid Build Coastguard Worker // IllegalArgumentException.toString() on the exception that was thrown by 200*795d594fSAndroid Build Coastguard Worker // the target. 201*795d594fSAndroid Build Coastguard Worker handler = MethodHandles.lookup().findVirtual(IllegalArgumentException.class, 202*795d594fSAndroid Build Coastguard Worker "toString", MethodType.methodType(String.class)); 203*795d594fSAndroid Build Coastguard Worker adapter = MethodHandles.catchException(target, IllegalArgumentException.class, handler); 204*795d594fSAndroid Build Coastguard Worker 205*795d594fSAndroid Build Coastguard Worker returnVal = (String) adapter.invoke("foo", 42, "exceptionMessage"); 206*795d594fSAndroid Build Coastguard Worker assertEquals("java.lang.IllegalArgumentException: exceptionMessage", returnVal); 207*795d594fSAndroid Build Coastguard Worker returnVal = (String) adapter.invokeExact("foo", 42l, "exceptionMessage2"); 208*795d594fSAndroid Build Coastguard Worker assertEquals("java.lang.IllegalArgumentException: exceptionMessage2", returnVal); 209*795d594fSAndroid Build Coastguard Worker 210*795d594fSAndroid Build Coastguard Worker // Check that asType works as expected. 211*795d594fSAndroid Build Coastguard Worker adapter = MethodHandles.catchException(target, IllegalArgumentException.class, 212*795d594fSAndroid Build Coastguard Worker handler); 213*795d594fSAndroid Build Coastguard Worker adapter = adapter.asType(MethodType.methodType(String.class, 214*795d594fSAndroid Build Coastguard Worker new Class<?>[] { String.class, int.class, String.class })); 215*795d594fSAndroid Build Coastguard Worker returnVal = (String) adapter.invokeExact("foo", 42, "exceptionMessage"); 216*795d594fSAndroid Build Coastguard Worker assertEquals("java.lang.IllegalArgumentException: exceptionMessage", returnVal); 217*795d594fSAndroid Build Coastguard Worker } 218*795d594fSAndroid Build Coastguard Worker testGuardWithTest_test(String arg1, long arg2)219*795d594fSAndroid Build Coastguard Worker public static boolean testGuardWithTest_test(String arg1, long arg2) { 220*795d594fSAndroid Build Coastguard Worker return "target".equals(arg1) && 42 == arg2; 221*795d594fSAndroid Build Coastguard Worker } 222*795d594fSAndroid Build Coastguard Worker testGuardWithTest_target(String arg1, long arg2, int arg3)223*795d594fSAndroid Build Coastguard Worker public static String testGuardWithTest_target(String arg1, long arg2, int arg3) { 224*795d594fSAndroid Build Coastguard Worker System.out.println("target: " + arg1 + ", " + arg2 + ", " + arg3); 225*795d594fSAndroid Build Coastguard Worker return "target"; 226*795d594fSAndroid Build Coastguard Worker } 227*795d594fSAndroid Build Coastguard Worker testGuardWithTest_fallback(String arg1, long arg2, int arg3)228*795d594fSAndroid Build Coastguard Worker public static String testGuardWithTest_fallback(String arg1, long arg2, int arg3) { 229*795d594fSAndroid Build Coastguard Worker System.out.println("fallback: " + arg1 + ", " + arg2 + ", " + arg3); 230*795d594fSAndroid Build Coastguard Worker return "fallback"; 231*795d594fSAndroid Build Coastguard Worker } 232*795d594fSAndroid Build Coastguard Worker testGuardWithTest()233*795d594fSAndroid Build Coastguard Worker public static void testGuardWithTest() throws Throwable { 234*795d594fSAndroid Build Coastguard Worker MethodHandle test = MethodHandles.lookup().findStatic(Main.class, 235*795d594fSAndroid Build Coastguard Worker "testGuardWithTest_test", 236*795d594fSAndroid Build Coastguard Worker MethodType.methodType(boolean.class, new Class<?>[] { String.class, long.class })); 237*795d594fSAndroid Build Coastguard Worker 238*795d594fSAndroid Build Coastguard Worker final MethodType type = MethodType.methodType(String.class, 239*795d594fSAndroid Build Coastguard Worker new Class<?>[] { String.class, long.class, int.class }); 240*795d594fSAndroid Build Coastguard Worker 241*795d594fSAndroid Build Coastguard Worker final MethodHandle target = MethodHandles.lookup().findStatic(Main.class, 242*795d594fSAndroid Build Coastguard Worker "testGuardWithTest_target", type); 243*795d594fSAndroid Build Coastguard Worker final MethodHandle fallback = MethodHandles.lookup().findStatic(Main.class, 244*795d594fSAndroid Build Coastguard Worker "testGuardWithTest_fallback", type); 245*795d594fSAndroid Build Coastguard Worker 246*795d594fSAndroid Build Coastguard Worker MethodHandle adapter = MethodHandles.guardWithTest(test, target, fallback); 247*795d594fSAndroid Build Coastguard Worker 248*795d594fSAndroid Build Coastguard Worker String returnVal = null; 249*795d594fSAndroid Build Coastguard Worker 250*795d594fSAndroid Build Coastguard Worker returnVal = (String) adapter.invoke("target", 42, 56); 251*795d594fSAndroid Build Coastguard Worker assertEquals("target", returnVal); 252*795d594fSAndroid Build Coastguard Worker returnVal = (String) adapter.invokeExact("target", 42l, 56); 253*795d594fSAndroid Build Coastguard Worker assertEquals("target", returnVal); 254*795d594fSAndroid Build Coastguard Worker 255*795d594fSAndroid Build Coastguard Worker returnVal = (String) adapter.invoke("fallback", 42l, 56); 256*795d594fSAndroid Build Coastguard Worker assertEquals("fallback", returnVal); 257*795d594fSAndroid Build Coastguard Worker returnVal = (String) adapter.invokeExact("target", 42l, 56); 258*795d594fSAndroid Build Coastguard Worker assertEquals("target", returnVal); 259*795d594fSAndroid Build Coastguard Worker 260*795d594fSAndroid Build Coastguard Worker // Check that asType works as expected. 261*795d594fSAndroid Build Coastguard Worker adapter = adapter.asType(MethodType.methodType(String.class, 262*795d594fSAndroid Build Coastguard Worker new Class<?>[] { String.class, int.class, int.class })); 263*795d594fSAndroid Build Coastguard Worker returnVal = (String) adapter.invokeExact("target", 42, 56); 264*795d594fSAndroid Build Coastguard Worker assertEquals("target", returnVal); 265*795d594fSAndroid Build Coastguard Worker } 266*795d594fSAndroid Build Coastguard Worker testArrayElementGetter()267*795d594fSAndroid Build Coastguard Worker public static void testArrayElementGetter() throws Throwable { 268*795d594fSAndroid Build Coastguard Worker MethodHandle getter = MethodHandles.arrayElementGetter(int[].class); 269*795d594fSAndroid Build Coastguard Worker 270*795d594fSAndroid Build Coastguard Worker { 271*795d594fSAndroid Build Coastguard Worker int[] array = new int[1]; 272*795d594fSAndroid Build Coastguard Worker array[0] = 42; 273*795d594fSAndroid Build Coastguard Worker int value = (int) getter.invoke(array, 0); 274*795d594fSAndroid Build Coastguard Worker if (value != 42) { 275*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + value); 276*795d594fSAndroid Build Coastguard Worker } 277*795d594fSAndroid Build Coastguard Worker 278*795d594fSAndroid Build Coastguard Worker try { 279*795d594fSAndroid Build Coastguard Worker value = (int) getter.invoke(array, -1); 280*795d594fSAndroid Build Coastguard Worker fail(); 281*795d594fSAndroid Build Coastguard Worker } catch (ArrayIndexOutOfBoundsException expected) { 282*795d594fSAndroid Build Coastguard Worker } 283*795d594fSAndroid Build Coastguard Worker 284*795d594fSAndroid Build Coastguard Worker try { 285*795d594fSAndroid Build Coastguard Worker value = (int) getter.invoke(null, -1); 286*795d594fSAndroid Build Coastguard Worker fail(); 287*795d594fSAndroid Build Coastguard Worker } catch (NullPointerException expected) { 288*795d594fSAndroid Build Coastguard Worker } 289*795d594fSAndroid Build Coastguard Worker } 290*795d594fSAndroid Build Coastguard Worker 291*795d594fSAndroid Build Coastguard Worker { 292*795d594fSAndroid Build Coastguard Worker getter = MethodHandles.arrayElementGetter(long[].class); 293*795d594fSAndroid Build Coastguard Worker long[] array = new long[1]; 294*795d594fSAndroid Build Coastguard Worker array[0] = 42; 295*795d594fSAndroid Build Coastguard Worker long value = (long) getter.invoke(array, 0); 296*795d594fSAndroid Build Coastguard Worker if (value != 42l) { 297*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + value); 298*795d594fSAndroid Build Coastguard Worker } 299*795d594fSAndroid Build Coastguard Worker } 300*795d594fSAndroid Build Coastguard Worker 301*795d594fSAndroid Build Coastguard Worker { 302*795d594fSAndroid Build Coastguard Worker getter = MethodHandles.arrayElementGetter(short[].class); 303*795d594fSAndroid Build Coastguard Worker short[] array = new short[1]; 304*795d594fSAndroid Build Coastguard Worker array[0] = 42; 305*795d594fSAndroid Build Coastguard Worker short value = (short) getter.invoke(array, 0); 306*795d594fSAndroid Build Coastguard Worker if (value != 42l) { 307*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + value); 308*795d594fSAndroid Build Coastguard Worker } 309*795d594fSAndroid Build Coastguard Worker } 310*795d594fSAndroid Build Coastguard Worker 311*795d594fSAndroid Build Coastguard Worker { 312*795d594fSAndroid Build Coastguard Worker getter = MethodHandles.arrayElementGetter(char[].class); 313*795d594fSAndroid Build Coastguard Worker char[] array = new char[1]; 314*795d594fSAndroid Build Coastguard Worker array[0] = 42; 315*795d594fSAndroid Build Coastguard Worker char value = (char) getter.invoke(array, 0); 316*795d594fSAndroid Build Coastguard Worker if (value != 42l) { 317*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + value); 318*795d594fSAndroid Build Coastguard Worker } 319*795d594fSAndroid Build Coastguard Worker } 320*795d594fSAndroid Build Coastguard Worker 321*795d594fSAndroid Build Coastguard Worker { 322*795d594fSAndroid Build Coastguard Worker getter = MethodHandles.arrayElementGetter(byte[].class); 323*795d594fSAndroid Build Coastguard Worker byte[] array = new byte[1]; 324*795d594fSAndroid Build Coastguard Worker array[0] = (byte) 0x8; 325*795d594fSAndroid Build Coastguard Worker byte value = (byte) getter.invoke(array, 0); 326*795d594fSAndroid Build Coastguard Worker if (value != (byte) 0x8) { 327*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + value); 328*795d594fSAndroid Build Coastguard Worker } 329*795d594fSAndroid Build Coastguard Worker } 330*795d594fSAndroid Build Coastguard Worker 331*795d594fSAndroid Build Coastguard Worker { 332*795d594fSAndroid Build Coastguard Worker getter = MethodHandles.arrayElementGetter(boolean[].class); 333*795d594fSAndroid Build Coastguard Worker boolean[] array = new boolean[1]; 334*795d594fSAndroid Build Coastguard Worker array[0] = true; 335*795d594fSAndroid Build Coastguard Worker boolean value = (boolean) getter.invoke(array, 0); 336*795d594fSAndroid Build Coastguard Worker if (!value) { 337*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + value); 338*795d594fSAndroid Build Coastguard Worker } 339*795d594fSAndroid Build Coastguard Worker } 340*795d594fSAndroid Build Coastguard Worker 341*795d594fSAndroid Build Coastguard Worker { 342*795d594fSAndroid Build Coastguard Worker getter = MethodHandles.arrayElementGetter(float[].class); 343*795d594fSAndroid Build Coastguard Worker float[] array = new float[1]; 344*795d594fSAndroid Build Coastguard Worker array[0] = 42.0f; 345*795d594fSAndroid Build Coastguard Worker float value = (float) getter.invoke(array, 0); 346*795d594fSAndroid Build Coastguard Worker if (value != 42.0f) { 347*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + value); 348*795d594fSAndroid Build Coastguard Worker } 349*795d594fSAndroid Build Coastguard Worker } 350*795d594fSAndroid Build Coastguard Worker 351*795d594fSAndroid Build Coastguard Worker { 352*795d594fSAndroid Build Coastguard Worker getter = MethodHandles.arrayElementGetter(double[].class); 353*795d594fSAndroid Build Coastguard Worker double[] array = new double[1]; 354*795d594fSAndroid Build Coastguard Worker array[0] = 42.0; 355*795d594fSAndroid Build Coastguard Worker double value = (double) getter.invoke(array, 0); 356*795d594fSAndroid Build Coastguard Worker if (value != 42.0) { 357*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + value); 358*795d594fSAndroid Build Coastguard Worker } 359*795d594fSAndroid Build Coastguard Worker } 360*795d594fSAndroid Build Coastguard Worker 361*795d594fSAndroid Build Coastguard Worker { 362*795d594fSAndroid Build Coastguard Worker getter = MethodHandles.arrayElementGetter(String[].class); 363*795d594fSAndroid Build Coastguard Worker String[] array = new String[3]; 364*795d594fSAndroid Build Coastguard Worker array[0] = "42"; 365*795d594fSAndroid Build Coastguard Worker array[1] = "48"; 366*795d594fSAndroid Build Coastguard Worker array[2] = "54"; 367*795d594fSAndroid Build Coastguard Worker String value = (String) getter.invoke(array, 0); 368*795d594fSAndroid Build Coastguard Worker assertEquals("42", value); 369*795d594fSAndroid Build Coastguard Worker value = (String) getter.invoke(array, 1); 370*795d594fSAndroid Build Coastguard Worker assertEquals("48", value); 371*795d594fSAndroid Build Coastguard Worker value = (String) getter.invoke(array, 2); 372*795d594fSAndroid Build Coastguard Worker assertEquals("54", value); 373*795d594fSAndroid Build Coastguard Worker } 374*795d594fSAndroid Build Coastguard Worker } 375*795d594fSAndroid Build Coastguard Worker testArrayElementSetter()376*795d594fSAndroid Build Coastguard Worker public static void testArrayElementSetter() throws Throwable { 377*795d594fSAndroid Build Coastguard Worker MethodHandle setter = MethodHandles.arrayElementSetter(int[].class); 378*795d594fSAndroid Build Coastguard Worker 379*795d594fSAndroid Build Coastguard Worker { 380*795d594fSAndroid Build Coastguard Worker int[] array = new int[2]; 381*795d594fSAndroid Build Coastguard Worker setter.invoke(array, 0, 42); 382*795d594fSAndroid Build Coastguard Worker setter.invoke(array, 1, 43); 383*795d594fSAndroid Build Coastguard Worker 384*795d594fSAndroid Build Coastguard Worker if (array[0] != 42) { 385*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + array[0]); 386*795d594fSAndroid Build Coastguard Worker } 387*795d594fSAndroid Build Coastguard Worker if (array[1] != 43) { 388*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + array[1]); 389*795d594fSAndroid Build Coastguard Worker } 390*795d594fSAndroid Build Coastguard Worker 391*795d594fSAndroid Build Coastguard Worker try { 392*795d594fSAndroid Build Coastguard Worker setter.invoke(array, -1, 42); 393*795d594fSAndroid Build Coastguard Worker fail(); 394*795d594fSAndroid Build Coastguard Worker } catch (ArrayIndexOutOfBoundsException expected) { 395*795d594fSAndroid Build Coastguard Worker } 396*795d594fSAndroid Build Coastguard Worker 397*795d594fSAndroid Build Coastguard Worker try { 398*795d594fSAndroid Build Coastguard Worker setter.invoke(null, 0, 42); 399*795d594fSAndroid Build Coastguard Worker fail(); 400*795d594fSAndroid Build Coastguard Worker } catch (NullPointerException expected) { 401*795d594fSAndroid Build Coastguard Worker } 402*795d594fSAndroid Build Coastguard Worker } 403*795d594fSAndroid Build Coastguard Worker 404*795d594fSAndroid Build Coastguard Worker { 405*795d594fSAndroid Build Coastguard Worker setter = MethodHandles.arrayElementSetter(long[].class); 406*795d594fSAndroid Build Coastguard Worker long[] array = new long[1]; 407*795d594fSAndroid Build Coastguard Worker setter.invoke(array, 0, 42l); 408*795d594fSAndroid Build Coastguard Worker if (array[0] != 42l) { 409*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + array[0]); 410*795d594fSAndroid Build Coastguard Worker } 411*795d594fSAndroid Build Coastguard Worker } 412*795d594fSAndroid Build Coastguard Worker 413*795d594fSAndroid Build Coastguard Worker { 414*795d594fSAndroid Build Coastguard Worker setter = MethodHandles.arrayElementSetter(short[].class); 415*795d594fSAndroid Build Coastguard Worker short[] array = new short[1]; 416*795d594fSAndroid Build Coastguard Worker setter.invoke(array, 0, (short) 42); 417*795d594fSAndroid Build Coastguard Worker if (array[0] != 42l) { 418*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + array[0]); 419*795d594fSAndroid Build Coastguard Worker } 420*795d594fSAndroid Build Coastguard Worker } 421*795d594fSAndroid Build Coastguard Worker 422*795d594fSAndroid Build Coastguard Worker { 423*795d594fSAndroid Build Coastguard Worker setter = MethodHandles.arrayElementSetter(char[].class); 424*795d594fSAndroid Build Coastguard Worker char[] array = new char[1]; 425*795d594fSAndroid Build Coastguard Worker setter.invoke(array, 0, (char) 42); 426*795d594fSAndroid Build Coastguard Worker if (array[0] != 42) { 427*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + array[0]); 428*795d594fSAndroid Build Coastguard Worker } 429*795d594fSAndroid Build Coastguard Worker } 430*795d594fSAndroid Build Coastguard Worker 431*795d594fSAndroid Build Coastguard Worker { 432*795d594fSAndroid Build Coastguard Worker setter = MethodHandles.arrayElementSetter(byte[].class); 433*795d594fSAndroid Build Coastguard Worker byte[] array = new byte[1]; 434*795d594fSAndroid Build Coastguard Worker setter.invoke(array, 0, (byte) 0x8); 435*795d594fSAndroid Build Coastguard Worker if (array[0] != (byte) 0x8) { 436*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + array[0]); 437*795d594fSAndroid Build Coastguard Worker } 438*795d594fSAndroid Build Coastguard Worker } 439*795d594fSAndroid Build Coastguard Worker 440*795d594fSAndroid Build Coastguard Worker { 441*795d594fSAndroid Build Coastguard Worker setter = MethodHandles.arrayElementSetter(boolean[].class); 442*795d594fSAndroid Build Coastguard Worker boolean[] array = new boolean[1]; 443*795d594fSAndroid Build Coastguard Worker setter.invoke(array, 0, true); 444*795d594fSAndroid Build Coastguard Worker if (!array[0]) { 445*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + array[0]); 446*795d594fSAndroid Build Coastguard Worker } 447*795d594fSAndroid Build Coastguard Worker } 448*795d594fSAndroid Build Coastguard Worker 449*795d594fSAndroid Build Coastguard Worker { 450*795d594fSAndroid Build Coastguard Worker setter = MethodHandles.arrayElementSetter(float[].class); 451*795d594fSAndroid Build Coastguard Worker float[] array = new float[1]; 452*795d594fSAndroid Build Coastguard Worker setter.invoke(array, 0, 42.0f); 453*795d594fSAndroid Build Coastguard Worker if (array[0] != 42.0f) { 454*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + array[0]); 455*795d594fSAndroid Build Coastguard Worker } 456*795d594fSAndroid Build Coastguard Worker } 457*795d594fSAndroid Build Coastguard Worker 458*795d594fSAndroid Build Coastguard Worker { 459*795d594fSAndroid Build Coastguard Worker setter = MethodHandles.arrayElementSetter(double[].class); 460*795d594fSAndroid Build Coastguard Worker double[] array = new double[1]; 461*795d594fSAndroid Build Coastguard Worker setter.invoke(array, 0, 42.0); 462*795d594fSAndroid Build Coastguard Worker if (array[0] != 42.0) { 463*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + array[0]); 464*795d594fSAndroid Build Coastguard Worker } 465*795d594fSAndroid Build Coastguard Worker } 466*795d594fSAndroid Build Coastguard Worker 467*795d594fSAndroid Build Coastguard Worker { 468*795d594fSAndroid Build Coastguard Worker setter = MethodHandles.arrayElementSetter(String[].class); 469*795d594fSAndroid Build Coastguard Worker String[] array = new String[3]; 470*795d594fSAndroid Build Coastguard Worker setter.invoke(array, 0, "42"); 471*795d594fSAndroid Build Coastguard Worker setter.invoke(array, 1, "48"); 472*795d594fSAndroid Build Coastguard Worker setter.invoke(array, 2, "54"); 473*795d594fSAndroid Build Coastguard Worker assertEquals("42", array[0]); 474*795d594fSAndroid Build Coastguard Worker assertEquals("48", array[1]); 475*795d594fSAndroid Build Coastguard Worker assertEquals("54", array[2]); 476*795d594fSAndroid Build Coastguard Worker } 477*795d594fSAndroid Build Coastguard Worker } 478*795d594fSAndroid Build Coastguard Worker testIdentity()479*795d594fSAndroid Build Coastguard Worker public static void testIdentity() throws Throwable { 480*795d594fSAndroid Build Coastguard Worker { 481*795d594fSAndroid Build Coastguard Worker MethodHandle identity = MethodHandles.identity(boolean.class); 482*795d594fSAndroid Build Coastguard Worker boolean value = (boolean) identity.invoke(false); 483*795d594fSAndroid Build Coastguard Worker if (value) { 484*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + value); 485*795d594fSAndroid Build Coastguard Worker } 486*795d594fSAndroid Build Coastguard Worker } 487*795d594fSAndroid Build Coastguard Worker 488*795d594fSAndroid Build Coastguard Worker { 489*795d594fSAndroid Build Coastguard Worker MethodHandle identity = MethodHandles.identity(byte.class); 490*795d594fSAndroid Build Coastguard Worker byte value = (byte) identity.invoke((byte) 0x8); 491*795d594fSAndroid Build Coastguard Worker if (value != (byte) 0x8) { 492*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + value); 493*795d594fSAndroid Build Coastguard Worker } 494*795d594fSAndroid Build Coastguard Worker } 495*795d594fSAndroid Build Coastguard Worker 496*795d594fSAndroid Build Coastguard Worker { 497*795d594fSAndroid Build Coastguard Worker MethodHandle identity = MethodHandles.identity(char.class); 498*795d594fSAndroid Build Coastguard Worker char value = (char) identity.invoke((char) -56); 499*795d594fSAndroid Build Coastguard Worker if (value != (char) -56) { 500*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + value); 501*795d594fSAndroid Build Coastguard Worker } 502*795d594fSAndroid Build Coastguard Worker } 503*795d594fSAndroid Build Coastguard Worker 504*795d594fSAndroid Build Coastguard Worker { 505*795d594fSAndroid Build Coastguard Worker MethodHandle identity = MethodHandles.identity(short.class); 506*795d594fSAndroid Build Coastguard Worker short value = (short) identity.invoke((short) -59); 507*795d594fSAndroid Build Coastguard Worker if (value != (short) -59) { 508*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + Short.toString(value)); 509*795d594fSAndroid Build Coastguard Worker } 510*795d594fSAndroid Build Coastguard Worker } 511*795d594fSAndroid Build Coastguard Worker 512*795d594fSAndroid Build Coastguard Worker { 513*795d594fSAndroid Build Coastguard Worker MethodHandle identity = MethodHandles.identity(int.class); 514*795d594fSAndroid Build Coastguard Worker int value = (int) identity.invoke(52); 515*795d594fSAndroid Build Coastguard Worker if (value != 52) { 516*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + value); 517*795d594fSAndroid Build Coastguard Worker } 518*795d594fSAndroid Build Coastguard Worker } 519*795d594fSAndroid Build Coastguard Worker 520*795d594fSAndroid Build Coastguard Worker { 521*795d594fSAndroid Build Coastguard Worker MethodHandle identity = MethodHandles.identity(long.class); 522*795d594fSAndroid Build Coastguard Worker long value = (long) identity.invoke(-76l); 523*795d594fSAndroid Build Coastguard Worker if (value != (long) -76) { 524*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + value); 525*795d594fSAndroid Build Coastguard Worker } 526*795d594fSAndroid Build Coastguard Worker } 527*795d594fSAndroid Build Coastguard Worker 528*795d594fSAndroid Build Coastguard Worker { 529*795d594fSAndroid Build Coastguard Worker MethodHandle identity = MethodHandles.identity(float.class); 530*795d594fSAndroid Build Coastguard Worker float value = (float) identity.invoke(56.0f); 531*795d594fSAndroid Build Coastguard Worker if (value != (float) 56.0f) { 532*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + value); 533*795d594fSAndroid Build Coastguard Worker } 534*795d594fSAndroid Build Coastguard Worker } 535*795d594fSAndroid Build Coastguard Worker 536*795d594fSAndroid Build Coastguard Worker { 537*795d594fSAndroid Build Coastguard Worker MethodHandle identity = MethodHandles.identity(double.class); 538*795d594fSAndroid Build Coastguard Worker double value = (double) identity.invoke((double) 72.0); 539*795d594fSAndroid Build Coastguard Worker if (value != (double) 72.0) { 540*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + value); 541*795d594fSAndroid Build Coastguard Worker } 542*795d594fSAndroid Build Coastguard Worker } 543*795d594fSAndroid Build Coastguard Worker 544*795d594fSAndroid Build Coastguard Worker { 545*795d594fSAndroid Build Coastguard Worker MethodHandle identity = MethodHandles.identity(String.class); 546*795d594fSAndroid Build Coastguard Worker String value = (String) identity.invoke("bazman"); 547*795d594fSAndroid Build Coastguard Worker assertEquals("bazman", value); 548*795d594fSAndroid Build Coastguard Worker } 549*795d594fSAndroid Build Coastguard Worker } 550*795d594fSAndroid Build Coastguard Worker testConstant()551*795d594fSAndroid Build Coastguard Worker public static void testConstant() throws Throwable { 552*795d594fSAndroid Build Coastguard Worker // int constants. 553*795d594fSAndroid Build Coastguard Worker { 554*795d594fSAndroid Build Coastguard Worker MethodHandle constant = MethodHandles.constant(int.class, 56); 555*795d594fSAndroid Build Coastguard Worker int value = (int) constant.invoke(); 556*795d594fSAndroid Build Coastguard Worker if (value != 56) { 557*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + value); 558*795d594fSAndroid Build Coastguard Worker } 559*795d594fSAndroid Build Coastguard Worker 560*795d594fSAndroid Build Coastguard Worker // short constant values are converted to int. 561*795d594fSAndroid Build Coastguard Worker constant = MethodHandles.constant(int.class, (short) 52); 562*795d594fSAndroid Build Coastguard Worker value = (int) constant.invoke(); 563*795d594fSAndroid Build Coastguard Worker if (value != 52) { 564*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + value); 565*795d594fSAndroid Build Coastguard Worker } 566*795d594fSAndroid Build Coastguard Worker 567*795d594fSAndroid Build Coastguard Worker // char constant values are converted to int. 568*795d594fSAndroid Build Coastguard Worker constant = MethodHandles.constant(int.class, (char) 'b'); 569*795d594fSAndroid Build Coastguard Worker value = (int) constant.invoke(); 570*795d594fSAndroid Build Coastguard Worker if (value != (int) 'b') { 571*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + value); 572*795d594fSAndroid Build Coastguard Worker } 573*795d594fSAndroid Build Coastguard Worker 574*795d594fSAndroid Build Coastguard Worker // int constant values are converted to int. 575*795d594fSAndroid Build Coastguard Worker constant = MethodHandles.constant(int.class, (byte) 0x1); 576*795d594fSAndroid Build Coastguard Worker value = (int) constant.invoke(); 577*795d594fSAndroid Build Coastguard Worker if (value != 1) { 578*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + value); 579*795d594fSAndroid Build Coastguard Worker } 580*795d594fSAndroid Build Coastguard Worker 581*795d594fSAndroid Build Coastguard Worker // boolean, float, double and long primitive constants are not convertible 582*795d594fSAndroid Build Coastguard Worker // to int, so the handle creation must fail with a CCE. 583*795d594fSAndroid Build Coastguard Worker try { 584*795d594fSAndroid Build Coastguard Worker MethodHandles.constant(int.class, false); 585*795d594fSAndroid Build Coastguard Worker fail(); 586*795d594fSAndroid Build Coastguard Worker } catch (ClassCastException expected) { 587*795d594fSAndroid Build Coastguard Worker } 588*795d594fSAndroid Build Coastguard Worker 589*795d594fSAndroid Build Coastguard Worker try { 590*795d594fSAndroid Build Coastguard Worker MethodHandles.constant(int.class, 0.1f); 591*795d594fSAndroid Build Coastguard Worker fail(); 592*795d594fSAndroid Build Coastguard Worker } catch (ClassCastException expected) { 593*795d594fSAndroid Build Coastguard Worker } 594*795d594fSAndroid Build Coastguard Worker 595*795d594fSAndroid Build Coastguard Worker try { 596*795d594fSAndroid Build Coastguard Worker MethodHandles.constant(int.class, 0.2); 597*795d594fSAndroid Build Coastguard Worker fail(); 598*795d594fSAndroid Build Coastguard Worker } catch (ClassCastException expected) { 599*795d594fSAndroid Build Coastguard Worker } 600*795d594fSAndroid Build Coastguard Worker 601*795d594fSAndroid Build Coastguard Worker try { 602*795d594fSAndroid Build Coastguard Worker MethodHandles.constant(int.class, 73l); 603*795d594fSAndroid Build Coastguard Worker fail(); 604*795d594fSAndroid Build Coastguard Worker } catch (ClassCastException expected) { 605*795d594fSAndroid Build Coastguard Worker } 606*795d594fSAndroid Build Coastguard Worker } 607*795d594fSAndroid Build Coastguard Worker 608*795d594fSAndroid Build Coastguard Worker // long constants. 609*795d594fSAndroid Build Coastguard Worker { 610*795d594fSAndroid Build Coastguard Worker MethodHandle constant = MethodHandles.constant(long.class, 56l); 611*795d594fSAndroid Build Coastguard Worker long value = (long) constant.invoke(); 612*795d594fSAndroid Build Coastguard Worker if (value != 56l) { 613*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + value); 614*795d594fSAndroid Build Coastguard Worker } 615*795d594fSAndroid Build Coastguard Worker 616*795d594fSAndroid Build Coastguard Worker constant = MethodHandles.constant(long.class, (int) 56); 617*795d594fSAndroid Build Coastguard Worker value = (long) constant.invoke(); 618*795d594fSAndroid Build Coastguard Worker if (value != 56l) { 619*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + value); 620*795d594fSAndroid Build Coastguard Worker } 621*795d594fSAndroid Build Coastguard Worker } 622*795d594fSAndroid Build Coastguard Worker 623*795d594fSAndroid Build Coastguard Worker // byte constants. 624*795d594fSAndroid Build Coastguard Worker { 625*795d594fSAndroid Build Coastguard Worker MethodHandle constant = MethodHandles.constant(byte.class, (byte) 0x12); 626*795d594fSAndroid Build Coastguard Worker byte value = (byte) constant.invoke(); 627*795d594fSAndroid Build Coastguard Worker if (value != (byte) 0x12) { 628*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + value); 629*795d594fSAndroid Build Coastguard Worker } 630*795d594fSAndroid Build Coastguard Worker } 631*795d594fSAndroid Build Coastguard Worker 632*795d594fSAndroid Build Coastguard Worker // boolean constants. 633*795d594fSAndroid Build Coastguard Worker { 634*795d594fSAndroid Build Coastguard Worker MethodHandle constant = MethodHandles.constant(boolean.class, true); 635*795d594fSAndroid Build Coastguard Worker boolean value = (boolean) constant.invoke(); 636*795d594fSAndroid Build Coastguard Worker if (!value) { 637*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + value); 638*795d594fSAndroid Build Coastguard Worker } 639*795d594fSAndroid Build Coastguard Worker } 640*795d594fSAndroid Build Coastguard Worker 641*795d594fSAndroid Build Coastguard Worker // char constants. 642*795d594fSAndroid Build Coastguard Worker { 643*795d594fSAndroid Build Coastguard Worker MethodHandle constant = MethodHandles.constant(char.class, 'f'); 644*795d594fSAndroid Build Coastguard Worker char value = (char) constant.invoke(); 645*795d594fSAndroid Build Coastguard Worker if (value != 'f') { 646*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + value); 647*795d594fSAndroid Build Coastguard Worker } 648*795d594fSAndroid Build Coastguard Worker } 649*795d594fSAndroid Build Coastguard Worker 650*795d594fSAndroid Build Coastguard Worker // short constants. 651*795d594fSAndroid Build Coastguard Worker { 652*795d594fSAndroid Build Coastguard Worker MethodHandle constant = MethodHandles.constant(short.class, (short) 123); 653*795d594fSAndroid Build Coastguard Worker short value = (short) constant.invoke(); 654*795d594fSAndroid Build Coastguard Worker if (value != (short) 123) { 655*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + value); 656*795d594fSAndroid Build Coastguard Worker } 657*795d594fSAndroid Build Coastguard Worker } 658*795d594fSAndroid Build Coastguard Worker 659*795d594fSAndroid Build Coastguard Worker // float constants. 660*795d594fSAndroid Build Coastguard Worker { 661*795d594fSAndroid Build Coastguard Worker MethodHandle constant = MethodHandles.constant(float.class, 56.0f); 662*795d594fSAndroid Build Coastguard Worker float value = (float) constant.invoke(); 663*795d594fSAndroid Build Coastguard Worker if (value != 56.0f) { 664*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + value); 665*795d594fSAndroid Build Coastguard Worker } 666*795d594fSAndroid Build Coastguard Worker } 667*795d594fSAndroid Build Coastguard Worker 668*795d594fSAndroid Build Coastguard Worker // double constants. 669*795d594fSAndroid Build Coastguard Worker { 670*795d594fSAndroid Build Coastguard Worker MethodHandle constant = MethodHandles.constant(double.class, 256.0); 671*795d594fSAndroid Build Coastguard Worker double value = (double) constant.invoke(); 672*795d594fSAndroid Build Coastguard Worker if (value != 256.0) { 673*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + value); 674*795d594fSAndroid Build Coastguard Worker } 675*795d594fSAndroid Build Coastguard Worker } 676*795d594fSAndroid Build Coastguard Worker 677*795d594fSAndroid Build Coastguard Worker // reference constants. 678*795d594fSAndroid Build Coastguard Worker { 679*795d594fSAndroid Build Coastguard Worker MethodHandle constant = MethodHandles.constant(String.class, "256.0"); 680*795d594fSAndroid Build Coastguard Worker String value = (String) constant.invoke(); 681*795d594fSAndroid Build Coastguard Worker assertEquals("256.0", value); 682*795d594fSAndroid Build Coastguard Worker } 683*795d594fSAndroid Build Coastguard Worker } 684*795d594fSAndroid Build Coastguard Worker testBindTo()685*795d594fSAndroid Build Coastguard Worker public static void testBindTo() throws Throwable { 686*795d594fSAndroid Build Coastguard Worker MethodHandle stringCharAt = MethodHandles.lookup().findVirtual( 687*795d594fSAndroid Build Coastguard Worker String.class, "charAt", MethodType.methodType(char.class, int.class)); 688*795d594fSAndroid Build Coastguard Worker 689*795d594fSAndroid Build Coastguard Worker char value = (char) stringCharAt.invoke("foo", 0); 690*795d594fSAndroid Build Coastguard Worker if (value != 'f') { 691*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + value); 692*795d594fSAndroid Build Coastguard Worker } 693*795d594fSAndroid Build Coastguard Worker 694*795d594fSAndroid Build Coastguard Worker MethodHandle bound = stringCharAt.bindTo("foo"); 695*795d594fSAndroid Build Coastguard Worker value = (char) bound.invoke(0); 696*795d594fSAndroid Build Coastguard Worker if (value != 'f') { 697*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + value); 698*795d594fSAndroid Build Coastguard Worker } 699*795d594fSAndroid Build Coastguard Worker 700*795d594fSAndroid Build Coastguard Worker try { 701*795d594fSAndroid Build Coastguard Worker stringCharAt.bindTo(new Object()); 702*795d594fSAndroid Build Coastguard Worker fail(); 703*795d594fSAndroid Build Coastguard Worker } catch (ClassCastException expected) { 704*795d594fSAndroid Build Coastguard Worker } 705*795d594fSAndroid Build Coastguard Worker 706*795d594fSAndroid Build Coastguard Worker bound = stringCharAt.bindTo(null); 707*795d594fSAndroid Build Coastguard Worker try { 708*795d594fSAndroid Build Coastguard Worker bound.invoke(0); 709*795d594fSAndroid Build Coastguard Worker fail(); 710*795d594fSAndroid Build Coastguard Worker } catch (NullPointerException expected) { 711*795d594fSAndroid Build Coastguard Worker } 712*795d594fSAndroid Build Coastguard Worker 713*795d594fSAndroid Build Coastguard Worker MethodHandle integerParseInt = MethodHandles.lookup().findStatic( 714*795d594fSAndroid Build Coastguard Worker Integer.class, "parseInt", MethodType.methodType(int.class, String.class)); 715*795d594fSAndroid Build Coastguard Worker 716*795d594fSAndroid Build Coastguard Worker bound = integerParseInt.bindTo("78452"); 717*795d594fSAndroid Build Coastguard Worker int intValue = (int) bound.invoke(); 718*795d594fSAndroid Build Coastguard Worker if (intValue != 78452) { 719*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + intValue); 720*795d594fSAndroid Build Coastguard Worker } 721*795d594fSAndroid Build Coastguard Worker 722*795d594fSAndroid Build Coastguard Worker class Locals { 723*795d594fSAndroid Build Coastguard Worker public int intValue; 724*795d594fSAndroid Build Coastguard Worker }; 725*795d594fSAndroid Build Coastguard Worker 726*795d594fSAndroid Build Coastguard Worker MethodHandle setter1 = MethodHandles.lookup().findSetter(Locals.class, "intValue", int.class); 727*795d594fSAndroid Build Coastguard Worker Locals locals = new Locals(); 728*795d594fSAndroid Build Coastguard Worker setter1.invoke(locals, 1); 729*795d594fSAndroid Build Coastguard Worker assertEquals(1, locals.intValue); 730*795d594fSAndroid Build Coastguard Worker 731*795d594fSAndroid Build Coastguard Worker MethodHandle setter2 = 732*795d594fSAndroid Build Coastguard Worker MethodHandles.insertArguments(setter1.bindTo(locals), 0, Integer.valueOf(2)); 733*795d594fSAndroid Build Coastguard Worker setter2.invoke(); 734*795d594fSAndroid Build Coastguard Worker assertEquals(2, locals.intValue); 735*795d594fSAndroid Build Coastguard Worker 736*795d594fSAndroid Build Coastguard Worker VarHandle vh = MethodHandles.lookup().findVarHandle(Locals.class, "intValue", int.class); 737*795d594fSAndroid Build Coastguard Worker MethodHandle setter3 = vh.toMethodHandle(VarHandle.AccessMode.GET_AND_SET); 738*795d594fSAndroid Build Coastguard Worker assertEquals(setter3.type().toString(), 739*795d594fSAndroid Build Coastguard Worker MethodType.methodType(int.class, Locals.class, int.class).toString()); 740*795d594fSAndroid Build Coastguard Worker assertEquals(2, (int) setter3.invoke(locals, 3)); 741*795d594fSAndroid Build Coastguard Worker 742*795d594fSAndroid Build Coastguard Worker MethodHandle setter4 = 743*795d594fSAndroid Build Coastguard Worker MethodHandles.varHandleInvoker(VarHandle.AccessMode.GET_AND_SET, 744*795d594fSAndroid Build Coastguard Worker MethodType.methodType(int.class, Locals.class, int.class)); 745*795d594fSAndroid Build Coastguard Worker assertEquals(3, (int) setter4.invoke(vh, locals, 4)); 746*795d594fSAndroid Build Coastguard Worker 747*795d594fSAndroid Build Coastguard Worker MethodHandle setter5 = setter4.bindTo(vh); 748*795d594fSAndroid Build Coastguard Worker assertEquals(4, (int) setter5.invoke(locals, 5)); 749*795d594fSAndroid Build Coastguard Worker 750*795d594fSAndroid Build Coastguard Worker MethodHandle setter6 = MethodHandles.insertArguments(setter5, 0, locals, 6); 751*795d594fSAndroid Build Coastguard Worker assertEquals(5, (int) setter6.invoke()); 752*795d594fSAndroid Build Coastguard Worker assertEquals(locals.intValue, 6); 753*795d594fSAndroid Build Coastguard Worker } 754*795d594fSAndroid Build Coastguard Worker filterReturnValue_target(int a)755*795d594fSAndroid Build Coastguard Worker public static String filterReturnValue_target(int a) { 756*795d594fSAndroid Build Coastguard Worker return "ReturnValue" + a; 757*795d594fSAndroid Build Coastguard Worker } 758*795d594fSAndroid Build Coastguard Worker filterReturnValue_filter(String value)759*795d594fSAndroid Build Coastguard Worker public static boolean filterReturnValue_filter(String value) { 760*795d594fSAndroid Build Coastguard Worker return value.indexOf("42") != -1; 761*795d594fSAndroid Build Coastguard Worker } 762*795d594fSAndroid Build Coastguard Worker filterReturnValue_intTarget(String a)763*795d594fSAndroid Build Coastguard Worker public static int filterReturnValue_intTarget(String a) { 764*795d594fSAndroid Build Coastguard Worker return Integer.parseInt(a); 765*795d594fSAndroid Build Coastguard Worker } 766*795d594fSAndroid Build Coastguard Worker filterReturnValue_intFilter(int b)767*795d594fSAndroid Build Coastguard Worker public static int filterReturnValue_intFilter(int b) { 768*795d594fSAndroid Build Coastguard Worker return b + 1; 769*795d594fSAndroid Build Coastguard Worker } 770*795d594fSAndroid Build Coastguard Worker filterReturnValue_voidTarget()771*795d594fSAndroid Build Coastguard Worker public static void filterReturnValue_voidTarget() { 772*795d594fSAndroid Build Coastguard Worker } 773*795d594fSAndroid Build Coastguard Worker filterReturnValue_voidFilter()774*795d594fSAndroid Build Coastguard Worker public static int filterReturnValue_voidFilter() { 775*795d594fSAndroid Build Coastguard Worker return 42; 776*795d594fSAndroid Build Coastguard Worker } 777*795d594fSAndroid Build Coastguard Worker testFilterReturnValue()778*795d594fSAndroid Build Coastguard Worker public static void testFilterReturnValue() throws Throwable { 779*795d594fSAndroid Build Coastguard Worker // A target that returns a reference. 780*795d594fSAndroid Build Coastguard Worker { 781*795d594fSAndroid Build Coastguard Worker final MethodHandle target = MethodHandles.lookup().findStatic(Main.class, 782*795d594fSAndroid Build Coastguard Worker "filterReturnValue_target", MethodType.methodType(String.class, int.class)); 783*795d594fSAndroid Build Coastguard Worker final MethodHandle filter = MethodHandles.lookup().findStatic(Main.class, 784*795d594fSAndroid Build Coastguard Worker "filterReturnValue_filter", MethodType.methodType(boolean.class, String.class)); 785*795d594fSAndroid Build Coastguard Worker 786*795d594fSAndroid Build Coastguard Worker MethodHandle adapter = MethodHandles.filterReturnValue(target, filter); 787*795d594fSAndroid Build Coastguard Worker 788*795d594fSAndroid Build Coastguard Worker boolean value = (boolean) adapter.invoke((int) 42); 789*795d594fSAndroid Build Coastguard Worker if (!value) { 790*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + value); 791*795d594fSAndroid Build Coastguard Worker } 792*795d594fSAndroid Build Coastguard Worker value = (boolean) adapter.invoke((int) 43); 793*795d594fSAndroid Build Coastguard Worker if (value) { 794*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + value); 795*795d594fSAndroid Build Coastguard Worker } 796*795d594fSAndroid Build Coastguard Worker } 797*795d594fSAndroid Build Coastguard Worker 798*795d594fSAndroid Build Coastguard Worker // A target that returns a primitive. 799*795d594fSAndroid Build Coastguard Worker { 800*795d594fSAndroid Build Coastguard Worker final MethodHandle target = MethodHandles.lookup().findStatic(Main.class, 801*795d594fSAndroid Build Coastguard Worker "filterReturnValue_intTarget", MethodType.methodType(int.class, String.class)); 802*795d594fSAndroid Build Coastguard Worker final MethodHandle filter = MethodHandles.lookup().findStatic(Main.class, 803*795d594fSAndroid Build Coastguard Worker "filterReturnValue_intFilter", MethodType.methodType(int.class, int.class)); 804*795d594fSAndroid Build Coastguard Worker 805*795d594fSAndroid Build Coastguard Worker MethodHandle adapter = MethodHandles.filterReturnValue(target, filter); 806*795d594fSAndroid Build Coastguard Worker 807*795d594fSAndroid Build Coastguard Worker int value = (int) adapter.invoke("56"); 808*795d594fSAndroid Build Coastguard Worker if (value != 57) { 809*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + value); 810*795d594fSAndroid Build Coastguard Worker } 811*795d594fSAndroid Build Coastguard Worker } 812*795d594fSAndroid Build Coastguard Worker 813*795d594fSAndroid Build Coastguard Worker // A target that returns void. 814*795d594fSAndroid Build Coastguard Worker { 815*795d594fSAndroid Build Coastguard Worker final MethodHandle target = MethodHandles.lookup().findStatic(Main.class, 816*795d594fSAndroid Build Coastguard Worker "filterReturnValue_voidTarget", MethodType.methodType(void.class)); 817*795d594fSAndroid Build Coastguard Worker final MethodHandle filter = MethodHandles.lookup().findStatic(Main.class, 818*795d594fSAndroid Build Coastguard Worker "filterReturnValue_voidFilter", MethodType.methodType(int.class)); 819*795d594fSAndroid Build Coastguard Worker 820*795d594fSAndroid Build Coastguard Worker MethodHandle adapter = MethodHandles.filterReturnValue(target, filter); 821*795d594fSAndroid Build Coastguard Worker 822*795d594fSAndroid Build Coastguard Worker int value = (int) adapter.invoke(); 823*795d594fSAndroid Build Coastguard Worker if (value != 42) { 824*795d594fSAndroid Build Coastguard Worker fail("Unexpected value: " + value); 825*795d594fSAndroid Build Coastguard Worker } 826*795d594fSAndroid Build Coastguard Worker } 827*795d594fSAndroid Build Coastguard Worker } 828*795d594fSAndroid Build Coastguard Worker permuteArguments_callee(boolean a, byte b, char c, short d, int e, long f, float g, double h)829*795d594fSAndroid Build Coastguard Worker public static void permuteArguments_callee(boolean a, byte b, char c, 830*795d594fSAndroid Build Coastguard Worker short d, int e, long f, float g, double h) { 831*795d594fSAndroid Build Coastguard Worker if (a == true && b == (byte) 'b' && c == 'c' && d == (short) 56 && 832*795d594fSAndroid Build Coastguard Worker e == 78 && f == (long) 97 && g == 98.0f && f == 97.0) { 833*795d594fSAndroid Build Coastguard Worker return; 834*795d594fSAndroid Build Coastguard Worker } 835*795d594fSAndroid Build Coastguard Worker 836*795d594fSAndroid Build Coastguard Worker fail("Unexpected arguments: " + a + ", " + b + ", " + c 837*795d594fSAndroid Build Coastguard Worker + ", " + d + ", " + e + ", " + f + ", " + g + ", " + h); 838*795d594fSAndroid Build Coastguard Worker } 839*795d594fSAndroid Build Coastguard Worker permuteArguments_boxingCallee(boolean a, Integer b)840*795d594fSAndroid Build Coastguard Worker public static void permuteArguments_boxingCallee(boolean a, Integer b) { 841*795d594fSAndroid Build Coastguard Worker if (a && b.intValue() == 42) { 842*795d594fSAndroid Build Coastguard Worker return; 843*795d594fSAndroid Build Coastguard Worker } 844*795d594fSAndroid Build Coastguard Worker 845*795d594fSAndroid Build Coastguard Worker fail("Unexpected arguments: " + a + ", " + b); 846*795d594fSAndroid Build Coastguard Worker } 847*795d594fSAndroid Build Coastguard Worker testPermuteArguments()848*795d594fSAndroid Build Coastguard Worker public static void testPermuteArguments() throws Throwable { 849*795d594fSAndroid Build Coastguard Worker { 850*795d594fSAndroid Build Coastguard Worker final MethodHandle target = MethodHandles.lookup().findStatic( 851*795d594fSAndroid Build Coastguard Worker Main.class, "permuteArguments_callee", 852*795d594fSAndroid Build Coastguard Worker MethodType.methodType(void.class, new Class<?>[] { 853*795d594fSAndroid Build Coastguard Worker boolean.class, byte.class, char.class, short.class, int.class, 854*795d594fSAndroid Build Coastguard Worker long.class, float.class, double.class })); 855*795d594fSAndroid Build Coastguard Worker 856*795d594fSAndroid Build Coastguard Worker final MethodType newType = MethodType.methodType(void.class, new Class<?>[] { 857*795d594fSAndroid Build Coastguard Worker double.class, float.class, long.class, int.class, short.class, char.class, 858*795d594fSAndroid Build Coastguard Worker byte.class, boolean.class }); 859*795d594fSAndroid Build Coastguard Worker 860*795d594fSAndroid Build Coastguard Worker final MethodHandle permutation = MethodHandles.permuteArguments( 861*795d594fSAndroid Build Coastguard Worker target, newType, new int[] { 7, 6, 5, 4, 3, 2, 1, 0 }); 862*795d594fSAndroid Build Coastguard Worker 863*795d594fSAndroid Build Coastguard Worker permutation.invoke((double) 97.0, (float) 98.0f, (long) 97, 78, 864*795d594fSAndroid Build Coastguard Worker (short) 56, 'c', (byte) 'b', (boolean) true); 865*795d594fSAndroid Build Coastguard Worker 866*795d594fSAndroid Build Coastguard Worker // The permutation array was not of the right length. 867*795d594fSAndroid Build Coastguard Worker try { 868*795d594fSAndroid Build Coastguard Worker MethodHandles.permuteArguments(target, newType, 869*795d594fSAndroid Build Coastguard Worker new int[] { 7 }); 870*795d594fSAndroid Build Coastguard Worker fail(); 871*795d594fSAndroid Build Coastguard Worker } catch (IllegalArgumentException expected) { 872*795d594fSAndroid Build Coastguard Worker } 873*795d594fSAndroid Build Coastguard Worker 874*795d594fSAndroid Build Coastguard Worker // The permutation array has an element that's out of bounds 875*795d594fSAndroid Build Coastguard Worker // (there's no argument with idx == 8). 876*795d594fSAndroid Build Coastguard Worker try { 877*795d594fSAndroid Build Coastguard Worker MethodHandles.permuteArguments(target, newType, 878*795d594fSAndroid Build Coastguard Worker new int[] { 8, 6, 5, 4, 3, 2, 1, 0 }); 879*795d594fSAndroid Build Coastguard Worker fail(); 880*795d594fSAndroid Build Coastguard Worker } catch (IllegalArgumentException expected) { 881*795d594fSAndroid Build Coastguard Worker } 882*795d594fSAndroid Build Coastguard Worker 883*795d594fSAndroid Build Coastguard Worker // The permutation array maps to an incorrect type. 884*795d594fSAndroid Build Coastguard Worker try { 885*795d594fSAndroid Build Coastguard Worker MethodHandles.permuteArguments(target, newType, 886*795d594fSAndroid Build Coastguard Worker new int[] { 7, 7, 5, 4, 3, 2, 1, 0 }); 887*795d594fSAndroid Build Coastguard Worker fail(); 888*795d594fSAndroid Build Coastguard Worker } catch (IllegalArgumentException expected) { 889*795d594fSAndroid Build Coastguard Worker } 890*795d594fSAndroid Build Coastguard Worker } 891*795d594fSAndroid Build Coastguard Worker 892*795d594fSAndroid Build Coastguard Worker // Tests for reference arguments as well as permutations that 893*795d594fSAndroid Build Coastguard Worker // repeat arguments. 894*795d594fSAndroid Build Coastguard Worker { 895*795d594fSAndroid Build Coastguard Worker final MethodHandle target = MethodHandles.lookup().findVirtual( 896*795d594fSAndroid Build Coastguard Worker String.class, "concat", MethodType.methodType(String.class, String.class)); 897*795d594fSAndroid Build Coastguard Worker 898*795d594fSAndroid Build Coastguard Worker final MethodType newType = MethodType.methodType(String.class, String.class, 899*795d594fSAndroid Build Coastguard Worker String.class); 900*795d594fSAndroid Build Coastguard Worker 901*795d594fSAndroid Build Coastguard Worker assertEquals("foobar", (String) target.invoke("foo", "bar")); 902*795d594fSAndroid Build Coastguard Worker 903*795d594fSAndroid Build Coastguard Worker MethodHandle permutation = MethodHandles.permuteArguments(target, 904*795d594fSAndroid Build Coastguard Worker newType, new int[] { 1, 0 }); 905*795d594fSAndroid Build Coastguard Worker assertEquals("barfoo", (String) permutation.invoke("foo", "bar")); 906*795d594fSAndroid Build Coastguard Worker 907*795d594fSAndroid Build Coastguard Worker permutation = MethodHandles.permuteArguments(target, newType, new int[] { 0, 0 }); 908*795d594fSAndroid Build Coastguard Worker assertEquals("foofoo", (String) permutation.invoke("foo", "bar")); 909*795d594fSAndroid Build Coastguard Worker 910*795d594fSAndroid Build Coastguard Worker permutation = MethodHandles.permuteArguments(target, newType, new int[] { 1, 1 }); 911*795d594fSAndroid Build Coastguard Worker assertEquals("barbar", (String) permutation.invoke("foo", "bar")); 912*795d594fSAndroid Build Coastguard Worker } 913*795d594fSAndroid Build Coastguard Worker 914*795d594fSAndroid Build Coastguard Worker // Tests for boxing and unboxing. 915*795d594fSAndroid Build Coastguard Worker { 916*795d594fSAndroid Build Coastguard Worker final MethodHandle target = MethodHandles.lookup().findStatic( 917*795d594fSAndroid Build Coastguard Worker Main.class, "permuteArguments_boxingCallee", 918*795d594fSAndroid Build Coastguard Worker MethodType.methodType(void.class, new Class<?>[] { boolean.class, Integer.class })); 919*795d594fSAndroid Build Coastguard Worker 920*795d594fSAndroid Build Coastguard Worker final MethodType newType = MethodType.methodType(void.class, 921*795d594fSAndroid Build Coastguard Worker new Class<?>[] { Integer.class, boolean.class }); 922*795d594fSAndroid Build Coastguard Worker 923*795d594fSAndroid Build Coastguard Worker MethodHandle permutation = MethodHandles.permuteArguments(target, 924*795d594fSAndroid Build Coastguard Worker newType, new int[] { 1, 0 }); 925*795d594fSAndroid Build Coastguard Worker 926*795d594fSAndroid Build Coastguard Worker permutation.invoke(42, true); 927*795d594fSAndroid Build Coastguard Worker permutation.invoke(42, Boolean.TRUE); 928*795d594fSAndroid Build Coastguard Worker permutation.invoke(Integer.valueOf(42), true); 929*795d594fSAndroid Build Coastguard Worker permutation.invoke(Integer.valueOf(42), Boolean.TRUE); 930*795d594fSAndroid Build Coastguard Worker } 931*795d594fSAndroid Build Coastguard Worker } 932*795d594fSAndroid Build Coastguard Worker returnBar()933*795d594fSAndroid Build Coastguard Worker private static Object returnBar() { 934*795d594fSAndroid Build Coastguard Worker return "bar"; 935*795d594fSAndroid Build Coastguard Worker } 936*795d594fSAndroid Build Coastguard Worker testInvokers()937*795d594fSAndroid Build Coastguard Worker public static void testInvokers() throws Throwable { 938*795d594fSAndroid Build Coastguard Worker final MethodType targetType = MethodType.methodType(String.class, String.class); 939*795d594fSAndroid Build Coastguard Worker final MethodHandle target = MethodHandles.lookup().findVirtual( 940*795d594fSAndroid Build Coastguard Worker String.class, "concat", targetType); 941*795d594fSAndroid Build Coastguard Worker 942*795d594fSAndroid Build Coastguard Worker MethodHandle invoker = MethodHandles.invoker(target.type()); 943*795d594fSAndroid Build Coastguard Worker assertEquals("barbar", (String) invoker.invoke(target, "bar", "bar")); 944*795d594fSAndroid Build Coastguard Worker assertEquals("barbar", (String) invoker.invoke(target, (Object) returnBar(), "bar")); 945*795d594fSAndroid Build Coastguard Worker try { 946*795d594fSAndroid Build Coastguard Worker String foo = (String) invoker.invoke(target, "bar", "bar", 24); 947*795d594fSAndroid Build Coastguard Worker fail(); 948*795d594fSAndroid Build Coastguard Worker } catch (WrongMethodTypeException expected) { 949*795d594fSAndroid Build Coastguard Worker } 950*795d594fSAndroid Build Coastguard Worker 951*795d594fSAndroid Build Coastguard Worker MethodHandle exactInvoker = MethodHandles.exactInvoker(target.type()); 952*795d594fSAndroid Build Coastguard Worker assertEquals("barbar", (String) exactInvoker.invoke(target, "bar", "bar")); 953*795d594fSAndroid Build Coastguard Worker assertEquals("barbar", (String) exactInvoker.invoke(target, (Object) returnBar(), "bar")); 954*795d594fSAndroid Build Coastguard Worker try { 955*795d594fSAndroid Build Coastguard Worker assertEquals("barbar", (String) invoker.invoke(target, (Object) Integer.valueOf(7), "bar")); 956*795d594fSAndroid Build Coastguard Worker fail(); 957*795d594fSAndroid Build Coastguard Worker } catch (ClassCastException expected) { 958*795d594fSAndroid Build Coastguard Worker } 959*795d594fSAndroid Build Coastguard Worker try { 960*795d594fSAndroid Build Coastguard Worker assertEquals("barbar", (String) invoker.invoke(target, (Object) null, "bar")); 961*795d594fSAndroid Build Coastguard Worker fail(); 962*795d594fSAndroid Build Coastguard Worker } catch (NullPointerException expected) { 963*795d594fSAndroid Build Coastguard Worker } 964*795d594fSAndroid Build Coastguard Worker exactInvoker.invoke(target, (Object) returnBar(), "bar"); 965*795d594fSAndroid Build Coastguard Worker 966*795d594fSAndroid Build Coastguard Worker try { 967*795d594fSAndroid Build Coastguard Worker String foo = (String) exactInvoker.invoke(target, "bar", "bar", 24); 968*795d594fSAndroid Build Coastguard Worker fail(); 969*795d594fSAndroid Build Coastguard Worker } catch (WrongMethodTypeException expected) { 970*795d594fSAndroid Build Coastguard Worker } 971*795d594fSAndroid Build Coastguard Worker } 972*795d594fSAndroid Build Coastguard Worker spreadReferences(String a, String b, String c)973*795d594fSAndroid Build Coastguard Worker public static int spreadReferences(String a, String b, String c) { 974*795d594fSAndroid Build Coastguard Worker System.out.println("a: " + a + ", b:" + b + ", c: " + c); 975*795d594fSAndroid Build Coastguard Worker return 42; 976*795d594fSAndroid Build Coastguard Worker } 977*795d594fSAndroid Build Coastguard Worker spreadReferences_Unbox(String a, int b)978*795d594fSAndroid Build Coastguard Worker public static int spreadReferences_Unbox(String a, int b) { 979*795d594fSAndroid Build Coastguard Worker System.out.println("a: " + a + ", b:" + b); 980*795d594fSAndroid Build Coastguard Worker return 43; 981*795d594fSAndroid Build Coastguard Worker } 982*795d594fSAndroid Build Coastguard Worker testSpreaders_reference()983*795d594fSAndroid Build Coastguard Worker public static void testSpreaders_reference() throws Throwable { 984*795d594fSAndroid Build Coastguard Worker MethodType methodType = MethodType.methodType(int.class, 985*795d594fSAndroid Build Coastguard Worker new Class<?>[] { String.class, String.class, String.class }); 986*795d594fSAndroid Build Coastguard Worker MethodHandle delegate = MethodHandles.lookup().findStatic( 987*795d594fSAndroid Build Coastguard Worker Main.class, "spreadReferences", methodType); 988*795d594fSAndroid Build Coastguard Worker 989*795d594fSAndroid Build Coastguard Worker // Basic checks on array lengths. 990*795d594fSAndroid Build Coastguard Worker // 991*795d594fSAndroid Build Coastguard Worker // Array size = 0 992*795d594fSAndroid Build Coastguard Worker MethodHandle mhAsSpreader = delegate.asSpreader(String[].class, 0); 993*795d594fSAndroid Build Coastguard Worker int ret = (int) mhAsSpreader.invoke("a", "b", "c", new String[] {}); 994*795d594fSAndroid Build Coastguard Worker assertEquals(42, ret); 995*795d594fSAndroid Build Coastguard Worker // Array size = 1 996*795d594fSAndroid Build Coastguard Worker mhAsSpreader = delegate.asSpreader(String[].class, 1); 997*795d594fSAndroid Build Coastguard Worker ret = (int) mhAsSpreader.invoke("a", "b", new String[] { "c" }); 998*795d594fSAndroid Build Coastguard Worker assertEquals(42, ret); 999*795d594fSAndroid Build Coastguard Worker // Array size = 2 1000*795d594fSAndroid Build Coastguard Worker mhAsSpreader = delegate.asSpreader(String[].class, 2); 1001*795d594fSAndroid Build Coastguard Worker ret = (int) mhAsSpreader.invoke("a", new String[] { "b", "c" }); 1002*795d594fSAndroid Build Coastguard Worker assertEquals(42, ret); 1003*795d594fSAndroid Build Coastguard Worker // Array size = 3 1004*795d594fSAndroid Build Coastguard Worker mhAsSpreader = delegate.asSpreader(String[].class, 3); 1005*795d594fSAndroid Build Coastguard Worker ret = (int) mhAsSpreader.invoke(new String[] { "a", "b", "c"}); 1006*795d594fSAndroid Build Coastguard Worker assertEquals(42, ret); 1007*795d594fSAndroid Build Coastguard Worker 1008*795d594fSAndroid Build Coastguard Worker // Exception case, array size = 4 is illegal. 1009*795d594fSAndroid Build Coastguard Worker try { 1010*795d594fSAndroid Build Coastguard Worker delegate.asSpreader(String[].class, 4); 1011*795d594fSAndroid Build Coastguard Worker fail(); 1012*795d594fSAndroid Build Coastguard Worker } catch (IllegalArgumentException expected) { 1013*795d594fSAndroid Build Coastguard Worker } 1014*795d594fSAndroid Build Coastguard Worker 1015*795d594fSAndroid Build Coastguard Worker // Exception case, calling with an arg of the wrong size. 1016*795d594fSAndroid Build Coastguard Worker // Array size = 3 1017*795d594fSAndroid Build Coastguard Worker mhAsSpreader = delegate.asSpreader(String[].class, 3); 1018*795d594fSAndroid Build Coastguard Worker try { 1019*795d594fSAndroid Build Coastguard Worker ret = (int) mhAsSpreader.invoke(new String[] { "a", "b"}); 1020*795d594fSAndroid Build Coastguard Worker } catch (IllegalArgumentException expected) { 1021*795d594fSAndroid Build Coastguard Worker } 1022*795d594fSAndroid Build Coastguard Worker 1023*795d594fSAndroid Build Coastguard Worker // Various other hijinks, pass as Object[] arrays, Object etc. 1024*795d594fSAndroid Build Coastguard Worker mhAsSpreader = delegate.asSpreader(Object[].class, 2); 1025*795d594fSAndroid Build Coastguard Worker ret = (int) mhAsSpreader.invoke("a", new String[] { "b", "c" }); 1026*795d594fSAndroid Build Coastguard Worker assertEquals(42, ret); 1027*795d594fSAndroid Build Coastguard Worker 1028*795d594fSAndroid Build Coastguard Worker mhAsSpreader = delegate.asSpreader(Object[].class, 2); 1029*795d594fSAndroid Build Coastguard Worker ret = (int) mhAsSpreader.invoke("a", new Object[] { "b", "c" }); 1030*795d594fSAndroid Build Coastguard Worker assertEquals(42, ret); 1031*795d594fSAndroid Build Coastguard Worker 1032*795d594fSAndroid Build Coastguard Worker mhAsSpreader = delegate.asSpreader(Object[].class, 2); 1033*795d594fSAndroid Build Coastguard Worker ret = (int) mhAsSpreader.invoke("a", (Object) new Object[] { "b", "c" }); 1034*795d594fSAndroid Build Coastguard Worker assertEquals(42, ret); 1035*795d594fSAndroid Build Coastguard Worker 1036*795d594fSAndroid Build Coastguard Worker // Test implicit unboxing. 1037*795d594fSAndroid Build Coastguard Worker MethodType methodType2 = MethodType.methodType(int.class, 1038*795d594fSAndroid Build Coastguard Worker new Class<?>[] { String.class, int.class }); 1039*795d594fSAndroid Build Coastguard Worker MethodHandle delegate2 = MethodHandles.lookup().findStatic( 1040*795d594fSAndroid Build Coastguard Worker Main.class, "spreadReferences_Unbox", methodType2); 1041*795d594fSAndroid Build Coastguard Worker 1042*795d594fSAndroid Build Coastguard Worker // .. with an Integer[] array. 1043*795d594fSAndroid Build Coastguard Worker mhAsSpreader = delegate2.asSpreader(Integer[].class, 1); 1044*795d594fSAndroid Build Coastguard Worker ret = (int) mhAsSpreader.invoke("a", new Integer[] { 43 }); 1045*795d594fSAndroid Build Coastguard Worker assertEquals(43, ret); 1046*795d594fSAndroid Build Coastguard Worker 1047*795d594fSAndroid Build Coastguard Worker // .. with an Integer[] array declared as an Object[] argument type. 1048*795d594fSAndroid Build Coastguard Worker mhAsSpreader = delegate2.asSpreader(Object[].class, 1); 1049*795d594fSAndroid Build Coastguard Worker ret = (int) mhAsSpreader.invoke("a", new Integer[] { 43 }); 1050*795d594fSAndroid Build Coastguard Worker assertEquals(43, ret); 1051*795d594fSAndroid Build Coastguard Worker 1052*795d594fSAndroid Build Coastguard Worker // .. with an Object[] array. 1053*795d594fSAndroid Build Coastguard Worker mhAsSpreader = delegate2.asSpreader(Object[].class, 1); 1054*795d594fSAndroid Build Coastguard Worker ret = (int) mhAsSpreader.invoke("a", new Object[] { Integer.valueOf(43)}); 1055*795d594fSAndroid Build Coastguard Worker assertEquals(43, ret); 1056*795d594fSAndroid Build Coastguard Worker 1057*795d594fSAndroid Build Coastguard Worker // -- Part 2-- 1058*795d594fSAndroid Build Coastguard Worker // Run a subset of these tests on MethodHandles.spreadInvoker, which only accepts 1059*795d594fSAndroid Build Coastguard Worker // a trailing argument type of Object[]. 1060*795d594fSAndroid Build Coastguard Worker MethodHandle spreadInvoker = MethodHandles.spreadInvoker(methodType2, 1); 1061*795d594fSAndroid Build Coastguard Worker ret = (int) spreadInvoker.invoke(delegate2, "a", new Object[] { Integer.valueOf(43)}); 1062*795d594fSAndroid Build Coastguard Worker assertEquals(43, ret); 1063*795d594fSAndroid Build Coastguard Worker 1064*795d594fSAndroid Build Coastguard Worker ret = (int) spreadInvoker.invoke(delegate2, "a", new Integer[] { 43 }); 1065*795d594fSAndroid Build Coastguard Worker assertEquals(43, ret); 1066*795d594fSAndroid Build Coastguard Worker 1067*795d594fSAndroid Build Coastguard Worker // NOTE: Annoyingly, the second argument here is leadingArgCount and not 1068*795d594fSAndroid Build Coastguard Worker // arrayLength. 1069*795d594fSAndroid Build Coastguard Worker spreadInvoker = MethodHandles.spreadInvoker(methodType, 3); 1070*795d594fSAndroid Build Coastguard Worker ret = (int) spreadInvoker.invoke(delegate, "a", "b", "c", new String[] {}); 1071*795d594fSAndroid Build Coastguard Worker assertEquals(42, ret); 1072*795d594fSAndroid Build Coastguard Worker 1073*795d594fSAndroid Build Coastguard Worker spreadInvoker = MethodHandles.spreadInvoker(methodType, 0); 1074*795d594fSAndroid Build Coastguard Worker ret = (int) spreadInvoker.invoke(delegate, new String[] { "a", "b", "c" }); 1075*795d594fSAndroid Build Coastguard Worker assertEquals(42, ret); 1076*795d594fSAndroid Build Coastguard Worker 1077*795d594fSAndroid Build Coastguard Worker // Exact invokes: Double check that the expected parameter type is 1078*795d594fSAndroid Build Coastguard Worker // Object[] and not T[]. 1079*795d594fSAndroid Build Coastguard Worker try { 1080*795d594fSAndroid Build Coastguard Worker spreadInvoker.invokeExact(delegate, new String[] { "a", "b", "c" }); 1081*795d594fSAndroid Build Coastguard Worker fail(); 1082*795d594fSAndroid Build Coastguard Worker } catch (WrongMethodTypeException expected) { 1083*795d594fSAndroid Build Coastguard Worker } 1084*795d594fSAndroid Build Coastguard Worker 1085*795d594fSAndroid Build Coastguard Worker ret = (int) spreadInvoker.invoke(delegate, new Object[] { "a", "b", "c" }); 1086*795d594fSAndroid Build Coastguard Worker assertEquals(42, ret); 1087*795d594fSAndroid Build Coastguard Worker } 1088*795d594fSAndroid Build Coastguard Worker spreadBoolean(String a, Boolean b, boolean c)1089*795d594fSAndroid Build Coastguard Worker public static int spreadBoolean(String a, Boolean b, boolean c) { 1090*795d594fSAndroid Build Coastguard Worker System.out.println("a: " + a + ", b:" + b + ", c: " + c); 1091*795d594fSAndroid Build Coastguard Worker return 44; 1092*795d594fSAndroid Build Coastguard Worker } 1093*795d594fSAndroid Build Coastguard Worker spreadByte(String a, Byte b, byte c, short d, int e, long f, float g, double h)1094*795d594fSAndroid Build Coastguard Worker public static int spreadByte(String a, Byte b, byte c, 1095*795d594fSAndroid Build Coastguard Worker short d, int e, long f, float g, double h) { 1096*795d594fSAndroid Build Coastguard Worker System.out.println("a: " + a + ", b:" + b + ", c: " + c + 1097*795d594fSAndroid Build Coastguard Worker ", d: " + d + ", e: " + e + ", f:" + f + ", g: " + g + 1098*795d594fSAndroid Build Coastguard Worker ", h: " + h); 1099*795d594fSAndroid Build Coastguard Worker return 45; 1100*795d594fSAndroid Build Coastguard Worker } 1101*795d594fSAndroid Build Coastguard Worker spreadChar(String a, Character b, char c, int d, long e, float f, double g)1102*795d594fSAndroid Build Coastguard Worker public static int spreadChar(String a, Character b, char c, 1103*795d594fSAndroid Build Coastguard Worker int d, long e, float f, double g) { 1104*795d594fSAndroid Build Coastguard Worker System.out.println("a: " + a + ", b:" + b + ", c: " + c + 1105*795d594fSAndroid Build Coastguard Worker ", d: " + d + ", e: " + e + ", f:" + f + ", g: " + g); 1106*795d594fSAndroid Build Coastguard Worker return 46; 1107*795d594fSAndroid Build Coastguard Worker } 1108*795d594fSAndroid Build Coastguard Worker spreadShort(String a, Short b, short c, int d, long e, float f, double g)1109*795d594fSAndroid Build Coastguard Worker public static int spreadShort(String a, Short b, short c, 1110*795d594fSAndroid Build Coastguard Worker int d, long e, float f, double g) { 1111*795d594fSAndroid Build Coastguard Worker System.out.println("a: " + a + ", b:" + b + ", c: " + c + 1112*795d594fSAndroid Build Coastguard Worker ", d: " + d + ", e: " + e + ", f:" + f + ", g:" + g); 1113*795d594fSAndroid Build Coastguard Worker return 47; 1114*795d594fSAndroid Build Coastguard Worker } 1115*795d594fSAndroid Build Coastguard Worker spreadInt(String a, Integer b, int c, long d, float e, double f)1116*795d594fSAndroid Build Coastguard Worker public static int spreadInt(String a, Integer b, int c, 1117*795d594fSAndroid Build Coastguard Worker long d, float e, double f) { 1118*795d594fSAndroid Build Coastguard Worker System.out.println("a: " + a + ", b:" + b + ", c: " + c + 1119*795d594fSAndroid Build Coastguard Worker ", d: " + d + ", e: " + e + ", f:" + f); 1120*795d594fSAndroid Build Coastguard Worker return 48; 1121*795d594fSAndroid Build Coastguard Worker } 1122*795d594fSAndroid Build Coastguard Worker spreadLong(String a, Long b, long c, float d, double e)1123*795d594fSAndroid Build Coastguard Worker public static int spreadLong(String a, Long b, long c, float d, double e) { 1124*795d594fSAndroid Build Coastguard Worker System.out.println("a: " + a + ", b:" + b + ", c: " + c + 1125*795d594fSAndroid Build Coastguard Worker ", d: " + d + ", e: " + e); 1126*795d594fSAndroid Build Coastguard Worker return 49; 1127*795d594fSAndroid Build Coastguard Worker } 1128*795d594fSAndroid Build Coastguard Worker spreadFloat(String a, Float b, float c, double d)1129*795d594fSAndroid Build Coastguard Worker public static int spreadFloat(String a, Float b, float c, double d) { 1130*795d594fSAndroid Build Coastguard Worker System.out.println("a: " + a + ", b:" + b + ", c: " + c + ", d: " + d); 1131*795d594fSAndroid Build Coastguard Worker return 50; 1132*795d594fSAndroid Build Coastguard Worker } 1133*795d594fSAndroid Build Coastguard Worker spreadDouble(String a, Double b, double c)1134*795d594fSAndroid Build Coastguard Worker public static int spreadDouble(String a, Double b, double c) { 1135*795d594fSAndroid Build Coastguard Worker System.out.println("a: " + a + ", b:" + b + ", c: " + c); 1136*795d594fSAndroid Build Coastguard Worker return 51; 1137*795d594fSAndroid Build Coastguard Worker } 1138*795d594fSAndroid Build Coastguard Worker testSpreaders_primitive()1139*795d594fSAndroid Build Coastguard Worker public static void testSpreaders_primitive() throws Throwable { 1140*795d594fSAndroid Build Coastguard Worker // boolean[] 1141*795d594fSAndroid Build Coastguard Worker // --------------------- 1142*795d594fSAndroid Build Coastguard Worker MethodType type = MethodType.methodType(int.class, 1143*795d594fSAndroid Build Coastguard Worker new Class<?>[] { String.class, Boolean.class, boolean.class }); 1144*795d594fSAndroid Build Coastguard Worker MethodHandle delegate = MethodHandles.lookup().findStatic( 1145*795d594fSAndroid Build Coastguard Worker Main.class, "spreadBoolean", type); 1146*795d594fSAndroid Build Coastguard Worker 1147*795d594fSAndroid Build Coastguard Worker MethodHandle spreader = delegate.asSpreader(boolean[].class, 2); 1148*795d594fSAndroid Build Coastguard Worker int ret = (int) spreader.invokeExact("a", new boolean[] { true, false }); 1149*795d594fSAndroid Build Coastguard Worker assertEquals(44, ret); 1150*795d594fSAndroid Build Coastguard Worker ret = (int) spreader.invoke("a", new boolean[] { true, false }); 1151*795d594fSAndroid Build Coastguard Worker assertEquals(44, ret); 1152*795d594fSAndroid Build Coastguard Worker 1153*795d594fSAndroid Build Coastguard Worker // boolean can't be cast to String (the first argument to the method). 1154*795d594fSAndroid Build Coastguard Worker try { 1155*795d594fSAndroid Build Coastguard Worker delegate.asSpreader(boolean[].class, 3); 1156*795d594fSAndroid Build Coastguard Worker fail(); 1157*795d594fSAndroid Build Coastguard Worker } catch (WrongMethodTypeException expected) { 1158*795d594fSAndroid Build Coastguard Worker } 1159*795d594fSAndroid Build Coastguard Worker 1160*795d594fSAndroid Build Coastguard Worker // int can't be cast to boolean to supply the last argument to the method. 1161*795d594fSAndroid Build Coastguard Worker try { 1162*795d594fSAndroid Build Coastguard Worker delegate.asSpreader(int[].class, 1); 1163*795d594fSAndroid Build Coastguard Worker fail(); 1164*795d594fSAndroid Build Coastguard Worker } catch (WrongMethodTypeException expected) { 1165*795d594fSAndroid Build Coastguard Worker } 1166*795d594fSAndroid Build Coastguard Worker 1167*795d594fSAndroid Build Coastguard Worker // byte[] 1168*795d594fSAndroid Build Coastguard Worker // --------------------- 1169*795d594fSAndroid Build Coastguard Worker type = MethodType.methodType(int.class, 1170*795d594fSAndroid Build Coastguard Worker new Class<?>[] { 1171*795d594fSAndroid Build Coastguard Worker String.class, Byte.class, byte.class, 1172*795d594fSAndroid Build Coastguard Worker short.class, int.class, long.class, 1173*795d594fSAndroid Build Coastguard Worker float.class, double.class }); 1174*795d594fSAndroid Build Coastguard Worker delegate = MethodHandles.lookup().findStatic(Main.class, "spreadByte", type); 1175*795d594fSAndroid Build Coastguard Worker 1176*795d594fSAndroid Build Coastguard Worker spreader = delegate.asSpreader(byte[].class, 7); 1177*795d594fSAndroid Build Coastguard Worker ret = (int) spreader.invokeExact("a", 1178*795d594fSAndroid Build Coastguard Worker new byte[] { 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 }); 1179*795d594fSAndroid Build Coastguard Worker assertEquals(45, ret); 1180*795d594fSAndroid Build Coastguard Worker ret = (int) spreader.invoke("a", 1181*795d594fSAndroid Build Coastguard Worker new byte[] { 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 }); 1182*795d594fSAndroid Build Coastguard Worker assertEquals(45, ret); 1183*795d594fSAndroid Build Coastguard Worker 1184*795d594fSAndroid Build Coastguard Worker // char[] 1185*795d594fSAndroid Build Coastguard Worker // --------------------- 1186*795d594fSAndroid Build Coastguard Worker type = MethodType.methodType(int.class, 1187*795d594fSAndroid Build Coastguard Worker new Class<?>[] { 1188*795d594fSAndroid Build Coastguard Worker String.class, Character.class,char.class, 1189*795d594fSAndroid Build Coastguard Worker int.class, long.class, float.class, double.class }); 1190*795d594fSAndroid Build Coastguard Worker delegate = MethodHandles.lookup().findStatic(Main.class, "spreadChar", type); 1191*795d594fSAndroid Build Coastguard Worker 1192*795d594fSAndroid Build Coastguard Worker spreader = delegate.asSpreader(char[].class, 6); 1193*795d594fSAndroid Build Coastguard Worker ret = (int) spreader.invokeExact("a", 1194*795d594fSAndroid Build Coastguard Worker new char[] { '1', '2', '3', '4', '5', '6' }); 1195*795d594fSAndroid Build Coastguard Worker assertEquals(46, ret); 1196*795d594fSAndroid Build Coastguard Worker ret = (int) spreader.invokeExact("a", 1197*795d594fSAndroid Build Coastguard Worker new char[] { '1', '2', '3', '4', '5', '6' }); 1198*795d594fSAndroid Build Coastguard Worker assertEquals(46, ret); 1199*795d594fSAndroid Build Coastguard Worker 1200*795d594fSAndroid Build Coastguard Worker // short[] 1201*795d594fSAndroid Build Coastguard Worker // --------------------- 1202*795d594fSAndroid Build Coastguard Worker type = MethodType.methodType(int.class, 1203*795d594fSAndroid Build Coastguard Worker new Class<?>[] { 1204*795d594fSAndroid Build Coastguard Worker String.class, Short.class, short.class, 1205*795d594fSAndroid Build Coastguard Worker int.class, long.class, float.class, double.class }); 1206*795d594fSAndroid Build Coastguard Worker delegate = MethodHandles.lookup().findStatic(Main.class, "spreadShort", type); 1207*795d594fSAndroid Build Coastguard Worker 1208*795d594fSAndroid Build Coastguard Worker spreader = delegate.asSpreader(short[].class, 6); 1209*795d594fSAndroid Build Coastguard Worker ret = (int) spreader.invokeExact("a", 1210*795d594fSAndroid Build Coastguard Worker new short[] { 0x1, 0x2, 0x3, 0x4, 0x5, 0x6 }); 1211*795d594fSAndroid Build Coastguard Worker assertEquals(47, ret); 1212*795d594fSAndroid Build Coastguard Worker ret = (int) spreader.invoke("a", 1213*795d594fSAndroid Build Coastguard Worker new short[] { 0x1, 0x2, 0x3, 0x4, 0x5, 0x6 }); 1214*795d594fSAndroid Build Coastguard Worker assertEquals(47, ret); 1215*795d594fSAndroid Build Coastguard Worker 1216*795d594fSAndroid Build Coastguard Worker // int[] 1217*795d594fSAndroid Build Coastguard Worker // --------------------- 1218*795d594fSAndroid Build Coastguard Worker type = MethodType.methodType(int.class, 1219*795d594fSAndroid Build Coastguard Worker new Class<?>[] { 1220*795d594fSAndroid Build Coastguard Worker String.class, Integer.class, int.class, 1221*795d594fSAndroid Build Coastguard Worker long.class, float.class, double.class }); 1222*795d594fSAndroid Build Coastguard Worker delegate = MethodHandles.lookup().findStatic(Main.class, "spreadInt", type); 1223*795d594fSAndroid Build Coastguard Worker 1224*795d594fSAndroid Build Coastguard Worker spreader = delegate.asSpreader(int[].class, 5); 1225*795d594fSAndroid Build Coastguard Worker ret = (int) spreader.invokeExact("a", new int[] { 1, 2, 3, 4, 5 }); 1226*795d594fSAndroid Build Coastguard Worker assertEquals(48, ret); 1227*795d594fSAndroid Build Coastguard Worker ret = (int) spreader.invokeExact("a", new int[] { 1, 2, 3, 4, 5 }); 1228*795d594fSAndroid Build Coastguard Worker assertEquals(48, ret); 1229*795d594fSAndroid Build Coastguard Worker 1230*795d594fSAndroid Build Coastguard Worker // long[] 1231*795d594fSAndroid Build Coastguard Worker // --------------------- 1232*795d594fSAndroid Build Coastguard Worker type = MethodType.methodType(int.class, 1233*795d594fSAndroid Build Coastguard Worker new Class<?>[] { 1234*795d594fSAndroid Build Coastguard Worker String.class, Long.class, long.class, float.class, double.class }); 1235*795d594fSAndroid Build Coastguard Worker delegate = MethodHandles.lookup().findStatic(Main.class, "spreadLong", type); 1236*795d594fSAndroid Build Coastguard Worker 1237*795d594fSAndroid Build Coastguard Worker spreader = delegate.asSpreader(long[].class, 4); 1238*795d594fSAndroid Build Coastguard Worker ret = (int) spreader.invokeExact("a", 1239*795d594fSAndroid Build Coastguard Worker new long[] { 0x1, 0x2, 0x3, 0x4 }); 1240*795d594fSAndroid Build Coastguard Worker assertEquals(49, ret); 1241*795d594fSAndroid Build Coastguard Worker ret = (int) spreader.invoke("a", 1242*795d594fSAndroid Build Coastguard Worker new long[] { 0x1, 0x2, 0x3, 0x4 }); 1243*795d594fSAndroid Build Coastguard Worker assertEquals(49, ret); 1244*795d594fSAndroid Build Coastguard Worker 1245*795d594fSAndroid Build Coastguard Worker // float[] 1246*795d594fSAndroid Build Coastguard Worker // --------------------- 1247*795d594fSAndroid Build Coastguard Worker type = MethodType.methodType(int.class, 1248*795d594fSAndroid Build Coastguard Worker new Class<?>[] { 1249*795d594fSAndroid Build Coastguard Worker String.class, Float.class, float.class, double.class }); 1250*795d594fSAndroid Build Coastguard Worker delegate = MethodHandles.lookup().findStatic(Main.class, "spreadFloat", type); 1251*795d594fSAndroid Build Coastguard Worker 1252*795d594fSAndroid Build Coastguard Worker spreader = delegate.asSpreader(float[].class, 3); 1253*795d594fSAndroid Build Coastguard Worker ret = (int) spreader.invokeExact("a", 1254*795d594fSAndroid Build Coastguard Worker new float[] { 1.0f, 2.0f, 3.0f }); 1255*795d594fSAndroid Build Coastguard Worker assertEquals(50, ret); 1256*795d594fSAndroid Build Coastguard Worker ret = (int) spreader.invokeExact("a", 1257*795d594fSAndroid Build Coastguard Worker new float[] { 1.0f, 2.0f, 3.0f }); 1258*795d594fSAndroid Build Coastguard Worker assertEquals(50, ret); 1259*795d594fSAndroid Build Coastguard Worker 1260*795d594fSAndroid Build Coastguard Worker // double[] 1261*795d594fSAndroid Build Coastguard Worker // --------------------- 1262*795d594fSAndroid Build Coastguard Worker type = MethodType.methodType(int.class, 1263*795d594fSAndroid Build Coastguard Worker new Class<?>[] { String.class, Double.class, double.class }); 1264*795d594fSAndroid Build Coastguard Worker delegate = MethodHandles.lookup().findStatic(Main.class, "spreadDouble", type); 1265*795d594fSAndroid Build Coastguard Worker 1266*795d594fSAndroid Build Coastguard Worker spreader = delegate.asSpreader(double[].class, 2); 1267*795d594fSAndroid Build Coastguard Worker ret = (int) spreader.invokeExact("a", new double[] { 1.0, 2.0 }); 1268*795d594fSAndroid Build Coastguard Worker assertEquals(51, ret); 1269*795d594fSAndroid Build Coastguard Worker ret = (int) spreader.invokeExact("a", new double[] { 1.0, 2.0 }); 1270*795d594fSAndroid Build Coastguard Worker assertEquals(51, ret); 1271*795d594fSAndroid Build Coastguard Worker } 1272*795d594fSAndroid Build Coastguard Worker testInvokeWithArguments()1273*795d594fSAndroid Build Coastguard Worker public static void testInvokeWithArguments() throws Throwable { 1274*795d594fSAndroid Build Coastguard Worker MethodType methodType = MethodType.methodType(int.class, 1275*795d594fSAndroid Build Coastguard Worker new Class<?>[] { String.class, String.class, String.class }); 1276*795d594fSAndroid Build Coastguard Worker MethodHandle handle = MethodHandles.lookup().findStatic( 1277*795d594fSAndroid Build Coastguard Worker Main.class, "spreadReferences", methodType); 1278*795d594fSAndroid Build Coastguard Worker 1279*795d594fSAndroid Build Coastguard Worker Object ret = handle.invokeWithArguments(new Object[] { "a", "b", "c"}); 1280*795d594fSAndroid Build Coastguard Worker assertEquals(42, (int) ret); 1281*795d594fSAndroid Build Coastguard Worker handle.invokeWithArguments(new String[] { "a", "b", "c" }); 1282*795d594fSAndroid Build Coastguard Worker assertEquals(42, (int) ret); 1283*795d594fSAndroid Build Coastguard Worker 1284*795d594fSAndroid Build Coastguard Worker // Pass in an array that's too small. Should throw an IAE. 1285*795d594fSAndroid Build Coastguard Worker try { 1286*795d594fSAndroid Build Coastguard Worker handle.invokeWithArguments(new Object[] { "a", "b" }); 1287*795d594fSAndroid Build Coastguard Worker fail(); 1288*795d594fSAndroid Build Coastguard Worker } catch (IllegalArgumentException expected) { 1289*795d594fSAndroid Build Coastguard Worker } catch (WrongMethodTypeException expected) { 1290*795d594fSAndroid Build Coastguard Worker } 1291*795d594fSAndroid Build Coastguard Worker 1292*795d594fSAndroid Build Coastguard Worker // Test implicit unboxing. 1293*795d594fSAndroid Build Coastguard Worker MethodType methodType2 = MethodType.methodType(int.class, 1294*795d594fSAndroid Build Coastguard Worker new Class<?>[] { String.class, int.class }); 1295*795d594fSAndroid Build Coastguard Worker MethodHandle handle2 = MethodHandles.lookup().findStatic( 1296*795d594fSAndroid Build Coastguard Worker Main.class, "spreadReferences_Unbox", methodType2); 1297*795d594fSAndroid Build Coastguard Worker 1298*795d594fSAndroid Build Coastguard Worker ret = (int) handle2.invokeWithArguments(new Object[] { "a", 43 }); 1299*795d594fSAndroid Build Coastguard Worker assertEquals(43, (int) ret); 1300*795d594fSAndroid Build Coastguard Worker } 1301*795d594fSAndroid Build Coastguard Worker collectBoolean(String a, boolean[] b)1302*795d594fSAndroid Build Coastguard Worker public static int collectBoolean(String a, boolean[] b) { 1303*795d594fSAndroid Build Coastguard Worker System.out.println("a: " + a + ", b:" + b[0] + ", c: " + b[1]); 1304*795d594fSAndroid Build Coastguard Worker return 44; 1305*795d594fSAndroid Build Coastguard Worker } 1306*795d594fSAndroid Build Coastguard Worker collectByte(String a, byte[] b)1307*795d594fSAndroid Build Coastguard Worker public static int collectByte(String a, byte[] b) { 1308*795d594fSAndroid Build Coastguard Worker System.out.println("a: " + a + ", b:" + b[0] + ", c: " + b[1]); 1309*795d594fSAndroid Build Coastguard Worker return 45; 1310*795d594fSAndroid Build Coastguard Worker } 1311*795d594fSAndroid Build Coastguard Worker collectChar(String a, char[] b)1312*795d594fSAndroid Build Coastguard Worker public static int collectChar(String a, char[] b) { 1313*795d594fSAndroid Build Coastguard Worker System.out.println("a: " + a + ", b:" + b[0] + ", c: " + b[1]); 1314*795d594fSAndroid Build Coastguard Worker return 46; 1315*795d594fSAndroid Build Coastguard Worker } 1316*795d594fSAndroid Build Coastguard Worker collectShort(String a, short[] b)1317*795d594fSAndroid Build Coastguard Worker public static int collectShort(String a, short[] b) { 1318*795d594fSAndroid Build Coastguard Worker System.out.println("a: " + a + ", b:" + b[0] + ", c: " + b[1]); 1319*795d594fSAndroid Build Coastguard Worker return 47; 1320*795d594fSAndroid Build Coastguard Worker } 1321*795d594fSAndroid Build Coastguard Worker collectInt(String a, int[] b)1322*795d594fSAndroid Build Coastguard Worker public static int collectInt(String a, int[] b) { 1323*795d594fSAndroid Build Coastguard Worker System.out.println("a: " + a + ", b:" + b[0] + ", c: " + b[1]); 1324*795d594fSAndroid Build Coastguard Worker return 48; 1325*795d594fSAndroid Build Coastguard Worker } 1326*795d594fSAndroid Build Coastguard Worker collectLong(String a, long[] b)1327*795d594fSAndroid Build Coastguard Worker public static int collectLong(String a, long[] b) { 1328*795d594fSAndroid Build Coastguard Worker System.out.println("a: " + a + ", b:" + b[0] + ", c: " + b[1]); 1329*795d594fSAndroid Build Coastguard Worker return 49; 1330*795d594fSAndroid Build Coastguard Worker } 1331*795d594fSAndroid Build Coastguard Worker collectFloat(String a, float[] b)1332*795d594fSAndroid Build Coastguard Worker public static int collectFloat(String a, float[] b) { 1333*795d594fSAndroid Build Coastguard Worker System.out.println("a: " + a + ", b:" + b[0] + ", c: " + b[1]); 1334*795d594fSAndroid Build Coastguard Worker return 50; 1335*795d594fSAndroid Build Coastguard Worker } 1336*795d594fSAndroid Build Coastguard Worker collectDouble(String a, double[] b)1337*795d594fSAndroid Build Coastguard Worker public static int collectDouble(String a, double[] b) { 1338*795d594fSAndroid Build Coastguard Worker System.out.println("a: " + a + ", b:" + b[0] + ", c: " + b[1]); 1339*795d594fSAndroid Build Coastguard Worker return 51; 1340*795d594fSAndroid Build Coastguard Worker } 1341*795d594fSAndroid Build Coastguard Worker collectCharSequence(String a, CharSequence[] b)1342*795d594fSAndroid Build Coastguard Worker public static int collectCharSequence(String a, CharSequence[] b) { 1343*795d594fSAndroid Build Coastguard Worker System.out.println("a: " + a + ", b:" + b[0] + ", c: " + b[1]); 1344*795d594fSAndroid Build Coastguard Worker return 99; 1345*795d594fSAndroid Build Coastguard Worker } 1346*795d594fSAndroid Build Coastguard Worker testAsCollector()1347*795d594fSAndroid Build Coastguard Worker public static void testAsCollector() throws Throwable { 1348*795d594fSAndroid Build Coastguard Worker // Reference arrays. 1349*795d594fSAndroid Build Coastguard Worker // ------------------- 1350*795d594fSAndroid Build Coastguard Worker MethodHandle trailingRef = MethodHandles.lookup().findStatic( 1351*795d594fSAndroid Build Coastguard Worker Main.class, "collectCharSequence", 1352*795d594fSAndroid Build Coastguard Worker MethodType.methodType(int.class, String.class, CharSequence[].class)); 1353*795d594fSAndroid Build Coastguard Worker 1354*795d594fSAndroid Build Coastguard Worker // int[] is not convertible to CharSequence[].class. 1355*795d594fSAndroid Build Coastguard Worker try { 1356*795d594fSAndroid Build Coastguard Worker trailingRef.asCollector(int[].class, 1); 1357*795d594fSAndroid Build Coastguard Worker fail(); 1358*795d594fSAndroid Build Coastguard Worker } catch (IllegalArgumentException expected) { 1359*795d594fSAndroid Build Coastguard Worker } 1360*795d594fSAndroid Build Coastguard Worker 1361*795d594fSAndroid Build Coastguard Worker // Object[] is not convertible to CharSequence[].class. 1362*795d594fSAndroid Build Coastguard Worker try { 1363*795d594fSAndroid Build Coastguard Worker trailingRef.asCollector(Object[].class, 1); 1364*795d594fSAndroid Build Coastguard Worker fail(); 1365*795d594fSAndroid Build Coastguard Worker } catch (IllegalArgumentException expected) { 1366*795d594fSAndroid Build Coastguard Worker } 1367*795d594fSAndroid Build Coastguard Worker 1368*795d594fSAndroid Build Coastguard Worker // String[].class is convertible to CharSequence.class 1369*795d594fSAndroid Build Coastguard Worker MethodHandle collector = trailingRef.asCollector(String[].class, 2); 1370*795d594fSAndroid Build Coastguard Worker assertEquals(99, (int) collector.invoke("a", "b", "c")); 1371*795d594fSAndroid Build Coastguard Worker 1372*795d594fSAndroid Build Coastguard Worker // Too few arguments should fail with a WMTE. 1373*795d594fSAndroid Build Coastguard Worker try { 1374*795d594fSAndroid Build Coastguard Worker collector.invoke("a", "b"); 1375*795d594fSAndroid Build Coastguard Worker fail(); 1376*795d594fSAndroid Build Coastguard Worker } catch (WrongMethodTypeException expected) { 1377*795d594fSAndroid Build Coastguard Worker } 1378*795d594fSAndroid Build Coastguard Worker 1379*795d594fSAndroid Build Coastguard Worker // Too many arguments should fail with a WMTE. 1380*795d594fSAndroid Build Coastguard Worker try { 1381*795d594fSAndroid Build Coastguard Worker collector.invoke("a", "b", "c", "d"); 1382*795d594fSAndroid Build Coastguard Worker fail(); 1383*795d594fSAndroid Build Coastguard Worker } catch (WrongMethodTypeException expected) { 1384*795d594fSAndroid Build Coastguard Worker } 1385*795d594fSAndroid Build Coastguard Worker 1386*795d594fSAndroid Build Coastguard Worker // Checks on other array types. 1387*795d594fSAndroid Build Coastguard Worker 1388*795d594fSAndroid Build Coastguard Worker MethodHandle target = MethodHandles.lookup().findStatic( 1389*795d594fSAndroid Build Coastguard Worker Main.class, "collectBoolean", 1390*795d594fSAndroid Build Coastguard Worker MethodType.methodType(int.class, String.class, boolean[].class)); 1391*795d594fSAndroid Build Coastguard Worker assertEquals(44, (int) target.asCollector(boolean[].class, 2).invoke("a", true, false)); 1392*795d594fSAndroid Build Coastguard Worker 1393*795d594fSAndroid Build Coastguard Worker target = MethodHandles.lookup().findStatic(Main.class, "collectByte", 1394*795d594fSAndroid Build Coastguard Worker MethodType.methodType(int.class, String.class, byte[].class)); 1395*795d594fSAndroid Build Coastguard Worker assertEquals(45, (int) target.asCollector(byte[].class, 2).invoke("a", (byte) 1, (byte) 2)); 1396*795d594fSAndroid Build Coastguard Worker 1397*795d594fSAndroid Build Coastguard Worker target = MethodHandles.lookup().findStatic(Main.class, "collectChar", 1398*795d594fSAndroid Build Coastguard Worker MethodType.methodType(int.class, String.class, char[].class)); 1399*795d594fSAndroid Build Coastguard Worker assertEquals(46, (int) target.asCollector(char[].class, 2).invoke("a", 'a', 'b')); 1400*795d594fSAndroid Build Coastguard Worker 1401*795d594fSAndroid Build Coastguard Worker target = MethodHandles.lookup().findStatic(Main.class, "collectShort", 1402*795d594fSAndroid Build Coastguard Worker MethodType.methodType(int.class, String.class, short[].class)); 1403*795d594fSAndroid Build Coastguard Worker assertEquals(47, (int) target.asCollector(short[].class, 2).invoke("a", (short) 3, (short) 4)); 1404*795d594fSAndroid Build Coastguard Worker 1405*795d594fSAndroid Build Coastguard Worker target = MethodHandles.lookup().findStatic(Main.class, "collectInt", 1406*795d594fSAndroid Build Coastguard Worker MethodType.methodType(int.class, String.class, int[].class)); 1407*795d594fSAndroid Build Coastguard Worker assertEquals(48, (int) target.asCollector(int[].class, 2).invoke("a", 42, 43)); 1408*795d594fSAndroid Build Coastguard Worker 1409*795d594fSAndroid Build Coastguard Worker target = MethodHandles.lookup().findStatic(Main.class, "collectLong", 1410*795d594fSAndroid Build Coastguard Worker MethodType.methodType(int.class, String.class, long[].class)); 1411*795d594fSAndroid Build Coastguard Worker assertEquals(49, (int) target.asCollector(long[].class, 2).invoke("a", 100, 99)); 1412*795d594fSAndroid Build Coastguard Worker 1413*795d594fSAndroid Build Coastguard Worker target = MethodHandles.lookup().findStatic(Main.class, "collectFloat", 1414*795d594fSAndroid Build Coastguard Worker MethodType.methodType(int.class, String.class, float[].class)); 1415*795d594fSAndroid Build Coastguard Worker assertEquals(50, (int) target.asCollector(float[].class, 2).invoke("a", 8.9f, 9.1f)); 1416*795d594fSAndroid Build Coastguard Worker 1417*795d594fSAndroid Build Coastguard Worker target = MethodHandles.lookup().findStatic(Main.class, "collectDouble", 1418*795d594fSAndroid Build Coastguard Worker MethodType.methodType(int.class, String.class, double[].class)); 1419*795d594fSAndroid Build Coastguard Worker assertEquals(51, (int) target.asCollector(double[].class, 2).invoke("a", 6.7, 7.8)); 1420*795d594fSAndroid Build Coastguard Worker } 1421*795d594fSAndroid Build Coastguard Worker filter1(char a)1422*795d594fSAndroid Build Coastguard Worker public static String filter1(char a) { 1423*795d594fSAndroid Build Coastguard Worker return String.valueOf(a); 1424*795d594fSAndroid Build Coastguard Worker } 1425*795d594fSAndroid Build Coastguard Worker filter2(String b)1426*795d594fSAndroid Build Coastguard Worker public static char filter2(String b) { 1427*795d594fSAndroid Build Coastguard Worker return b.charAt(0); 1428*795d594fSAndroid Build Coastguard Worker } 1429*795d594fSAndroid Build Coastguard Worker badFilter1(char a, char b)1430*795d594fSAndroid Build Coastguard Worker public static String badFilter1(char a, char b) { 1431*795d594fSAndroid Build Coastguard Worker return "bad"; 1432*795d594fSAndroid Build Coastguard Worker } 1433*795d594fSAndroid Build Coastguard Worker filterTarget(String a, char b, String c, char d)1434*795d594fSAndroid Build Coastguard Worker public static int filterTarget(String a, char b, String c, char d) { 1435*795d594fSAndroid Build Coastguard Worker System.out.println("a: " + a + ", b: " + b + ", c:" + c + ", d:" + d); 1436*795d594fSAndroid Build Coastguard Worker return 56; 1437*795d594fSAndroid Build Coastguard Worker } 1438*795d594fSAndroid Build Coastguard Worker testFilterArguments()1439*795d594fSAndroid Build Coastguard Worker public static void testFilterArguments() throws Throwable { 1440*795d594fSAndroid Build Coastguard Worker MethodHandle filter1 = MethodHandles.lookup().findStatic( 1441*795d594fSAndroid Build Coastguard Worker Main.class, "filter1", MethodType.methodType(String.class, char.class)); 1442*795d594fSAndroid Build Coastguard Worker MethodHandle filter2 = MethodHandles.lookup().findStatic( 1443*795d594fSAndroid Build Coastguard Worker Main.class, "filter2", MethodType.methodType(char.class, String.class)); 1444*795d594fSAndroid Build Coastguard Worker 1445*795d594fSAndroid Build Coastguard Worker MethodHandle target = MethodHandles.lookup().findStatic( 1446*795d594fSAndroid Build Coastguard Worker Main.class, "filterTarget", MethodType.methodType(int.class, 1447*795d594fSAndroid Build Coastguard Worker String.class, char.class, String.class, char.class)); 1448*795d594fSAndroid Build Coastguard Worker 1449*795d594fSAndroid Build Coastguard Worker // In all the cases below, the values printed will be 'a', 'b', 'c', 'd'. 1450*795d594fSAndroid Build Coastguard Worker 1451*795d594fSAndroid Build Coastguard Worker // Filter arguments [0, 1] - all other arguments are passed through 1452*795d594fSAndroid Build Coastguard Worker // as is. 1453*795d594fSAndroid Build Coastguard Worker MethodHandle adapter = MethodHandles.filterArguments( 1454*795d594fSAndroid Build Coastguard Worker target, 0, filter1, filter2); 1455*795d594fSAndroid Build Coastguard Worker assertEquals(56, (int) adapter.invokeExact('a', "bXXXX", "c", 'd')); 1456*795d594fSAndroid Build Coastguard Worker 1457*795d594fSAndroid Build Coastguard Worker // Filter arguments [1, 2]. 1458*795d594fSAndroid Build Coastguard Worker adapter = MethodHandles.filterArguments(target, 1, filter2, filter1); 1459*795d594fSAndroid Build Coastguard Worker assertEquals(56, (int) adapter.invokeExact("a", "bXXXX", 'c', 'd')); 1460*795d594fSAndroid Build Coastguard Worker 1461*795d594fSAndroid Build Coastguard Worker // Filter arguments [2, 3]. 1462*795d594fSAndroid Build Coastguard Worker adapter = MethodHandles.filterArguments(target, 2, filter1, filter2); 1463*795d594fSAndroid Build Coastguard Worker assertEquals(56, (int) adapter.invokeExact("a", 'b', 'c', "dXXXXX")); 1464*795d594fSAndroid Build Coastguard Worker 1465*795d594fSAndroid Build Coastguard Worker // Try out a few error cases : 1466*795d594fSAndroid Build Coastguard Worker 1467*795d594fSAndroid Build Coastguard Worker // The return types of the filter doesn't align with the expected argument 1468*795d594fSAndroid Build Coastguard Worker // type of the target. 1469*795d594fSAndroid Build Coastguard Worker try { 1470*795d594fSAndroid Build Coastguard Worker adapter = MethodHandles.filterArguments(target, 2, filter2, filter1); 1471*795d594fSAndroid Build Coastguard Worker fail(); 1472*795d594fSAndroid Build Coastguard Worker } catch (IllegalArgumentException expected) { 1473*795d594fSAndroid Build Coastguard Worker } 1474*795d594fSAndroid Build Coastguard Worker 1475*795d594fSAndroid Build Coastguard Worker // There are more filters than arguments. 1476*795d594fSAndroid Build Coastguard Worker try { 1477*795d594fSAndroid Build Coastguard Worker adapter = MethodHandles.filterArguments(target, 3, filter2, filter1); 1478*795d594fSAndroid Build Coastguard Worker fail(); 1479*795d594fSAndroid Build Coastguard Worker } catch (IllegalArgumentException expected) { 1480*795d594fSAndroid Build Coastguard Worker } 1481*795d594fSAndroid Build Coastguard Worker 1482*795d594fSAndroid Build Coastguard Worker // We pass in an obviously bogus position. 1483*795d594fSAndroid Build Coastguard Worker try { 1484*795d594fSAndroid Build Coastguard Worker adapter = MethodHandles.filterArguments(target, -1, filter2, filter1); 1485*795d594fSAndroid Build Coastguard Worker fail(); 1486*795d594fSAndroid Build Coastguard Worker } catch (ArrayIndexOutOfBoundsException expected) { 1487*795d594fSAndroid Build Coastguard Worker } 1488*795d594fSAndroid Build Coastguard Worker 1489*795d594fSAndroid Build Coastguard Worker // We pass in a function that has more than one argument. 1490*795d594fSAndroid Build Coastguard Worker MethodHandle badFilter1 = MethodHandles.lookup().findStatic( 1491*795d594fSAndroid Build Coastguard Worker Main.class, "badFilter1", 1492*795d594fSAndroid Build Coastguard Worker MethodType.methodType(String.class, char.class, char.class)); 1493*795d594fSAndroid Build Coastguard Worker 1494*795d594fSAndroid Build Coastguard Worker try { 1495*795d594fSAndroid Build Coastguard Worker adapter = MethodHandles.filterArguments(target, 0, badFilter1, filter2); 1496*795d594fSAndroid Build Coastguard Worker fail(); 1497*795d594fSAndroid Build Coastguard Worker } catch (IllegalArgumentException expected) { 1498*795d594fSAndroid Build Coastguard Worker } 1499*795d594fSAndroid Build Coastguard Worker } 1500*795d594fSAndroid Build Coastguard Worker voidFilter(char a, char b)1501*795d594fSAndroid Build Coastguard Worker static void voidFilter(char a, char b) { 1502*795d594fSAndroid Build Coastguard Worker System.out.println("voidFilter"); 1503*795d594fSAndroid Build Coastguard Worker } 1504*795d594fSAndroid Build Coastguard Worker filter(char a, char b)1505*795d594fSAndroid Build Coastguard Worker static String filter(char a, char b) { 1506*795d594fSAndroid Build Coastguard Worker return String.valueOf(a) + "+" + b; 1507*795d594fSAndroid Build Coastguard Worker } 1508*795d594fSAndroid Build Coastguard Worker badFilter(char a, char b)1509*795d594fSAndroid Build Coastguard Worker static char badFilter(char a, char b) { 1510*795d594fSAndroid Build Coastguard Worker return 0; 1511*795d594fSAndroid Build Coastguard Worker } 1512*795d594fSAndroid Build Coastguard Worker target(String a, String b, String c)1513*795d594fSAndroid Build Coastguard Worker static int target(String a, String b, String c) { 1514*795d594fSAndroid Build Coastguard Worker System.out.println("a: " + a + ", b: " + b + ", c: " + c); 1515*795d594fSAndroid Build Coastguard Worker return 57; 1516*795d594fSAndroid Build Coastguard Worker } 1517*795d594fSAndroid Build Coastguard Worker testCollectArguments()1518*795d594fSAndroid Build Coastguard Worker public static void testCollectArguments() throws Throwable { 1519*795d594fSAndroid Build Coastguard Worker // Test non-void filters. 1520*795d594fSAndroid Build Coastguard Worker MethodHandle filter = MethodHandles.lookup().findStatic( 1521*795d594fSAndroid Build Coastguard Worker Main.class, "filter", 1522*795d594fSAndroid Build Coastguard Worker MethodType.methodType(String.class, char.class, char.class)); 1523*795d594fSAndroid Build Coastguard Worker 1524*795d594fSAndroid Build Coastguard Worker MethodHandle target = MethodHandles.lookup().findStatic( 1525*795d594fSAndroid Build Coastguard Worker Main.class, "target", 1526*795d594fSAndroid Build Coastguard Worker MethodType.methodType(int.class, String.class, String.class, String.class)); 1527*795d594fSAndroid Build Coastguard Worker 1528*795d594fSAndroid Build Coastguard Worker // Filter at position 0. 1529*795d594fSAndroid Build Coastguard Worker MethodHandle adapter = MethodHandles.collectArguments(target, 0, filter); 1530*795d594fSAndroid Build Coastguard Worker assertEquals(57, (int) adapter.invokeExact('a', 'b', "c", "d")); 1531*795d594fSAndroid Build Coastguard Worker 1532*795d594fSAndroid Build Coastguard Worker // Filter at position 1. 1533*795d594fSAndroid Build Coastguard Worker adapter = MethodHandles.collectArguments(target, 1, filter); 1534*795d594fSAndroid Build Coastguard Worker assertEquals(57, (int) adapter.invokeExact("a", 'b', 'c', "d")); 1535*795d594fSAndroid Build Coastguard Worker 1536*795d594fSAndroid Build Coastguard Worker // Filter at position 2. 1537*795d594fSAndroid Build Coastguard Worker adapter = MethodHandles.collectArguments(target, 2, filter); 1538*795d594fSAndroid Build Coastguard Worker assertEquals(57, (int) adapter.invokeExact("a", "b", 'c', 'd')); 1539*795d594fSAndroid Build Coastguard Worker 1540*795d594fSAndroid Build Coastguard Worker // Test void filters. Note that we're passing in one more argument 1541*795d594fSAndroid Build Coastguard Worker // than usual because the filter returns nothing - we have to invoke with 1542*795d594fSAndroid Build Coastguard Worker // the full set of filter args and the full set of target args. 1543*795d594fSAndroid Build Coastguard Worker filter = MethodHandles.lookup().findStatic(Main.class, "voidFilter", 1544*795d594fSAndroid Build Coastguard Worker MethodType.methodType(void.class, char.class, char.class)); 1545*795d594fSAndroid Build Coastguard Worker adapter = MethodHandles.collectArguments(target, 0, filter); 1546*795d594fSAndroid Build Coastguard Worker assertEquals(57, (int) adapter.invokeExact('a', 'b', "a", "b", "c")); 1547*795d594fSAndroid Build Coastguard Worker 1548*795d594fSAndroid Build Coastguard Worker adapter = MethodHandles.collectArguments(target, 1, filter); 1549*795d594fSAndroid Build Coastguard Worker assertEquals(57, (int) adapter.invokeExact("a", 'a', 'b', "b", "c")); 1550*795d594fSAndroid Build Coastguard Worker 1551*795d594fSAndroid Build Coastguard Worker // Test out a few failure cases. 1552*795d594fSAndroid Build Coastguard Worker filter = MethodHandles.lookup().findStatic( 1553*795d594fSAndroid Build Coastguard Worker Main.class, "filter", 1554*795d594fSAndroid Build Coastguard Worker MethodType.methodType(String.class, char.class, char.class)); 1555*795d594fSAndroid Build Coastguard Worker 1556*795d594fSAndroid Build Coastguard Worker // Bogus filter position. 1557*795d594fSAndroid Build Coastguard Worker try { 1558*795d594fSAndroid Build Coastguard Worker adapter = MethodHandles.collectArguments(target, 3, filter); 1559*795d594fSAndroid Build Coastguard Worker fail(); 1560*795d594fSAndroid Build Coastguard Worker } catch (IndexOutOfBoundsException | IllegalArgumentException expected) { 1561*795d594fSAndroid Build Coastguard Worker } 1562*795d594fSAndroid Build Coastguard Worker 1563*795d594fSAndroid Build Coastguard Worker // Mismatch in filter return type. 1564*795d594fSAndroid Build Coastguard Worker filter = MethodHandles.lookup().findStatic( 1565*795d594fSAndroid Build Coastguard Worker Main.class, "badFilter", 1566*795d594fSAndroid Build Coastguard Worker MethodType.methodType(char.class, char.class, char.class)); 1567*795d594fSAndroid Build Coastguard Worker try { 1568*795d594fSAndroid Build Coastguard Worker adapter = MethodHandles.collectArguments(target, 0, filter); 1569*795d594fSAndroid Build Coastguard Worker fail(); 1570*795d594fSAndroid Build Coastguard Worker } catch (IllegalArgumentException expected) { 1571*795d594fSAndroid Build Coastguard Worker } 1572*795d594fSAndroid Build Coastguard Worker } 1573*795d594fSAndroid Build Coastguard Worker insertReceiver(String a, int b, Integer c, String d)1574*795d594fSAndroid Build Coastguard Worker static int insertReceiver(String a, int b, Integer c, String d) { 1575*795d594fSAndroid Build Coastguard Worker System.out.println("a: " + a + ", b:" + b + ", c:" + c + ", d:" + d); 1576*795d594fSAndroid Build Coastguard Worker return 73; 1577*795d594fSAndroid Build Coastguard Worker } 1578*795d594fSAndroid Build Coastguard Worker testInsertArguments()1579*795d594fSAndroid Build Coastguard Worker public static void testInsertArguments() throws Throwable { 1580*795d594fSAndroid Build Coastguard Worker MethodHandle target = MethodHandles.lookup().findStatic( 1581*795d594fSAndroid Build Coastguard Worker Main.class, "insertReceiver", 1582*795d594fSAndroid Build Coastguard Worker MethodType.methodType(int.class, 1583*795d594fSAndroid Build Coastguard Worker String.class, int.class, Integer.class, String.class)); 1584*795d594fSAndroid Build Coastguard Worker 1585*795d594fSAndroid Build Coastguard Worker // Basic single element array inserted at position 0. 1586*795d594fSAndroid Build Coastguard Worker MethodHandle adapter = MethodHandles.insertArguments( 1587*795d594fSAndroid Build Coastguard Worker target, 0, new Object[] { "foo" }); 1588*795d594fSAndroid Build Coastguard Worker assertEquals(73, (int) adapter.invokeExact(45, Integer.valueOf(56), "bar")); 1589*795d594fSAndroid Build Coastguard Worker 1590*795d594fSAndroid Build Coastguard Worker // Exercise unboxing. 1591*795d594fSAndroid Build Coastguard Worker adapter = MethodHandles.insertArguments( 1592*795d594fSAndroid Build Coastguard Worker target, 1, new Object[] { Integer.valueOf(56), 57 }); 1593*795d594fSAndroid Build Coastguard Worker assertEquals(73, (int) adapter.invokeExact("foo", "bar")); 1594*795d594fSAndroid Build Coastguard Worker 1595*795d594fSAndroid Build Coastguard Worker // Exercise a widening conversion. 1596*795d594fSAndroid Build Coastguard Worker adapter = MethodHandles.insertArguments( 1597*795d594fSAndroid Build Coastguard Worker target, 1, new Object[] { (short) 56, Integer.valueOf(57) }); 1598*795d594fSAndroid Build Coastguard Worker assertEquals(73, (int) adapter.invokeExact("foo", "bar")); 1599*795d594fSAndroid Build Coastguard Worker 1600*795d594fSAndroid Build Coastguard Worker // Insert an argument at the last position. 1601*795d594fSAndroid Build Coastguard Worker adapter = MethodHandles.insertArguments( 1602*795d594fSAndroid Build Coastguard Worker target, 3, new Object[] { "bar" }); 1603*795d594fSAndroid Build Coastguard Worker assertEquals(73, (int) adapter.invokeExact("foo", 45, Integer.valueOf(46))); 1604*795d594fSAndroid Build Coastguard Worker 1605*795d594fSAndroid Build Coastguard Worker // Exercise a few error cases. 1606*795d594fSAndroid Build Coastguard Worker 1607*795d594fSAndroid Build Coastguard Worker // A reference type that can't be cast to another reference type. 1608*795d594fSAndroid Build Coastguard Worker try { 1609*795d594fSAndroid Build Coastguard Worker MethodHandles.insertArguments(target, 3, new Object[] { new Object() }); 1610*795d594fSAndroid Build Coastguard Worker fail(); 1611*795d594fSAndroid Build Coastguard Worker } catch (ClassCastException expected) { 1612*795d594fSAndroid Build Coastguard Worker } 1613*795d594fSAndroid Build Coastguard Worker 1614*795d594fSAndroid Build Coastguard Worker // A boxed type that can't be unboxed correctly. 1615*795d594fSAndroid Build Coastguard Worker try { 1616*795d594fSAndroid Build Coastguard Worker MethodHandles.insertArguments(target, 1, new Object[] { Long.valueOf(56) }); 1617*795d594fSAndroid Build Coastguard Worker fail(); 1618*795d594fSAndroid Build Coastguard Worker } catch (ClassCastException expected) { 1619*795d594fSAndroid Build Coastguard Worker } 1620*795d594fSAndroid Build Coastguard Worker } 1621*795d594fSAndroid Build Coastguard Worker foldFilter(char a, char b)1622*795d594fSAndroid Build Coastguard Worker public static String foldFilter(char a, char b) { 1623*795d594fSAndroid Build Coastguard Worker return String.valueOf(a) + "+" + b; 1624*795d594fSAndroid Build Coastguard Worker } 1625*795d594fSAndroid Build Coastguard Worker voidFoldFilter(String e, char a, char b)1626*795d594fSAndroid Build Coastguard Worker public static void voidFoldFilter(String e, char a, char b) { 1627*795d594fSAndroid Build Coastguard Worker System.out.println(String.valueOf(a) + "+" + b); 1628*795d594fSAndroid Build Coastguard Worker } 1629*795d594fSAndroid Build Coastguard Worker foldTarget(String a, char b, char c, String d)1630*795d594fSAndroid Build Coastguard Worker public static int foldTarget(String a, char b, char c, String d) { 1631*795d594fSAndroid Build Coastguard Worker System.out.println("a: " + a + " ,b:" + b + " ,c:" + c + " ,d:" + d); 1632*795d594fSAndroid Build Coastguard Worker return 89; 1633*795d594fSAndroid Build Coastguard Worker } 1634*795d594fSAndroid Build Coastguard Worker mismatchedVoidFilter(Integer a)1635*795d594fSAndroid Build Coastguard Worker public static void mismatchedVoidFilter(Integer a) { 1636*795d594fSAndroid Build Coastguard Worker } 1637*795d594fSAndroid Build Coastguard Worker mismatchedNonVoidFilter(char a, char b)1638*795d594fSAndroid Build Coastguard Worker public static Integer mismatchedNonVoidFilter(char a, char b) { 1639*795d594fSAndroid Build Coastguard Worker return null; 1640*795d594fSAndroid Build Coastguard Worker } 1641*795d594fSAndroid Build Coastguard Worker testFoldArguments()1642*795d594fSAndroid Build Coastguard Worker public static void testFoldArguments() throws Throwable { 1643*795d594fSAndroid Build Coastguard Worker // Test non-void filters. 1644*795d594fSAndroid Build Coastguard Worker MethodHandle filter = MethodHandles.lookup().findStatic( 1645*795d594fSAndroid Build Coastguard Worker Main.class, "foldFilter", 1646*795d594fSAndroid Build Coastguard Worker MethodType.methodType(String.class, char.class, char.class)); 1647*795d594fSAndroid Build Coastguard Worker 1648*795d594fSAndroid Build Coastguard Worker MethodHandle target = MethodHandles.lookup().findStatic( 1649*795d594fSAndroid Build Coastguard Worker Main.class, "foldTarget", 1650*795d594fSAndroid Build Coastguard Worker MethodType.methodType(int.class, String.class, 1651*795d594fSAndroid Build Coastguard Worker char.class, char.class, String.class)); 1652*795d594fSAndroid Build Coastguard Worker 1653*795d594fSAndroid Build Coastguard Worker // Folder with a non-void type. 1654*795d594fSAndroid Build Coastguard Worker MethodHandle adapter = MethodHandles.foldArguments(target, filter); 1655*795d594fSAndroid Build Coastguard Worker assertEquals(89, (int) adapter.invokeExact('c', 'd', "e")); 1656*795d594fSAndroid Build Coastguard Worker 1657*795d594fSAndroid Build Coastguard Worker // Folder with a void type. 1658*795d594fSAndroid Build Coastguard Worker filter = MethodHandles.lookup().findStatic( 1659*795d594fSAndroid Build Coastguard Worker Main.class, "voidFoldFilter", 1660*795d594fSAndroid Build Coastguard Worker MethodType.methodType(void.class, String.class, char.class, char.class)); 1661*795d594fSAndroid Build Coastguard Worker adapter = MethodHandles.foldArguments(target, filter); 1662*795d594fSAndroid Build Coastguard Worker assertEquals(89, (int) adapter.invokeExact("a", 'c', 'd', "e")); 1663*795d594fSAndroid Build Coastguard Worker 1664*795d594fSAndroid Build Coastguard Worker // Test a few erroneous cases. 1665*795d594fSAndroid Build Coastguard Worker 1666*795d594fSAndroid Build Coastguard Worker filter = MethodHandles.lookup().findStatic( 1667*795d594fSAndroid Build Coastguard Worker Main.class, "mismatchedVoidFilter", 1668*795d594fSAndroid Build Coastguard Worker MethodType.methodType(void.class, Integer.class)); 1669*795d594fSAndroid Build Coastguard Worker try { 1670*795d594fSAndroid Build Coastguard Worker adapter = MethodHandles.foldArguments(target, filter); 1671*795d594fSAndroid Build Coastguard Worker fail(); 1672*795d594fSAndroid Build Coastguard Worker } catch (IllegalArgumentException expected) { 1673*795d594fSAndroid Build Coastguard Worker } 1674*795d594fSAndroid Build Coastguard Worker 1675*795d594fSAndroid Build Coastguard Worker filter = MethodHandles.lookup().findStatic( 1676*795d594fSAndroid Build Coastguard Worker Main.class, "mismatchedNonVoidFilter", 1677*795d594fSAndroid Build Coastguard Worker MethodType.methodType(Integer.class, char.class, char.class)); 1678*795d594fSAndroid Build Coastguard Worker try { 1679*795d594fSAndroid Build Coastguard Worker adapter = MethodHandles.foldArguments(target, filter); 1680*795d594fSAndroid Build Coastguard Worker fail(); 1681*795d594fSAndroid Build Coastguard Worker } catch (IllegalArgumentException expected) { 1682*795d594fSAndroid Build Coastguard Worker } 1683*795d594fSAndroid Build Coastguard Worker } 1684*795d594fSAndroid Build Coastguard Worker fail()1685*795d594fSAndroid Build Coastguard Worker public static void fail() { 1686*795d594fSAndroid Build Coastguard Worker System.out.println("FAIL"); 1687*795d594fSAndroid Build Coastguard Worker Thread.dumpStack(); 1688*795d594fSAndroid Build Coastguard Worker } 1689*795d594fSAndroid Build Coastguard Worker fail(String message)1690*795d594fSAndroid Build Coastguard Worker public static void fail(String message) { 1691*795d594fSAndroid Build Coastguard Worker System.out.println("fail: " + message); 1692*795d594fSAndroid Build Coastguard Worker Thread.dumpStack(); 1693*795d594fSAndroid Build Coastguard Worker } 1694*795d594fSAndroid Build Coastguard Worker assertEquals(int i1, int i2)1695*795d594fSAndroid Build Coastguard Worker public static void assertEquals(int i1, int i2) { 1696*795d594fSAndroid Build Coastguard Worker if (i1 != i2) throw new AssertionError("Expected: " + i1 + " was " + i2); 1697*795d594fSAndroid Build Coastguard Worker } 1698*795d594fSAndroid Build Coastguard Worker assertEquals(String s1, String s2)1699*795d594fSAndroid Build Coastguard Worker public static void assertEquals(String s1, String s2) { 1700*795d594fSAndroid Build Coastguard Worker if (s1 == s2) { 1701*795d594fSAndroid Build Coastguard Worker return; 1702*795d594fSAndroid Build Coastguard Worker } 1703*795d594fSAndroid Build Coastguard Worker 1704*795d594fSAndroid Build Coastguard Worker if (s1 != null && s2 != null && s1.equals(s2)) { 1705*795d594fSAndroid Build Coastguard Worker return; 1706*795d594fSAndroid Build Coastguard Worker } 1707*795d594fSAndroid Build Coastguard Worker 1708*795d594fSAndroid Build Coastguard Worker throw new AssertionError("assertEquals s1: " + s1 + ", s2: " + s2); 1709*795d594fSAndroid Build Coastguard Worker } 1710*795d594fSAndroid Build Coastguard Worker } 1711