1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 import java.lang.reflect.InvocationHandler; 18 import java.lang.reflect.Method; 19 import java.lang.reflect.Proxy; 20 21 interface TestInterface { 22 void method0(); 23 void method1(String arg); 24 void method10(String arg1, String arg2, String arg3, String arg4, String arg5, 25 String arg6, String arg7, String arg8, String arg9, String arg10); 26 void method10Even(byte arg1, String arg2, short arg3, String arg4, int arg5, 27 String arg6, long arg7, String arg8, double arg9, String arg10); 28 } 29 30 class TestInvocationHandler implements InvocationHandler { 31 @Override 32 public Object invoke(Object proxy, Method method, Object[] args) { 33 // Force garbage collection to try to make `proxy` move in memory 34 // (in the case of a moving garbage collector). 35 System.gc(); 36 37 System.out.println("Proxy for " + TestInterface.class + "." + method.getName()); 38 if (method.getName().equals("method0")) { 39 testMethod0(proxy, args); 40 } else if (method.getName().equals("method1")) { 41 testMethod1(proxy, args); 42 } else if (method.getName().equals("method10")) { 43 testMethod10(proxy, args); 44 } else if (method.getName().equals("method10Even")) { 45 testMethod10Even(proxy, args); 46 } 47 return null; 48 } 49 50 private void testMethod0(Object proxy, Object[] args) { 51 // Get argument 0 (method target) from the proxy method frame ($Proxy0.method0 activation). 52 Object arg0 = getProxyMethodArgument(0); 53 System.out.println(" arg0: " + arg0.getClass().getName()); 54 Main.assertEquals(proxy, arg0); 55 } 56 57 private void testMethod1(Object proxy, Object[] args) { 58 // Get argument 0 (method target) from the proxy method frame ($Proxy0.method0 activation). 59 Object arg0 = getProxyMethodArgument(0); 60 System.out.println(" arg0: " + arg0.getClass().getName()); 61 Main.assertEquals(proxy, arg0); 62 // Get argument 1 from the proxy method frame ($Proxy0.method1 activation). 63 String arg1 = (String) getProxyMethodArgument(1); 64 System.out.println(" arg1: " + arg1.getClass().getName() + " \"" + arg1 + "\""); 65 Main.assertEquals(args[0], arg1); 66 } 67 68 private void testMethod10(Object proxy, Object[] args) { 69 // Get argument 0 (method target) from the proxy method frame ($Proxy0.method10 activation). 70 Object arg0 = getProxyMethodArgument(0); 71 System.out.println(" arg0: " + arg0.getClass().getName()); 72 Main.assertEquals(proxy, arg0); 73 // Get argument `i` from the proxy method frame ($Proxy0.method10 activation). 74 for (int i = 0; i < 10; ++i) { 75 int arg_pos = i + 1; 76 String arg = (String) getProxyMethodArgument(arg_pos); 77 System.out.println(" arg" + arg_pos + ": " + arg.getClass().getName() + " \"" + arg + "\""); 78 Main.assertEquals(args[i], arg); 79 } 80 } 81 82 private void testMethod10Even(Object proxy, Object[] args) { 83 // Get argument 0 (method target) from the proxy method frame ($Proxy0.method10Even 84 // activation). 85 Object arg0 = getProxyMethodArgument(0); 86 System.out.println(" arg0: " + arg0.getClass().getName()); 87 Main.assertEquals(proxy, arg0); 88 // Get argument `i` from the proxy method frame ($Proxy0.method10Even activation). 89 for (int i = 1; i < 10; i += 2) { 90 int arg_pos = i + 1; 91 String arg = (String) getProxyMethodArgument(arg_pos); 92 System.out.println(" arg" + arg_pos + ": " + arg.getClass().getName() + " \"" + arg + "\""); 93 Main.assertEquals(args[i], arg); 94 } 95 } 96 97 // Get reference argument at position `arg_pos` in proxy frame. 98 // This method should only be called from one of the 99 // `TestInvocationHandler.testMethod*` methods via `TestInvocationHandler.invoke`. 100 private Object getProxyMethodArgument(int arg_pos) { 101 // Find proxy frame in stack (from a testMethod* method). 102 // 103 // depth method 104 // ---------------------------------------------------------------------- 105 // 0 TestInvocationHandler.getArgument (outermost frame) 106 // 1 TestInvocationHandler.getProxyMethodArgument 107 // 2 TestInvocationHandler.testMethod* 108 // 3 TestInvocationHandler.invoke 109 // 4 java.lang.reflect.Proxy.invoke 110 // -> 5 TestInterface.method* (proxy method) 111 // 6 Main.main (innermost frame) 112 // 113 int proxy_method_frame_depth = 5; 114 return getArgument(arg_pos, proxy_method_frame_depth); 115 } 116 117 // Get reference argument at position `arg_pos` in frame at depth `frame_depth`. 118 private native Object getArgument(int arg_pos, int frame_depth); 119 } 120 121 public class Main { 122 public static void main(String[] args) { 123 System.loadLibrary(args[0]); 124 125 TestInvocationHandler invocationHandler = new TestInvocationHandler(); 126 TestInterface proxy = (TestInterface) Proxy.newProxyInstance( 127 Main.class.getClassLoader(), 128 new Class<?>[] { TestInterface.class }, 129 invocationHandler); 130 System.out.println("proxy: " + proxy.getClass().getName()); 131 132 proxy.method0(); 133 proxy.method1("a"); 134 proxy.method10("one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"); 135 proxy.method10Even((byte) 1, "two", (short) 3, "four", 5, "six", 7L, "eight", 9.0, "ten"); 136 } 137 138 public static void assertEquals(Object expected, Object actual) { 139 if (expected != actual) { 140 throw new Error("Expected " + expected + ", got " + actual); 141 } 142 } 143 144 public static void assertEquals(String expected, String actual) { 145 if (expected != actual) { 146 throw new Error("Expected \"" + expected + "\", got \"" + actual + "\""); 147 } 148 } 149 } 150