1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 /* 18 * Copyright (C) 2012 The Android Open Source Project 19 * 20 * Licensed under the Apache License, Version 2.0 (the "License"); 21 * you may not use this file except in compliance with the License. 22 * You may obtain a copy of the License at 23 * 24 * http://www.apache.org/licenses/LICENSE-2.0 25 * 26 * Unless required by applicable law or agreed to in writing, software 27 * distributed under the License is distributed on an "AS IS" BASIS, 28 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 29 * See the License for the specific language governing permissions and 30 * limitations under the License. 31 */ 32 33 package java.lang.reflect; 34 35 import com.android.dex.Dex; 36 import java.lang.annotation.Annotation; 37 import java.util.List; 38 import libcore.reflect.GenericSignatureParser; 39 import libcore.reflect.ListOfTypes; 40 import libcore.reflect.Types; 41 import libcore.util.EmptyArray; 42 43 /** 44 * This class represents an abstract method. Abstract methods are either methods or constructors. 45 * @hide 46 */ 47 public abstract class AbstractMethod extends AccessibleObject { 48 /** Bits encoding access (e.g. public, private) as well as other runtime specific flags */ 49 protected int accessFlags; 50 51 /** 52 * The ArtMethod associated with this Method, requried for dispatching due to entrypoints 53 * Classloader is held live by the declaring class. 54 * Hidden to workaround b/16828157. 55 * @hide 56 */ 57 protected long artMethod; 58 59 /** Method's declaring class */ 60 protected Class<?> declaringClass; 61 62 /** Overriden method's declaring class (same as declaringClass unless declaringClass 63 * is a proxy class) */ 64 protected Class<?> declaringClassOfOverriddenMethod; 65 66 /** The method index of this method within its defining dex file */ 67 protected int dexMethodIndex; 68 69 /** 70 * Hidden to workaround b/16828157. 71 * @hide 72 */ AbstractMethod()73 protected AbstractMethod() { 74 } 75 getAnnotation(Class<T> annotationClass)76 public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { 77 return super.getAnnotation(annotationClass); 78 } 79 80 /** 81 * We insert native method stubs for abstract methods so we don't have to 82 * check the access flags at the time of the method call. This results in 83 * "native abstract" methods, which can't exist. If we see the "abstract" 84 * flag set, clear the "native" flag. 85 * 86 * We also move the DECLARED_SYNCHRONIZED flag into the SYNCHRONIZED 87 * position, because the callers of this function are trying to convey 88 * the "traditional" meaning of the flags to their callers. 89 */ fixMethodFlags(int flags)90 private static int fixMethodFlags(int flags) { 91 if ((flags & Modifier.ABSTRACT) != 0) { 92 flags &= ~Modifier.NATIVE; 93 } 94 flags &= ~Modifier.SYNCHRONIZED; 95 int ACC_DECLARED_SYNCHRONIZED = 0x00020000; 96 if ((flags & ACC_DECLARED_SYNCHRONIZED) != 0) { 97 flags |= Modifier.SYNCHRONIZED; 98 } 99 return flags & 0xffff; // mask out bits not used by Java 100 } 101 getModifiers()102 int getModifiers() { 103 return fixMethodFlags(accessFlags); 104 } 105 isVarArgs()106 boolean isVarArgs() { 107 return (accessFlags & Modifier.VARARGS) != 0; 108 } 109 isBridge()110 boolean isBridge() { 111 return (accessFlags & Modifier.BRIDGE) != 0; 112 } 113 isSynthetic()114 boolean isSynthetic() { 115 return (accessFlags & Modifier.SYNTHETIC) != 0; 116 } 117 isDefault()118 boolean isDefault() { 119 return (accessFlags & Modifier.DEFAULT) != 0; 120 } 121 122 /** 123 * @hide 124 */ getAccessFlags()125 public final int getAccessFlags() { 126 return accessFlags; 127 } 128 129 /** 130 * Returns the class that declares this constructor or method. 131 */ getDeclaringClass()132 Class<?> getDeclaringClass() { 133 return declaringClass; 134 } 135 136 /** 137 * Returns the index of this method's ID in its dex file. 138 * 139 * @hide 140 */ getDexMethodIndex()141 public final int getDexMethodIndex() { 142 return dexMethodIndex; 143 } 144 145 /** 146 * Returns the name of the method or constructor represented by this 147 * instance. 148 * 149 * @return the name of this method 150 */ getName()151 abstract public String getName(); 152 153 /** 154 * Returns an array of {@code Class} objects associated with the parameter types of this 155 * abstract method. If the method was declared with no parameters, an 156 * empty array will be returned. 157 * 158 * @return the parameter types 159 */ getParameterTypes()160 Class<?>[] getParameterTypes() { 161 Dex dex = declaringClassOfOverriddenMethod.getDex(); 162 short[] types = dex.parameterTypeIndicesFromMethodIndex(dexMethodIndex); 163 if (types.length == 0) { 164 return EmptyArray.CLASS; 165 } 166 Class<?>[] parametersArray = new Class[types.length]; 167 for (int i = 0; i < types.length; i++) { 168 // Note, in the case of a Proxy the dex cache types are equal. 169 parametersArray[i] = declaringClassOfOverriddenMethod.getDexCacheType(dex, types[i]); 170 } 171 return parametersArray; 172 } 173 174 /** 175 * Returns true if {@code other} has the same declaring class, name, 176 * parameters and return type as this method. 177 */ equals(Object other)178 @Override public boolean equals(Object other) { 179 if (!(other instanceof AbstractMethod)) { 180 return false; 181 } 182 // Exactly one instance of each member in this runtime, todo, does this work for proxies? 183 AbstractMethod otherMethod = (AbstractMethod) other; 184 return this.declaringClass == otherMethod.declaringClass && 185 this.dexMethodIndex == otherMethod.dexMethodIndex; 186 } 187 toGenericString()188 String toGenericString() { 189 return toGenericStringHelper(); 190 } 191 getGenericParameterTypes()192 Type[] getGenericParameterTypes() { 193 return Types.getTypeArray(getMethodOrConstructorGenericInfo().genericParameterTypes, false); 194 } 195 getGenericExceptionTypes()196 Type[] getGenericExceptionTypes() { 197 return Types.getTypeArray(getMethodOrConstructorGenericInfo().genericExceptionTypes, false); 198 } 199 getDeclaredAnnotations()200 @Override public native Annotation[] getDeclaredAnnotations(); 201 isAnnotationPresent(Class<? extends Annotation> annotationType)202 @Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) { 203 if (annotationType == null) { 204 throw new NullPointerException("annotationType == null"); 205 } 206 return isAnnotationPresentNative(annotationType); 207 } 208 isAnnotationPresentNative(Class<? extends Annotation> annotationType)209 private native boolean isAnnotationPresentNative(Class<? extends Annotation> annotationType); 210 getAnnotations()211 public Annotation[] getAnnotations() { 212 return super.getAnnotations(); 213 } 214 215 /** 216 * Returns an array of arrays that represent the annotations of the formal 217 * parameters of this method. If there are no parameters on this method, 218 * then an empty array is returned. If there are no annotations set, then 219 * and array of empty arrays is returned. 220 * 221 * @return an array of arrays of {@code Annotation} instances 222 */ getParameterAnnotations()223 public abstract Annotation[][] getParameterAnnotations(); 224 225 /** 226 * Returns the constructor's signature in non-printable form. This is called 227 * (only) from IO native code and needed for deriving the serialVersionUID 228 * of the class 229 * 230 * @return The constructor's signature. 231 */ 232 @SuppressWarnings("unused") getSignature()233 abstract String getSignature(); 234 235 static final class GenericInfo { 236 final ListOfTypes genericExceptionTypes; 237 final ListOfTypes genericParameterTypes; 238 final Type genericReturnType; 239 final TypeVariable<?>[] formalTypeParameters; 240 GenericInfo(ListOfTypes exceptions, ListOfTypes parameters, Type ret, TypeVariable<?>[] formal)241 GenericInfo(ListOfTypes exceptions, ListOfTypes parameters, Type ret, 242 TypeVariable<?>[] formal) { 243 genericExceptionTypes = exceptions; 244 genericParameterTypes = parameters; 245 genericReturnType = ret; 246 formalTypeParameters = formal; 247 } 248 } 249 250 /** 251 * Returns generic information associated with this method/constructor member. 252 */ getMethodOrConstructorGenericInfo()253 final GenericInfo getMethodOrConstructorGenericInfo() { 254 String signatureAttribute = getSignatureAttribute(); 255 Member member; 256 Class<?>[] exceptionTypes; 257 boolean method = this instanceof Method; 258 if (method) { 259 Method m = (Method) this; 260 member = m; 261 exceptionTypes = m.getExceptionTypes(); 262 } else { 263 Constructor<?> c = (Constructor<?>) this; 264 member = c; 265 exceptionTypes = c.getExceptionTypes(); 266 } 267 GenericSignatureParser parser = 268 new GenericSignatureParser(member.getDeclaringClass().getClassLoader()); 269 if (method) { 270 parser.parseForMethod((GenericDeclaration) this, signatureAttribute, exceptionTypes); 271 } else { 272 parser.parseForConstructor((GenericDeclaration) this, 273 signatureAttribute, 274 exceptionTypes); 275 } 276 return new GenericInfo(parser.exceptionTypes, parser.parameterTypes, 277 parser.returnType, parser.formalTypeParameters); 278 } 279 getSignatureAttribute()280 private String getSignatureAttribute() { 281 String[] annotation = getSignatureAnnotation(); 282 if (annotation == null) { 283 return null; 284 } 285 StringBuilder result = new StringBuilder(); 286 for (String s : annotation) { 287 result.append(s); 288 } 289 return result.toString(); 290 } 291 getSignatureAnnotation()292 private native String[] getSignatureAnnotation(); 293 equalMethodParameters(Class<?>[] params)294 protected boolean equalMethodParameters(Class<?>[] params) { 295 Dex dex = declaringClassOfOverriddenMethod.getDex(); 296 short[] types = dex.parameterTypeIndicesFromMethodIndex(dexMethodIndex); 297 if (types.length != params.length) { 298 return false; 299 } 300 for (int i = 0; i < types.length; i++) { 301 if (declaringClassOfOverriddenMethod.getDexCacheType(dex, types[i]) != params[i]) { 302 return false; 303 } 304 } 305 return true; 306 } 307 compareParameters(Class<?>[] params)308 protected int compareParameters(Class<?>[] params) { 309 Dex dex = declaringClassOfOverriddenMethod.getDex(); 310 short[] types = dex.parameterTypeIndicesFromMethodIndex(dexMethodIndex); 311 int length = Math.min(types.length, params.length); 312 for (int i = 0; i < length; i++) { 313 Class<?> aType = declaringClassOfOverriddenMethod.getDexCacheType(dex, types[i]); 314 Class<?> bType = params[i]; 315 if (aType != bType) { 316 int comparison = aType.getName().compareTo(bType.getName()); 317 if (comparison != 0) { 318 return comparison; 319 } 320 } 321 } 322 return types.length - params.length; 323 } 324 325 /** 326 * Helper for Method and Constructor for toGenericString 327 */ toGenericStringHelper()328 final String toGenericStringHelper() { 329 StringBuilder sb = new StringBuilder(80); 330 GenericInfo info = getMethodOrConstructorGenericInfo(); 331 int modifiers = ((Member)this).getModifiers(); 332 // append modifiers if any 333 if (modifiers != 0) { 334 sb.append(Modifier.toString(modifiers & ~Modifier.VARARGS)).append(' '); 335 } 336 // append type parameters 337 if (info.formalTypeParameters != null && info.formalTypeParameters.length > 0) { 338 sb.append('<'); 339 for (int i = 0; i < info.formalTypeParameters.length; i++) { 340 Types.appendGenericType(sb, info.formalTypeParameters[i]); 341 if (i < info.formalTypeParameters.length - 1) { 342 sb.append(","); 343 } 344 } 345 sb.append("> "); 346 } 347 Class<?> declaringClass = ((Member) this).getDeclaringClass(); 348 if (this instanceof Constructor) { 349 // append constructor name 350 Types.appendTypeName(sb, declaringClass); 351 } else { 352 // append return type 353 Types.appendGenericType(sb, Types.getType(info.genericReturnType)); 354 sb.append(' '); 355 // append method name 356 Types.appendTypeName(sb, declaringClass); 357 sb.append(".").append(((Method) this).getName()); 358 } 359 // append parameters 360 sb.append('('); 361 Types.appendArrayGenericType(sb, info.genericParameterTypes.getResolvedTypes()); 362 sb.append(')'); 363 // append exceptions if any 364 Type[] genericExceptionTypeArray = 365 Types.getTypeArray(info.genericExceptionTypes, false); 366 if (genericExceptionTypeArray.length > 0) { 367 sb.append(" throws "); 368 Types.appendArrayGenericType(sb, genericExceptionTypeArray); 369 } 370 return sb.toString(); 371 } 372 } 373