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