Main.java revision fdeef52e2b7df4cd2184bb42deb8f1e4325cedce
1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17import java.lang.reflect.Method;
18import java.lang.reflect.Proxy;
19import java.util.Arrays;
20
21public class Main {
22  public static void main(String[] args) throws Exception {
23    System.loadLibrary(args[1]);
24
25    doTest();
26  }
27
28  public static void doTest() throws Exception {
29    testMethod("java.lang.Object", "toString");
30    testMethod("java.lang.String", "charAt", int.class);
31    testMethod("java.lang.Math", "sqrt", double.class);
32    testMethod("java.util.List", "add", Object.class);
33
34    testMethod(getProxyClass(), "run");
35
36    // Find a synthetic method in the dummy inner class. Do not print the name. Javac and Jack
37    // disagree on the naming of synthetic accessors.
38    testMethod(findSyntheticMethod(), NestedSynthetic.class, false);
39  }
40
41  private static Class<?> proxyClass = null;
42
43  private static Class<?> getProxyClass() throws Exception {
44    if (proxyClass != null) {
45      return proxyClass;
46    }
47
48    proxyClass = Proxy.getProxyClass(Main.class.getClassLoader(), new Class[] { Runnable.class });
49    return proxyClass;
50  }
51
52  private static void testMethod(String className, String methodName, Class<?>... types)
53      throws Exception {
54    Class<?> base = Class.forName(className);
55    testMethod(base, methodName, types);
56  }
57
58  private static void testMethod(Class<?> base, String methodName, Class<?>... types)
59      throws Exception {
60    Method m = base.getDeclaredMethod(methodName, types);
61    testMethod(m, base, true);
62  }
63
64  private static void testMethod(Method m, Class<?> base, boolean printName) {
65    String[] result = getMethodName(m);
66    if (!result[0].equals(m.getName())) {
67      throw new RuntimeException("Name not equal: " + m.getName() + " vs " + result[0]);
68    }
69    if (printName) {
70      System.out.println(Arrays.toString(result));
71    }
72
73    Class<?> declClass = getMethodDeclaringClass(m);
74    if (base != declClass) {
75      throw new RuntimeException("Declaring class not equal: " + base + " vs " + declClass);
76    }
77    System.out.println(declClass);
78
79    int modifiers = getMethodModifiers(m);
80    if (modifiers != m.getModifiers()) {
81      throw new RuntimeException("Modifiers not equal: " + m.getModifiers() + " vs " + modifiers);
82    }
83    System.out.println(modifiers);
84
85    System.out.print("Max locals: ");
86    try {
87      System.out.println(getMaxLocals(m));
88    } catch (RuntimeException e) {
89      System.out.println(e.getMessage());
90    }
91
92    System.out.print("Argument size: ");
93    try {
94      System.out.println(getArgumentsSize(m));
95    } catch (RuntimeException e) {
96      System.out.println(e.getMessage());
97    }
98
99    System.out.print("Location start: ");
100    try {
101      System.out.println(getMethodLocationStart(m));
102    } catch (RuntimeException e) {
103      System.out.println(e.getMessage());
104    }
105
106    System.out.print("Location end: ");
107    try {
108      System.out.println(getMethodLocationEnd(m));
109    } catch (RuntimeException e) {
110      System.out.println(e.getMessage());
111    }
112
113    System.out.println("Is native: " + isMethodNative(m));
114    System.out.println("Is obsolete: " + isMethodObsolete(m));
115    System.out.println("Is synthetic: " + isMethodSynthetic(m));
116  }
117
118  private static class NestedSynthetic {
119    // Accessing this private field will create a synthetic accessor method;
120    private static String dummy;
121  }
122
123  private static void dummyAccess() {
124    System.out.println(NestedSynthetic.dummy);
125  }
126
127  private static Method findSyntheticMethod() throws Exception {
128    Method methods[] = NestedSynthetic.class.getDeclaredMethods();
129    for (Method m : methods) {
130      if (m.isSynthetic()) {
131        return m;
132      }
133    }
134    throw new RuntimeException("Could not find synthetic method");
135  }
136
137  private static native String[] getMethodName(Method m);
138  private static native Class<?> getMethodDeclaringClass(Method m);
139  private static native int getMethodModifiers(Method m);
140  private static native int getMaxLocals(Method m);
141  private static native int getArgumentsSize(Method m);
142  private static native long getMethodLocationStart(Method m);
143  private static native long getMethodLocationEnd(Method m);
144  private static native boolean isMethodNative(Method m);
145  private static native boolean isMethodObsolete(Method m);
146  private static native boolean isMethodSynthetic(Method m);
147}
148