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.AnnotationAccess; 39 import libcore.reflect.GenericSignatureParser; 40 import libcore.reflect.ListOfTypes; 41 import libcore.reflect.Types; 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 49 /** 50 * Hidden to workaround b/16828157. 51 * @hide 52 */ 53 protected final ArtMethod artMethod; 54 55 /** 56 * Hidden to workaround b/16828157. 57 * @hide 58 */ 59 protected AbstractMethod(ArtMethod artMethod) { 60 if (artMethod == null) { 61 throw new NullPointerException("artMethod == null"); 62 } 63 this.artMethod = artMethod; 64 } 65 66 public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { 67 return super.getAnnotation(annotationClass); 68 } 69 70 /** 71 * We insert native method stubs for abstract methods so we don't have to 72 * check the access flags at the time of the method call. This results in 73 * "native abstract" methods, which can't exist. If we see the "abstract" 74 * flag set, clear the "native" flag. 75 * 76 * We also move the DECLARED_SYNCHRONIZED flag into the SYNCHRONIZED 77 * position, because the callers of this function are trying to convey 78 * the "traditional" meaning of the flags to their callers. 79 */ 80 private static int fixMethodFlags(int flags) { 81 if ((flags & Modifier.ABSTRACT) != 0) { 82 flags &= ~Modifier.NATIVE; 83 } 84 flags &= ~Modifier.SYNCHRONIZED; 85 int ACC_DECLARED_SYNCHRONIZED = 0x00020000; 86 if ((flags & ACC_DECLARED_SYNCHRONIZED) != 0) { 87 flags |= Modifier.SYNCHRONIZED; 88 } 89 return flags & 0xffff; // mask out bits not used by Java 90 } 91 92 int getModifiers() { 93 return fixMethodFlags(artMethod.getAccessFlags()); 94 } 95 96 boolean isVarArgs() { 97 return (artMethod.getAccessFlags() & Modifier.VARARGS) != 0; 98 } 99 100 boolean isBridge() { 101 return (artMethod.getAccessFlags() & Modifier.BRIDGE) != 0; 102 } 103 104 boolean isSynthetic() { 105 return (artMethod.getAccessFlags() & Modifier.SYNTHETIC) != 0; 106 } 107 108 /** 109 * @hide 110 */ 111 public final int getAccessFlags() { 112 return artMethod.getAccessFlags(); 113 } 114 115 /** 116 * Returns the class that declares this constructor or method. 117 */ 118 Class<?> getDeclaringClass() { 119 return artMethod.getDeclaringClass(); 120 } 121 122 /** 123 * Returns the index of this method's ID in its dex file. 124 * 125 * @hide 126 */ 127 public final int getDexMethodIndex() { 128 return artMethod.getDexMethodIndex(); 129 } 130 131 /** 132 * Returns the name of the method or constructor represented by this 133 * instance. 134 * 135 * @return the name of this method 136 */ 137 abstract public String getName(); 138 139 /** 140 * Returns an array of {@code Class} objects associated with the parameter types of this 141 * abstract method. If the method was declared with no parameters, an 142 * empty array will be returned. 143 * 144 * @return the parameter types 145 */ 146 Class<?>[] getParameterTypes() { 147 return artMethod.getParameterTypes(); 148 } 149 150 /** 151 * Returns true if {@code other} has the same declaring class, name, 152 * parameters and return type as this method. 153 */ 154 @Override public boolean equals(Object other) { 155 if (!(other instanceof AbstractMethod)) { 156 return false; 157 } 158 // exactly one instance of each member in this runtime 159 return this.artMethod == ((AbstractMethod) other).artMethod; 160 } 161 162 String toGenericString() { 163 return toGenericStringHelper(); 164 } 165 166 Type[] getGenericParameterTypes() { 167 return Types.getTypeArray(getMethodOrConstructorGenericInfo().genericParameterTypes, false); 168 } 169 170 Type[] getGenericExceptionTypes() { 171 return Types.getTypeArray(getMethodOrConstructorGenericInfo().genericExceptionTypes, false); 172 } 173 174 @Override public Annotation[] getDeclaredAnnotations() { 175 List<Annotation> result = AnnotationAccess.getDeclaredAnnotations(this); 176 return result.toArray(new Annotation[result.size()]); 177 } 178 179 @Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) { 180 if (annotationType == null) { 181 throw new NullPointerException("annotationType == null"); 182 } 183 return AnnotationAccess.isDeclaredAnnotationPresent(this, annotationType); 184 } 185 186 public Annotation[] getAnnotations() { 187 return super.getAnnotations(); 188 } 189 190 /** 191 * Returns an array of arrays that represent the annotations of the formal 192 * parameters of this method. If there are no parameters on this method, 193 * then an empty array is returned. If there are no annotations set, then 194 * and array of empty arrays is returned. 195 * 196 * @return an array of arrays of {@code Annotation} instances 197 */ 198 public abstract Annotation[][] getParameterAnnotations(); 199 200 /** 201 * Returns the constructor's signature in non-printable form. This is called 202 * (only) from IO native code and needed for deriving the serialVersionUID 203 * of the class 204 * 205 * @return The constructor's signature. 206 */ 207 @SuppressWarnings("unused") 208 abstract String getSignature(); 209 210 static final class GenericInfo { 211 final ListOfTypes genericExceptionTypes; 212 final ListOfTypes genericParameterTypes; 213 final Type genericReturnType; 214 final TypeVariable<?>[] formalTypeParameters; 215 216 GenericInfo(ListOfTypes exceptions, ListOfTypes parameters, Type ret, 217 TypeVariable<?>[] formal) { 218 genericExceptionTypes = exceptions; 219 genericParameterTypes = parameters; 220 genericReturnType = ret; 221 formalTypeParameters = formal; 222 } 223 } 224 225 /** 226 * Returns generic information associated with this method/constructor member. 227 */ 228 final GenericInfo getMethodOrConstructorGenericInfo() { 229 String signatureAttribute = AnnotationAccess.getSignature(this); 230 Member member; 231 Class<?>[] exceptionTypes; 232 boolean method = this instanceof Method; 233 if (method) { 234 Method m = (Method) this; 235 member = m; 236 exceptionTypes = m.getExceptionTypes(); 237 } else { 238 Constructor<?> c = (Constructor<?>) this; 239 member = c; 240 exceptionTypes = c.getExceptionTypes(); 241 } 242 GenericSignatureParser parser = 243 new GenericSignatureParser(member.getDeclaringClass().getClassLoader()); 244 if (method) { 245 parser.parseForMethod((GenericDeclaration) this, signatureAttribute, exceptionTypes); 246 } else { 247 parser.parseForConstructor((GenericDeclaration) this, 248 signatureAttribute, 249 exceptionTypes); 250 } 251 return new GenericInfo(parser.exceptionTypes, parser.parameterTypes, 252 parser.returnType, parser.formalTypeParameters); 253 } 254 255 /** 256 * Helper for Method and Constructor for toGenericString 257 */ 258 final String toGenericStringHelper() { 259 StringBuilder sb = new StringBuilder(80); 260 GenericInfo info = getMethodOrConstructorGenericInfo(); 261 int modifiers = ((Member)this).getModifiers(); 262 // append modifiers if any 263 if (modifiers != 0) { 264 sb.append(Modifier.toString(modifiers & ~Modifier.VARARGS)).append(' '); 265 } 266 // append type parameters 267 if (info.formalTypeParameters != null && info.formalTypeParameters.length > 0) { 268 sb.append('<'); 269 for (int i = 0; i < info.formalTypeParameters.length; i++) { 270 Types.appendGenericType(sb, info.formalTypeParameters[i]); 271 if (i < info.formalTypeParameters.length - 1) { 272 sb.append(","); 273 } 274 } 275 sb.append("> "); 276 } 277 Class<?> declaringClass = ((Member) this).getDeclaringClass(); 278 if (this instanceof Constructor) { 279 // append constructor name 280 Types.appendTypeName(sb, declaringClass); 281 } else { 282 // append return type 283 Types.appendGenericType(sb, Types.getType(info.genericReturnType)); 284 sb.append(' '); 285 // append method name 286 Types.appendTypeName(sb, declaringClass); 287 sb.append(".").append(((Method) this).getName()); 288 } 289 // append parameters 290 sb.append('('); 291 Types.appendArrayGenericType(sb, info.genericParameterTypes.getResolvedTypes()); 292 sb.append(')'); 293 // append exceptions if any 294 Type[] genericExceptionTypeArray = 295 Types.getTypeArray(info.genericExceptionTypes, false); 296 if (genericExceptionTypeArray.length > 0) { 297 sb.append(" throws "); 298 Types.appendArrayGenericType(sb, genericExceptionTypeArray); 299 } 300 return sb.toString(); 301 } 302 } 303