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) 2008 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 33package java.lang.reflect; 34 35import java.lang.annotation.Annotation; 36import java.util.Arrays; 37import java.util.Comparator; 38import libcore.util.EmptyArray; 39import org.apache.harmony.kernel.vm.StringUtils; 40import libcore.reflect.GenericSignatureParser; 41import libcore.reflect.ListOfTypes; 42import libcore.reflect.Types; 43 44/** 45 * This class represents a method. Information about the method can be accessed, 46 * and the method can be invoked dynamically. 47 */ 48public final class Method extends AccessibleObject implements GenericDeclaration, Member { 49 50 /** 51 * Orders methods by their name, parameters and return type. 52 * 53 * @hide 54 */ 55 public static final Comparator<Method> ORDER_BY_SIGNATURE = new Comparator<Method>() { 56 public int compare(Method a, Method b) { 57 int comparison = a.name.compareTo(b.name); 58 if (comparison != 0) { 59 return comparison; 60 } 61 62 Class<?>[] aParameters = a.parameterTypes; 63 Class<?>[] bParameters = b.parameterTypes; 64 int length = Math.min(aParameters.length, bParameters.length); 65 for (int i = 0; i < length; i++) { 66 comparison = aParameters[i].getName().compareTo(bParameters[i].getName()); 67 if (comparison != 0) { 68 return comparison; 69 } 70 } 71 72 if (aParameters.length != bParameters.length) { 73 return aParameters.length - bParameters.length; 74 } 75 76 // this is necessary for methods that have covariant return types. 77 return a.getReturnType().getName().compareTo(b.getReturnType().getName()); 78 } 79 }; 80 81 private int slot; 82 83 private final int methodDexIndex; 84 85 private Class<?> declaringClass; 86 87 private String name; 88 89 private Class<?>[] parameterTypes; 90 91 private Class<?>[] exceptionTypes; 92 93 private Class<?> returnType; 94 95 private ListOfTypes genericExceptionTypes; 96 private ListOfTypes genericParameterTypes; 97 private Type genericReturnType; 98 private TypeVariable<Method>[] formalTypeParameters; 99 private volatile boolean genericTypesAreInitialized = false; 100 101 private synchronized void initGenericTypes() { 102 if (!genericTypesAreInitialized) { 103 String signatureAttribute = getSignatureAttribute(); 104 GenericSignatureParser parser = new GenericSignatureParser( 105 declaringClass.getClassLoader()); 106 parser.parseForMethod(this, signatureAttribute, exceptionTypes); 107 formalTypeParameters = parser.formalTypeParameters; 108 genericParameterTypes = parser.parameterTypes; 109 genericExceptionTypes = parser.exceptionTypes; 110 genericReturnType = parser.returnType; 111 genericTypesAreInitialized = true; 112 } 113 } 114 115 private Method(Class<?> declaring, Class<?>[] paramTypes, Class<?>[] exceptTypes, Class<?> returnType, String name, int slot, int methodDexIndex) { 116 this.declaringClass = declaring; 117 this.name = name; 118 this.slot = slot; 119 this.parameterTypes = paramTypes; 120 this.exceptionTypes = exceptTypes; // may be null 121 this.returnType = returnType; 122 this.methodDexIndex = methodDexIndex; 123 } 124 125 /** @hide */ 126 public int getDexMethodIndex() { 127 return methodDexIndex; 128 } 129 130 public TypeVariable<Method>[] getTypeParameters() { 131 initGenericTypes(); 132 return formalTypeParameters.clone(); 133 } 134 135 /** {@inheritDoc} */ 136 @Override /*package*/ String getSignatureAttribute() { 137 Object[] annotation = getSignatureAnnotation(declaringClass, slot); 138 139 if (annotation == null) { 140 return null; 141 } 142 143 return StringUtils.combineStrings(annotation); 144 } 145 146 /** 147 * Returns the Signature annotation for this method. Returns {@code null} if 148 * not found. 149 */ 150 static native Object[] getSignatureAnnotation(Class declaringClass, int slot); 151 152 /** 153 * Returns the string representation of the method's declaration, including 154 * the type parameters. 155 * 156 * @return the string representation of this method 157 */ 158 public String toGenericString() { 159 StringBuilder sb = new StringBuilder(80); 160 161 initGenericTypes(); 162 163 // append modifiers if any 164 int modifier = getModifiers(); 165 if (modifier != 0) { 166 sb.append(Modifier.toString(modifier & ~(Modifier.BRIDGE + 167 Modifier.VARARGS))).append(' '); 168 } 169 // append type parameters 170 if (formalTypeParameters != null && formalTypeParameters.length > 0) { 171 sb.append('<'); 172 for (int i = 0; i < formalTypeParameters.length; i++) { 173 appendGenericType(sb, formalTypeParameters[i]); 174 if (i < formalTypeParameters.length - 1) { 175 sb.append(","); 176 } 177 } 178 sb.append("> "); 179 } 180 // append return type 181 appendGenericType(sb, Types.getType(genericReturnType)); 182 sb.append(' '); 183 // append method name 184 appendTypeName(sb, getDeclaringClass()); 185 sb.append(".").append(getName()); 186 // append parameters 187 sb.append('('); 188 appendArrayGenericType(sb, Types.getTypeArray(genericParameterTypes, false)); 189 sb.append(')'); 190 // append exceptions if any 191 Type[] genericExceptionTypeArray = Types.getTypeArray(genericExceptionTypes, false); 192 if (genericExceptionTypeArray.length > 0) { 193 sb.append(" throws "); 194 appendArrayGenericType(sb, genericExceptionTypeArray); 195 } 196 return sb.toString(); 197 } 198 199 /** 200 * Returns the parameter types as an array of {@code Type} instances, in 201 * declaration order. If this method has no parameters, an empty array is 202 * returned. 203 * 204 * @return the parameter types 205 * 206 * @throws GenericSignatureFormatError 207 * if the generic method signature is invalid 208 * @throws TypeNotPresentException 209 * if any parameter type points to a missing type 210 * @throws MalformedParameterizedTypeException 211 * if any parameter type points to a type that cannot be 212 * instantiated for some reason 213 */ 214 public Type[] getGenericParameterTypes() { 215 initGenericTypes(); 216 return Types.getTypeArray(genericParameterTypes, true); 217 } 218 219 /** 220 * Returns the exception types as an array of {@code Type} instances. If 221 * this method has no declared exceptions, an empty array will be returned. 222 * 223 * @return an array of generic exception types 224 * 225 * @throws GenericSignatureFormatError 226 * if the generic method signature is invalid 227 * @throws TypeNotPresentException 228 * if any exception type points to a missing type 229 * @throws MalformedParameterizedTypeException 230 * if any exception type points to a type that cannot be 231 * instantiated for some reason 232 */ 233 public Type[] getGenericExceptionTypes() { 234 initGenericTypes(); 235 return Types.getTypeArray(genericExceptionTypes, true); 236 } 237 238 /** 239 * Returns the return type of this method as a {@code Type} instance. 240 * 241 * @return the return type of this method 242 * 243 * @throws GenericSignatureFormatError 244 * if the generic method signature is invalid 245 * @throws TypeNotPresentException 246 * if the return type points to a missing type 247 * @throws MalformedParameterizedTypeException 248 * if the return type points to a type that cannot be 249 * instantiated for some reason 250 */ 251 public Type getGenericReturnType() { 252 initGenericTypes(); 253 return Types.getType(genericReturnType); 254 } 255 256 @Override 257 public Annotation[] getDeclaredAnnotations() { 258 return getDeclaredAnnotations(declaringClass, slot); 259 } 260 static native Annotation[] getDeclaredAnnotations(Class<?> declaringClass, int slot); 261 262 @Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) { 263 if (annotationType == null) { 264 throw new NullPointerException("annotationType == null"); 265 } 266 return getAnnotation(declaringClass, slot, annotationType); 267 } 268 static native <A extends Annotation> A getAnnotation( 269 Class<?> declaringClass, int slot, Class<A> annotationType); 270 271 @Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) { 272 if (annotationType == null) { 273 throw new NullPointerException("annotationType == null"); 274 } 275 return isAnnotationPresent(declaringClass, slot, annotationType); 276 } 277 static native boolean isAnnotationPresent( 278 Class<?> declaringClass, int slot, Class<? extends Annotation> annotationType); 279 280 private static final Annotation[] NO_ANNOTATIONS = new Annotation[0]; 281 282 /** 283 * Creates an array of empty Annotation arrays. 284 */ 285 /*package*/ static Annotation[][] noAnnotations(int size) { 286 Annotation[][] annotations = new Annotation[size][]; 287 for (int i = 0; i < size; i++) { 288 annotations[i] = NO_ANNOTATIONS; 289 } 290 return annotations; 291 } 292 293 /** 294 * Returns an array of arrays that represent the annotations of the formal 295 * parameters of this method. If there are no parameters on this method, 296 * then an empty array is returned. If there are no annotations set, then 297 * and array of empty arrays is returned. 298 * 299 * @return an array of arrays of {@code Annotation} instances 300 */ 301 public Annotation[][] getParameterAnnotations() { 302 Annotation[][] parameterAnnotations 303 = getParameterAnnotations(declaringClass, slot); 304 if (parameterAnnotations.length == 0) { 305 return noAnnotations(parameterTypes.length); 306 } 307 return parameterAnnotations; 308 } 309 310 static native Annotation[][] getParameterAnnotations(Class declaringClass, int slot); 311 312 /** 313 * Indicates whether or not this method takes a variable number argument. 314 * 315 * @return {@code true} if a vararg is declared, {@code false} otherwise 316 */ 317 public boolean isVarArgs() { 318 int modifiers = getMethodModifiers(declaringClass, slot); 319 return (modifiers & Modifier.VARARGS) != 0; 320 } 321 322 /** 323 * Indicates whether or not this method is a bridge. 324 * 325 * @return {@code true} if this method is a bridge, {@code false} otherwise 326 */ 327 public boolean isBridge() { 328 int modifiers = getMethodModifiers(declaringClass, slot); 329 return (modifiers & Modifier.BRIDGE) != 0; 330 } 331 332 /** 333 * Indicates whether or not this method is synthetic. 334 * 335 * @return {@code true} if this method is synthetic, {@code false} otherwise 336 */ 337 public boolean isSynthetic() { 338 int modifiers = getMethodModifiers(declaringClass, slot); 339 return (modifiers & Modifier.SYNTHETIC) != 0; 340 } 341 342 /** 343 * Returns the default value for the annotation member represented by this 344 * method. 345 * 346 * @return the default value, or {@code null} if none 347 * 348 * @throws TypeNotPresentException 349 * if this annotation member is of type {@code Class} and no 350 * definition can be found 351 */ 352 public Object getDefaultValue() { 353 return getDefaultValue(declaringClass, slot); 354 } 355 native private Object getDefaultValue(Class declaringClass, int slot); 356 357 /** 358 * Indicates whether or not the specified {@code object} is equal to this 359 * method. To be equal, the specified object must be an instance 360 * of {@code Method} with the same declaring class and parameter types 361 * as this method. 362 * 363 * @param object 364 * the object to compare 365 * 366 * @return {@code true} if the specified object is equal to this 367 * method, {@code false} otherwise 368 * 369 * @see #hashCode 370 */ 371 @Override 372 public boolean equals(Object object) { 373 if (this == object) { 374 return true; 375 } 376 if (!(object instanceof Method)) { 377 return false; 378 } 379 Method rhs = (Method) object; 380 // We don't compare exceptionTypes because two methods 381 // can't differ only by their declared exceptions. 382 return declaringClass.equals(rhs.declaringClass) && 383 name.equals(rhs.name) && 384 getModifiers() == rhs.getModifiers() && 385 returnType.equals(rhs.returnType) && 386 Arrays.equals(parameterTypes, rhs.parameterTypes); 387 } 388 389 /** 390 * Returns the class that declares this method. 391 * 392 * @return the declaring class 393 */ 394 public Class<?> getDeclaringClass() { 395 return declaringClass; 396 } 397 398 /** 399 * Returns the exception types as an array of {@code Class} instances. If 400 * this method has no declared exceptions, an empty array is returned. 401 * 402 * @return the declared exception classes 403 */ 404 public Class<?>[] getExceptionTypes() { 405 if (exceptionTypes == null) { 406 return EmptyArray.CLASS; 407 } 408 return exceptionTypes.clone(); 409 } 410 411 /** 412 * Returns the modifiers for this method. The {@link Modifier} class should 413 * be used to decode the result. 414 * 415 * @return the modifiers for this method 416 * 417 * @see Modifier 418 */ 419 public int getModifiers() { 420 return getMethodModifiers(declaringClass, slot); 421 } 422 423 static native int getMethodModifiers(Class<?> declaringClass, int slot); 424 425 /** 426 * Returns the name of the method represented by this {@code Method} 427 * instance. 428 * 429 * @return the name of this method 430 */ 431 public String getName() { 432 return name; 433 } 434 435 /** 436 * Returns an array of {@code Class} objects associated with the parameter 437 * types of this method. If the method was declared with no parameters, an 438 * empty array will be returned. 439 * 440 * @return the parameter types 441 */ 442 public Class<?>[] getParameterTypes() { 443 return parameterTypes.clone(); 444 } 445 446 /** 447 * Returns the {@code Class} associated with the return type of this 448 * method. 449 * 450 * @return the return type 451 */ 452 public Class<?> getReturnType() { 453 return returnType; 454 } 455 456 /** 457 * Returns an integer hash code for this method. Objects which are equal 458 * return the same value for this method. The hash code for this Method is 459 * the hash code of the name of this method. 460 * 461 * @return hash code for this method 462 * 463 * @see #equals 464 */ 465 @Override 466 public int hashCode() { 467 return name.hashCode(); 468 } 469 470 /** 471 * Returns the result of dynamically invoking this method. Equivalent to 472 * {@code receiver.methodName(arg1, arg2, ... , argN)}. 473 * 474 * <p>If the method is static, the receiver argument is ignored (and may be null). 475 * 476 * <p>If the method takes no arguments, you can pass {@code (Object[]) null} instead of 477 * allocating an empty array. 478 * 479 * <p>If you're calling a varargs method, you need to pass an {@code Object[]} for the 480 * varargs parameter: that conversion is usually done in {@code javac}, not the VM, and 481 * the reflection machinery does not do this for you. (It couldn't, because it would be 482 * ambiguous.) 483 * 484 * <p>Reflective method invocation follows the usual process for method lookup. 485 * 486 * <p>If an exception is thrown during the invocation it is caught and 487 * wrapped in an InvocationTargetException. This exception is then thrown. 488 * 489 * <p>If the invocation completes normally, the return value itself is 490 * returned. If the method is declared to return a primitive type, the 491 * return value is boxed. If the return type is void, null is returned. 492 * 493 * @param receiver 494 * the object on which to call this method (or null for static methods) 495 * @param args 496 * the arguments to the method 497 * @return the result 498 * 499 * @throws NullPointerException 500 * if {@code receiver == null} for a non-static method 501 * @throws IllegalAccessException 502 * if this method is not accessible (see {@link AccessibleObject}) 503 * @throws IllegalArgumentException 504 * if the number of arguments doesn't match the number of parameters, the receiver 505 * is incompatible with the declaring class, or an argument could not be unboxed 506 * or converted by a widening conversion to the corresponding parameter type 507 * @throws InvocationTargetException 508 * if an exception was thrown by the invoked method 509 */ 510 public Object invoke(Object receiver, Object... args) 511 throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { 512 if (args == null) { 513 args = EmptyArray.OBJECT; 514 } 515 return invokeNative(receiver, args, declaringClass, parameterTypes, returnType, slot, flag); 516 } 517 518 private native Object invokeNative(Object obj, Object[] args, Class<?> declaringClass, 519 Class<?>[] parameterTypes, Class<?> returnType, int slot, boolean noAccessCheck) 520 throws IllegalAccessException, IllegalArgumentException, 521 InvocationTargetException; 522 523 /** 524 * Returns a string containing a concise, human-readable description of this 525 * method. The format of the string is: 526 * 527 * <ol> 528 * <li>modifiers (if any) 529 * <li>return type or 'void' 530 * <li>declaring class name 531 * <li>'(' 532 * <li>parameter types, separated by ',' (if any) 533 * <li>')' 534 * <li>'throws' plus exception types, separated by ',' (if any) 535 * </ol> 536 * 537 * For example: {@code public native Object 538 * java.lang.Method.invoke(Object,Object) throws 539 * IllegalAccessException,IllegalArgumentException 540 * ,InvocationTargetException} 541 * 542 * @return a printable representation for this method 543 */ 544 @Override 545 public String toString() { 546 StringBuilder result = new StringBuilder(Modifier.toString(getModifiers())); 547 548 if (result.length() != 0) 549 result.append(' '); 550 result.append(returnType.getName()); 551 result.append(' '); 552 result.append(declaringClass.getName()); 553 result.append('.'); 554 result.append(name); 555 result.append("("); 556 result.append(toString(parameterTypes)); 557 result.append(")"); 558 if (exceptionTypes != null && exceptionTypes.length != 0) { 559 result.append(" throws "); 560 result.append(toString(exceptionTypes)); 561 } 562 563 return result.toString(); 564 } 565 566 /** 567 * Returns the constructor's signature in non-printable form. This is called 568 * (only) from IO native code and needed for deriving the serialVersionUID 569 * of the class 570 * 571 * @return The constructor's signature. 572 */ 573 @SuppressWarnings("unused") 574 private String getSignature() { 575 StringBuilder result = new StringBuilder(); 576 577 result.append('('); 578 for (int i = 0; i < parameterTypes.length; i++) { 579 result.append(getSignature(parameterTypes[i])); 580 } 581 result.append(')'); 582 result.append(getSignature(returnType)); 583 584 return result.toString(); 585 } 586 587} 588