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 17 package art; 18 19 import java.lang.reflect.Method; 20 import java.lang.reflect.Proxy; 21 import java.util.Arrays; 22 23 public class Test910 { run()24 public static void run() throws Exception { 25 doTest(); 26 } 27 doTest()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 placeholder 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 testMethod(String className, String methodName, Class<?>... types)41 private static void testMethod(String className, String methodName, Class<?>... types) 42 throws Exception { 43 Class<?> base = Class.forName(className); 44 testMethod(base, methodName, types); 45 } 46 testMethod(Class<?> base, String methodName, Class<?>... types)47 private static void testMethod(Class<?> base, String methodName, Class<?>... types) 48 throws Exception { 49 Method m = base.getDeclaredMethod(methodName, types); 50 testMethod(m, base, true); 51 } 52 testMethod(Method m, Class<?> base, boolean printName)53 private static void testMethod(Method m, Class<?> base, boolean printName) { 54 String[] result = getMethodName(m); 55 if (!result[0].equals(m.getName())) { 56 throw new RuntimeException("Name not equal: " + m.getName() + " vs " + result[0]); 57 } 58 if (printName) { 59 System.out.println(Arrays.toString(result)); 60 } 61 62 Class<?> declClass = getMethodDeclaringClass(m); 63 if (base != declClass) { 64 throw new RuntimeException("Declaring class not equal: " + base + " vs " + declClass); 65 } 66 System.out.println(declClass); 67 68 int modifiers = getMethodModifiers(m); 69 if (modifiers != m.getModifiers()) { 70 throw new RuntimeException("Modifiers not equal: " + m.getModifiers() + " vs " + modifiers); 71 } 72 System.out.println(modifiers); 73 74 System.out.print("Max locals: "); 75 try { 76 System.out.println(getMaxLocals(m)); 77 } catch (RuntimeException e) { 78 System.out.println(e.getMessage()); 79 } 80 81 System.out.print("Argument size: "); 82 try { 83 System.out.println(getArgumentsSize(m)); 84 } catch (RuntimeException e) { 85 System.out.println(e.getMessage()); 86 } 87 88 System.out.print("Location start: "); 89 try { 90 System.out.println(getMethodLocationStart(m)); 91 } catch (RuntimeException e) { 92 System.out.println(e.getMessage()); 93 } 94 95 System.out.print("Location end: "); 96 try { 97 System.out.println(getMethodLocationEnd(m)); 98 } catch (RuntimeException e) { 99 System.out.println(e.getMessage()); 100 } 101 102 System.out.println("Is native: " + isMethodNative(m)); 103 System.out.println("Is obsolete: " + isMethodObsolete(m)); 104 System.out.println("Is synthetic: " + isMethodSynthetic(m)); 105 } 106 107 private static class NestedSynthetic { 108 // Accessing this private field will create a synthetic accessor method; 109 private static String placeholder; 110 } 111 placeholderAccess()112 private static void placeholderAccess() { 113 System.out.println(NestedSynthetic.placeholder); 114 } 115 findSyntheticMethod()116 private static Method findSyntheticMethod() throws Exception { 117 Method methods[] = NestedSynthetic.class.getDeclaredMethods(); 118 for (Method m : methods) { 119 if (m.isSynthetic()) { 120 return m; 121 } 122 } 123 throw new RuntimeException("Could not find synthetic method"); 124 } 125 getMethodName(Method m)126 private static native String[] getMethodName(Method m); getMethodDeclaringClass(Method m)127 private static native Class<?> getMethodDeclaringClass(Method m); getMethodModifiers(Method m)128 private static native int getMethodModifiers(Method m); getMaxLocals(Method m)129 private static native int getMaxLocals(Method m); getArgumentsSize(Method m)130 private static native int getArgumentsSize(Method m); getMethodLocationStart(Method m)131 private static native long getMethodLocationStart(Method m); getMethodLocationEnd(Method m)132 private static native long getMethodLocationEnd(Method m); isMethodNative(Method m)133 private static native boolean isMethodNative(Method m); isMethodObsolete(Method m)134 private static native boolean isMethodObsolete(Method m); isMethodSynthetic(Method m)135 private static native boolean isMethodSynthetic(Method m); 136 137 // We need this machinery for a consistent proxy name. Names of proxy classes include a 138 // unique number (derived by counting). This means that a simple call to getProxyClass 139 // depends on the test environment. 140 // 141 // To work around this, we assume that at most twenty proxies have been created before 142 // the test is run, and canonicalize on "$Proxy20". We add infrastructure to create 143 // as many proxy classes but cycling through subsets of the test-provided interfaces 144 // I0...I4. 145 // 146 // 147 // (This is made under the judgment that we do not want to have proxy-specific behavior 148 // for testMethod.) 149 150 private static Class<?> proxyClass = null; 151 getProxyClass()152 private static Class<?> getProxyClass() throws Exception { 153 if (proxyClass != null) { 154 return proxyClass; 155 } 156 157 for (int i = 1; i <= 21; i++) { 158 proxyClass = createProxyClass(i); 159 String name = proxyClass.getName(); 160 if (name.equals("$Proxy20")) { 161 return proxyClass; 162 } 163 } 164 return proxyClass; 165 } 166 createProxyClass(int i)167 private static Class<?> createProxyClass(int i) throws Exception { 168 int count = Integer.bitCount(i); 169 Class<?>[] input = new Class<?>[count + 1]; 170 input[0] = Runnable.class; 171 int inputIndex = 1; 172 int bitIndex = 0; 173 while (i != 0) { 174 if ((i & 1) != 0) { 175 input[inputIndex++] = Class.forName("art.Test910$I" + bitIndex); 176 } 177 i >>>= 1; 178 bitIndex++; 179 } 180 return Proxy.getProxyClass(Test910.class.getClassLoader(), input); 181 } 182 183 // Need this for the proxy naming. 184 public static interface I0 { 185 } 186 public static interface I1 { 187 } 188 public static interface I2 { 189 } 190 public static interface I3 { 191 } 192 public static interface I4 { 193 } 194 } 195