1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2018 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.reflect.InvocationHandler; 18*795d594fSAndroid Build Coastguard Worker import java.lang.reflect.Method; 19*795d594fSAndroid Build Coastguard Worker import java.lang.reflect.Proxy; 20*795d594fSAndroid Build Coastguard Worker 21*795d594fSAndroid Build Coastguard Worker interface TestInterface { method0()22*795d594fSAndroid Build Coastguard Worker void method0(); method1(String arg)23*795d594fSAndroid Build Coastguard Worker void method1(String arg); method10(String arg1, String arg2, String arg3, String arg4, String arg5, String arg6, String arg7, String arg8, String arg9, String arg10)24*795d594fSAndroid Build Coastguard Worker void method10(String arg1, String arg2, String arg3, String arg4, String arg5, 25*795d594fSAndroid Build Coastguard Worker String arg6, String arg7, String arg8, String arg9, String arg10); method10Even(byte arg1, String arg2, short arg3, String arg4, int arg5, String arg6, long arg7, String arg8, double arg9, String arg10)26*795d594fSAndroid Build Coastguard Worker void method10Even(byte arg1, String arg2, short arg3, String arg4, int arg5, 27*795d594fSAndroid Build Coastguard Worker String arg6, long arg7, String arg8, double arg9, String arg10); 28*795d594fSAndroid Build Coastguard Worker } 29*795d594fSAndroid Build Coastguard Worker 30*795d594fSAndroid Build Coastguard Worker class TestInvocationHandler implements InvocationHandler { 31*795d594fSAndroid Build Coastguard Worker @Override invoke(Object proxy, Method method, Object[] args)32*795d594fSAndroid Build Coastguard Worker public Object invoke(Object proxy, Method method, Object[] args) { 33*795d594fSAndroid Build Coastguard Worker // Force garbage collection to try to make `proxy` move in memory 34*795d594fSAndroid Build Coastguard Worker // (in the case of a moving garbage collector). 35*795d594fSAndroid Build Coastguard Worker System.gc(); 36*795d594fSAndroid Build Coastguard Worker 37*795d594fSAndroid Build Coastguard Worker System.out.println("Proxy for " + TestInterface.class + "." + method.getName()); 38*795d594fSAndroid Build Coastguard Worker if (method.getName().equals("method0")) { 39*795d594fSAndroid Build Coastguard Worker testMethod0(proxy, args); 40*795d594fSAndroid Build Coastguard Worker } else if (method.getName().equals("method1")) { 41*795d594fSAndroid Build Coastguard Worker testMethod1(proxy, args); 42*795d594fSAndroid Build Coastguard Worker } else if (method.getName().equals("method10")) { 43*795d594fSAndroid Build Coastguard Worker testMethod10(proxy, args); 44*795d594fSAndroid Build Coastguard Worker } else if (method.getName().equals("method10Even")) { 45*795d594fSAndroid Build Coastguard Worker testMethod10Even(proxy, args); 46*795d594fSAndroid Build Coastguard Worker } 47*795d594fSAndroid Build Coastguard Worker return null; 48*795d594fSAndroid Build Coastguard Worker } 49*795d594fSAndroid Build Coastguard Worker testMethod0(Object proxy, Object[] args)50*795d594fSAndroid Build Coastguard Worker private void testMethod0(Object proxy, Object[] args) { 51*795d594fSAndroid Build Coastguard Worker // Get argument 0 (method target) from the proxy method frame ($Proxy0.method0 activation). 52*795d594fSAndroid Build Coastguard Worker Object arg0 = getProxyMethodArgument(0); 53*795d594fSAndroid Build Coastguard Worker System.out.println(" arg0: " + arg0.getClass().getName()); 54*795d594fSAndroid Build Coastguard Worker Main.assertEquals(proxy, arg0); 55*795d594fSAndroid Build Coastguard Worker } 56*795d594fSAndroid Build Coastguard Worker testMethod1(Object proxy, Object[] args)57*795d594fSAndroid Build Coastguard Worker private void testMethod1(Object proxy, Object[] args) { 58*795d594fSAndroid Build Coastguard Worker // Get argument 0 (method target) from the proxy method frame ($Proxy0.method0 activation). 59*795d594fSAndroid Build Coastguard Worker Object arg0 = getProxyMethodArgument(0); 60*795d594fSAndroid Build Coastguard Worker System.out.println(" arg0: " + arg0.getClass().getName()); 61*795d594fSAndroid Build Coastguard Worker Main.assertEquals(proxy, arg0); 62*795d594fSAndroid Build Coastguard Worker // Get argument 1 from the proxy method frame ($Proxy0.method1 activation). 63*795d594fSAndroid Build Coastguard Worker String arg1 = (String) getProxyMethodArgument(1); 64*795d594fSAndroid Build Coastguard Worker System.out.println(" arg1: " + arg1.getClass().getName() + " \"" + arg1 + "\""); 65*795d594fSAndroid Build Coastguard Worker Main.assertEquals(args[0], arg1); 66*795d594fSAndroid Build Coastguard Worker } 67*795d594fSAndroid Build Coastguard Worker testMethod10(Object proxy, Object[] args)68*795d594fSAndroid Build Coastguard Worker private void testMethod10(Object proxy, Object[] args) { 69*795d594fSAndroid Build Coastguard Worker // Get argument 0 (method target) from the proxy method frame ($Proxy0.method10 activation). 70*795d594fSAndroid Build Coastguard Worker Object arg0 = getProxyMethodArgument(0); 71*795d594fSAndroid Build Coastguard Worker System.out.println(" arg0: " + arg0.getClass().getName()); 72*795d594fSAndroid Build Coastguard Worker Main.assertEquals(proxy, arg0); 73*795d594fSAndroid Build Coastguard Worker // Get argument `i` from the proxy method frame ($Proxy0.method10 activation). 74*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < 10; ++i) { 75*795d594fSAndroid Build Coastguard Worker int arg_pos = i + 1; 76*795d594fSAndroid Build Coastguard Worker String arg = (String) getProxyMethodArgument(arg_pos); 77*795d594fSAndroid Build Coastguard Worker System.out.println(" arg" + arg_pos + ": " + arg.getClass().getName() + " \"" + arg + "\""); 78*795d594fSAndroid Build Coastguard Worker Main.assertEquals(args[i], arg); 79*795d594fSAndroid Build Coastguard Worker } 80*795d594fSAndroid Build Coastguard Worker } 81*795d594fSAndroid Build Coastguard Worker testMethod10Even(Object proxy, Object[] args)82*795d594fSAndroid Build Coastguard Worker private void testMethod10Even(Object proxy, Object[] args) { 83*795d594fSAndroid Build Coastguard Worker // Get argument 0 (method target) from the proxy method frame ($Proxy0.method10Even 84*795d594fSAndroid Build Coastguard Worker // activation). 85*795d594fSAndroid Build Coastguard Worker Object arg0 = getProxyMethodArgument(0); 86*795d594fSAndroid Build Coastguard Worker System.out.println(" arg0: " + arg0.getClass().getName()); 87*795d594fSAndroid Build Coastguard Worker Main.assertEquals(proxy, arg0); 88*795d594fSAndroid Build Coastguard Worker // Get argument `i` from the proxy method frame ($Proxy0.method10Even activation). 89*795d594fSAndroid Build Coastguard Worker for (int i = 1; i < 10; i += 2) { 90*795d594fSAndroid Build Coastguard Worker int arg_pos = i + 1; 91*795d594fSAndroid Build Coastguard Worker String arg = (String) getProxyMethodArgument(arg_pos); 92*795d594fSAndroid Build Coastguard Worker System.out.println(" arg" + arg_pos + ": " + arg.getClass().getName() + " \"" + arg + "\""); 93*795d594fSAndroid Build Coastguard Worker Main.assertEquals(args[i], arg); 94*795d594fSAndroid Build Coastguard Worker } 95*795d594fSAndroid Build Coastguard Worker } 96*795d594fSAndroid Build Coastguard Worker 97*795d594fSAndroid Build Coastguard Worker // Get reference argument at position `arg_pos` in proxy frame. 98*795d594fSAndroid Build Coastguard Worker // This method should only be called from one of the 99*795d594fSAndroid Build Coastguard Worker // `TestInvocationHandler.testMethod*` methods via `TestInvocationHandler.invoke`. getProxyMethodArgument(int arg_pos)100*795d594fSAndroid Build Coastguard Worker private Object getProxyMethodArgument(int arg_pos) { 101*795d594fSAndroid Build Coastguard Worker // Find proxy frame in stack (from a testMethod* method). 102*795d594fSAndroid Build Coastguard Worker // 103*795d594fSAndroid Build Coastguard Worker // depth method 104*795d594fSAndroid Build Coastguard Worker // ---------------------------------------------------------------------- 105*795d594fSAndroid Build Coastguard Worker // 0 TestInvocationHandler.getArgument (outermost frame) 106*795d594fSAndroid Build Coastguard Worker // 1 TestInvocationHandler.getProxyMethodArgument 107*795d594fSAndroid Build Coastguard Worker // 2 TestInvocationHandler.testMethod* 108*795d594fSAndroid Build Coastguard Worker // 3 TestInvocationHandler.invoke 109*795d594fSAndroid Build Coastguard Worker // 4 java.lang.reflect.Proxy.invoke 110*795d594fSAndroid Build Coastguard Worker // -> 5 TestInterface.method* (proxy method) 111*795d594fSAndroid Build Coastguard Worker // 6 Main.main (innermost frame) 112*795d594fSAndroid Build Coastguard Worker // 113*795d594fSAndroid Build Coastguard Worker int proxy_method_frame_depth = 5; 114*795d594fSAndroid Build Coastguard Worker return getArgument(arg_pos, proxy_method_frame_depth); 115*795d594fSAndroid Build Coastguard Worker } 116*795d594fSAndroid Build Coastguard Worker 117*795d594fSAndroid Build Coastguard Worker // Get reference argument at position `arg_pos` in frame at depth `frame_depth`. getArgument(int arg_pos, int frame_depth)118*795d594fSAndroid Build Coastguard Worker private native Object getArgument(int arg_pos, int frame_depth); 119*795d594fSAndroid Build Coastguard Worker } 120*795d594fSAndroid Build Coastguard Worker 121*795d594fSAndroid Build Coastguard Worker public class Main { main(String[] args)122*795d594fSAndroid Build Coastguard Worker public static void main(String[] args) { 123*795d594fSAndroid Build Coastguard Worker System.loadLibrary(args[0]); 124*795d594fSAndroid Build Coastguard Worker 125*795d594fSAndroid Build Coastguard Worker TestInvocationHandler invocationHandler = new TestInvocationHandler(); 126*795d594fSAndroid Build Coastguard Worker TestInterface proxy = (TestInterface) Proxy.newProxyInstance( 127*795d594fSAndroid Build Coastguard Worker Main.class.getClassLoader(), 128*795d594fSAndroid Build Coastguard Worker new Class<?>[] { TestInterface.class }, 129*795d594fSAndroid Build Coastguard Worker invocationHandler); 130*795d594fSAndroid Build Coastguard Worker System.out.println("proxy: " + proxy.getClass().getName()); 131*795d594fSAndroid Build Coastguard Worker 132*795d594fSAndroid Build Coastguard Worker proxy.method0(); 133*795d594fSAndroid Build Coastguard Worker proxy.method1("a"); 134*795d594fSAndroid Build Coastguard Worker proxy.method10("one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"); 135*795d594fSAndroid Build Coastguard Worker proxy.method10Even((byte) 1, "two", (short) 3, "four", 5, "six", 7L, "eight", 9.0, "ten"); 136*795d594fSAndroid Build Coastguard Worker } 137*795d594fSAndroid Build Coastguard Worker assertEquals(Object expected, Object actual)138*795d594fSAndroid Build Coastguard Worker public static void assertEquals(Object expected, Object actual) { 139*795d594fSAndroid Build Coastguard Worker if (expected != actual) { 140*795d594fSAndroid Build Coastguard Worker throw new Error("Expected " + expected + ", got " + actual); 141*795d594fSAndroid Build Coastguard Worker } 142*795d594fSAndroid Build Coastguard Worker } 143*795d594fSAndroid Build Coastguard Worker assertEquals(String expected, String actual)144*795d594fSAndroid Build Coastguard Worker public static void assertEquals(String expected, String actual) { 145*795d594fSAndroid Build Coastguard Worker if (expected != actual) { 146*795d594fSAndroid Build Coastguard Worker throw new Error("Expected \"" + expected + "\", got \"" + actual + "\""); 147*795d594fSAndroid Build Coastguard Worker } 148*795d594fSAndroid Build Coastguard Worker } 149*795d594fSAndroid Build Coastguard Worker } 150