• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
method0()22   void method0();
method1(String arg)23   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   void method10(String arg1, String arg2, String arg3, String arg4, String arg5,
25                 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   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
invoke(Object proxy, Method method, Object[] args)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 
testMethod0(Object proxy, Object[] args)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 
testMethod1(Object proxy, Object[] args)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 
testMethod10(Object proxy, Object[] args)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 
testMethod10Even(Object proxy, Object[] args)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`.
getProxyMethodArgument(int arg_pos)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`.
getArgument(int arg_pos, int frame_depth)118   private native Object getArgument(int arg_pos, int frame_depth);
119 }
120 
121 public class Main {
main(String[] args)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 
assertEquals(Object expected, Object actual)138   public static void assertEquals(Object expected, Object actual) {
139     if (expected != actual) {
140       throw new Error("Expected " + expected  + ", got " + actual);
141     }
142   }
143 
assertEquals(String expected, String actual)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