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