001 // Method.java - Represent method of class or interface. 002 003 /* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2006, 2007 Free Software Foundation 004 005 This file is part of libgcj. 006 007 This software is copyrighted work licensed under the terms of the 008 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for 009 details. */ 010 011 package java.lang.reflect; 012 013 import gnu.gcj.RawData; 014 import gnu.java.lang.reflect.MethodSignatureParser; 015 import java.lang.annotation.Annotation; 016 017 /** 018 * The Method class represents a member method of a class. It also allows 019 * dynamic invocation, via reflection. This works for both static and 020 * instance methods. Invocation on Method objects knows how to do 021 * widening conversions, but throws {@link IllegalArgumentException} if 022 * a narrowing conversion would be necessary. You can query for information 023 * on this Method regardless of location, but invocation access may be limited 024 * by Java language access controls. If you can't do it in the compiler, you 025 * can't normally do it here either.<p> 026 * 027 * <B>Note:</B> This class returns and accepts types as Classes, even 028 * primitive types; there are Class types defined that represent each 029 * different primitive type. They are <code>java.lang.Boolean.TYPE, 030 * java.lang.Byte.TYPE,</code>, also available as <code>boolean.class, 031 * byte.class</code>, etc. These are not to be confused with the 032 * classes <code>java.lang.Boolean, java.lang.Byte</code>, etc., which are 033 * real classes.<p> 034 * 035 * Also note that this is not a serializable class. It is entirely feasible 036 * to make it serializable using the Externalizable interface, but this is 037 * on Sun, not me. 038 * 039 * @author John Keiser 040 * @author Eric Blake <ebb9@email.byu.edu> 041 * @author Tom Tromey <tromey@redhat.com> 042 * @see Member 043 * @see Class 044 * @see java.lang.Class#getMethod(String,Class[]) 045 * @see java.lang.Class#getDeclaredMethod(String,Class[]) 046 * @see java.lang.Class#getMethods() 047 * @see java.lang.Class#getDeclaredMethods() 048 * @since 1.1 049 * @status updated to 1.4 050 */ 051 public final class Method 052 extends AccessibleObject implements Member, GenericDeclaration 053 { 054 static final int METHOD_MODIFIERS 055 = Modifier.ABSTRACT | Modifier.FINAL | Modifier.NATIVE 056 | Modifier.PRIVATE | Modifier.PROTECTED | Modifier.PUBLIC 057 | Modifier.STATIC | Modifier.STRICT | Modifier.SYNCHRONIZED; 058 059 /** 060 * This class is uninstantiable. 061 */ 062 private Method () 063 { 064 } 065 066 /** 067 * Gets the class that declared this method, or the class where this method 068 * is a non-inherited member. 069 * @return the class that declared this member 070 */ 071 public Class<?> getDeclaringClass() 072 { 073 return declaringClass; 074 } 075 076 /** 077 * Gets the name of this method. 078 * @return the name of this method 079 */ 080 public native String getName (); 081 082 /** 083 * Return the raw modifiers for this method. 084 * @return the method's modifiers 085 */ 086 private native int getModifiersInternal(); 087 088 /** 089 * Gets the modifiers this method uses. Use the <code>Modifier</code> 090 * class to interpret the values. A method can only have a subset of the 091 * following modifiers: public, private, protected, abstract, static, 092 * final, synchronized, native, and strictfp. 093 * 094 * @return an integer representing the modifiers to this Member 095 * @see Modifier 096 */ 097 public int getModifiers() 098 { 099 return getModifiersInternal() & METHOD_MODIFIERS; 100 } 101 102 /** 103 * Return true if this method is a bridge method. A bridge method 104 * is generated by the compiler in some situations involving 105 * generics and inheritance. 106 * @since 1.5 107 */ 108 public boolean isBridge() 109 { 110 return (getModifiersInternal() & Modifier.BRIDGE) != 0; 111 } 112 113 /** 114 * Return true if this method is synthetic, false otherwise. 115 * @since 1.5 116 */ 117 public boolean isSynthetic() 118 { 119 return (getModifiersInternal() & Modifier.SYNTHETIC) != 0; 120 } 121 122 /** 123 * Return true if this is a varargs method, that is if 124 * the method takes a variable number of arguments. 125 * @since 1.5 126 */ 127 public boolean isVarArgs() 128 { 129 return (getModifiersInternal() & Modifier.VARARGS) != 0; 130 } 131 132 /** 133 * Gets the return type of this method. 134 * @return the type of this method 135 */ 136 public Class<?> getReturnType () 137 { 138 if (return_type == null) 139 getType(); 140 return return_type; 141 } 142 143 /** 144 * Get the parameter list for this method, in declaration order. If the 145 * method takes no parameters, returns a 0-length array (not null). 146 * 147 * @return a list of the types of the method's parameters 148 */ 149 public Class<?>[] getParameterTypes () 150 { 151 if (parameter_types == null) 152 getType(); 153 return (Class<?>[]) parameter_types.clone(); 154 } 155 156 // Just like getParameterTypes, but don't clone the array. 157 // Package private for use by VMProxy. 158 final Class<?>[] internalGetParameterTypes () 159 { 160 if (parameter_types == null) 161 getType(); 162 return (Class<?>[]) parameter_types; 163 } 164 165 /** 166 * Get the exception types this method says it throws, in no particular 167 * order. If the method has no throws clause, returns a 0-length array 168 * (not null). 169 * 170 * @return a list of the types in the method's throws clause 171 */ 172 public Class<?>[] getExceptionTypes () 173 { 174 if (exception_types == null) 175 getType(); 176 return (Class<?>[]) exception_types.clone(); 177 } 178 179 // Just like getExceptionTypes, but don't clone the array. 180 // Package private for use by VMProxy. 181 final Class<?>[] internalGetExceptionTypes () 182 { 183 if (exception_types == null) 184 getType(); 185 return (Class<?>[]) exception_types; 186 } 187 188 /** 189 * Compare two objects to see if they are semantically equivalent. 190 * Two Methods are semantically equivalent if they have the same declaring 191 * class, name, and parameter list. This ignores different exception 192 * clauses or return types. 193 * 194 * @param o the object to compare to 195 * @return <code>true</code> if they are equal; <code>false</code> if not 196 */ 197 public boolean equals (Object obj) 198 { 199 if (! (obj instanceof Method)) 200 return false; 201 Method m = (Method) obj; 202 return declaringClass == m.declaringClass && offset == m.offset; 203 } 204 205 /** 206 * Get the hash code for the Method. The Method hash code is the hash code 207 * of its name XOR'd with the hash code of its class name. 208 * 209 * @return the hash code for the object 210 */ 211 public int hashCode() 212 { 213 return getDeclaringClass().getName().hashCode() ^ getName().hashCode(); 214 } 215 216 /** 217 * Get a String representation of the Method. A Method's String 218 * representation is "<modifiers> <returntype> 219 * <methodname>(<paramtypes>) throws <exceptions>", where 220 * everything after ')' is omitted if there are no exceptions.<br> Example: 221 * <code>public static int run(java.lang.Runnable,int)</code> 222 * 223 * @return the String representation of the Method 224 */ 225 public String toString() 226 { 227 if (parameter_types == null) 228 getType (); 229 230 StringBuffer b = new StringBuffer (); 231 int mods = getModifiers(); 232 if (mods != 0) 233 { 234 Modifier.toString(mods, b); 235 b.append(" "); 236 } 237 appendClassName (b, return_type); 238 b.append(" "); 239 appendClassName (b, declaringClass); 240 b.append("."); 241 b.append(getName()); 242 b.append("("); 243 for (int i = 0; i < parameter_types.length; ++i) 244 { 245 appendClassName (b, parameter_types[i]); 246 if (i < parameter_types.length - 1) 247 b.append(","); 248 } 249 b.append(")"); 250 if (exception_types.length > 0) 251 { 252 b.append(" throws "); 253 for (int i = 0; i < exception_types.length; ++i) 254 { 255 appendClassName (b, exception_types[i]); 256 if (i < exception_types.length - 1) 257 b.append(","); 258 } 259 } 260 return b.toString(); 261 } 262 263 public String toGenericString() 264 { 265 // 128 is a reasonable buffer initial size for constructor 266 StringBuilder sb = new StringBuilder(128); 267 Modifier.toString(getModifiers(), sb).append(' '); 268 Constructor.addTypeParameters(sb, getTypeParameters()); 269 sb.append(getGenericReturnType()).append(' '); 270 sb.append(getDeclaringClass().getName()).append('.'); 271 sb.append(getName()).append('('); 272 Type[] types = getGenericParameterTypes(); 273 if (types.length > 0) 274 { 275 sb.append(types[0]); 276 for (int i = 1; i < types.length; i++) 277 sb.append(',').append(types[i]); 278 } 279 sb.append(')'); 280 types = getGenericExceptionTypes(); 281 if (types.length > 0) 282 { 283 sb.append(" throws ").append(types[0]); 284 for (int i = 1; i < types.length; i++) 285 sb.append(',').append(types[i]); 286 } 287 return sb.toString(); 288 } 289 290 /** 291 * Invoke the method. Arguments are automatically unwrapped and widened, 292 * and the result is automatically wrapped, if needed.<p> 293 * 294 * If the method is static, <code>o</code> will be ignored. Otherwise, 295 * the method uses dynamic lookup as described in JLS 15.12.4.4. You cannot 296 * mimic the behavior of nonvirtual lookup (as in super.foo()). This means 297 * you will get a <code>NullPointerException</code> if <code>o</code> is 298 * null, and an <code>IllegalArgumentException</code> if it is incompatible 299 * with the declaring class of the method. If the method takes 0 arguments, 300 * you may use null or a 0-length array for <code>args</code>.<p> 301 * 302 * Next, if this Method enforces access control, your runtime context is 303 * evaluated, and you may have an <code>IllegalAccessException</code> if 304 * you could not acces this method in similar compiled code. If the method 305 * is static, and its class is uninitialized, you trigger class 306 * initialization, which may end in a 307 * <code>ExceptionInInitializerError</code>.<p> 308 * 309 * Finally, the method is invoked. If it completes normally, the return value 310 * will be null for a void method, a wrapped object for a primitive return 311 * method, or the actual return of an Object method. If it completes 312 * abruptly, the exception is wrapped in an 313 * <code>InvocationTargetException</code>. 314 * 315 * @param o the object to invoke the method on 316 * @param args the arguments to the method 317 * @return the return value of the method, wrapped in the appropriate 318 * wrapper if it is primitive 319 * @throws IllegalAccessException if the method could not normally be called 320 * by the Java code (i.e. it is not public) 321 * @throws IllegalArgumentException if the number of arguments is incorrect; 322 * if the arguments types are wrong even with a widening conversion; 323 * or if <code>o</code> is not an instance of the class or interface 324 * declaring this method 325 * @throws InvocationTargetException if the method throws an exception 326 * @throws NullPointerException if <code>o</code> is null and this field 327 * requires an instance 328 * @throws ExceptionInInitializerError if accessing a static method triggered 329 * class initialization, which then failed 330 */ 331 public native Object invoke (Object obj, Object... args) 332 throws IllegalAccessException, IllegalArgumentException, 333 InvocationTargetException; 334 335 /** 336 * Returns an array of <code>TypeVariable</code> objects that represents 337 * the type variables declared by this constructor, in declaration order. 338 * An array of size zero is returned if this class has no type 339 * variables. 340 * 341 * @return the type variables associated with this class. 342 * @throws GenericSignatureFormatError if the generic signature does 343 * not conform to the format specified in the Virtual Machine 344 * specification, version 3. 345 * @since 1.5 346 */ 347 public TypeVariable<Method>[] getTypeParameters() 348 { 349 String sig = getSignature(); 350 if (sig == null) 351 return new TypeVariable[0]; 352 MethodSignatureParser p = new MethodSignatureParser(this, sig); 353 return p.getTypeParameters(); 354 } 355 356 /** 357 * Return the String in the Signature attribute for this method. If there 358 * is no Signature attribute, return null. 359 */ 360 private native String getSignature(); 361 362 /** 363 * Returns an array of <code>Type</code> objects that represents 364 * the exception types declared by this method, in declaration order. 365 * An array of size zero is returned if this method declares no 366 * exceptions. 367 * 368 * @return the exception types declared by this method. 369 * @throws GenericSignatureFormatError if the generic signature does 370 * not conform to the format specified in the Virtual Machine 371 * specification, version 3. 372 * @since 1.5 373 */ 374 public Type[] getGenericExceptionTypes() 375 { 376 String sig = getSignature(); 377 if (sig == null) 378 return getExceptionTypes(); 379 MethodSignatureParser p = new MethodSignatureParser(this, sig); 380 return p.getGenericExceptionTypes(); 381 } 382 383 /** 384 * Returns an array of <code>Type</code> objects that represents 385 * the parameter list for this method, in declaration order. 386 * An array of size zero is returned if this method takes no 387 * parameters. 388 * 389 * @return a list of the types of the method's parameters 390 * @throws GenericSignatureFormatError if the generic signature does 391 * not conform to the format specified in the Virtual Machine 392 * specification, version 3. 393 * @since 1.5 394 */ 395 public Type[] getGenericParameterTypes() 396 { 397 String sig = getSignature(); 398 if (sig == null) 399 return getParameterTypes(); 400 MethodSignatureParser p = new MethodSignatureParser(this, sig); 401 return p.getGenericParameterTypes(); 402 } 403 404 /** 405 * Returns the return type of this method. 406 * 407 * @return the return type of this method 408 * @throws GenericSignatureFormatError if the generic signature does 409 * not conform to the format specified in the Virtual Machine 410 * specification, version 3. 411 * @since 1.5 412 */ 413 public Type getGenericReturnType() 414 { 415 String sig = getSignature(); 416 if (sig == null) 417 return getReturnType(); 418 MethodSignatureParser p = new MethodSignatureParser(this, sig); 419 return p.getGenericReturnType(); 420 } 421 422 /** 423 * If this method is an annotation method, returns the default 424 * value for the method. If there is no default value, or if the 425 * method is not a member of an annotation type, returns null. 426 * Primitive types are wrapped. 427 * 428 * @throws TypeNotPresentException if the method returns a Class, 429 * and the class cannot be found 430 * 431 * @since 1.5 432 */ 433 public native Object getDefaultValue(); 434 435 public <T extends Annotation> T getAnnotation(Class<T> annoClass) 436 { 437 Annotation[] annos = getDeclaredAnnotations(); 438 for (int i = 0; i < annos.length; ++i) 439 if (annos[i].annotationType() == annoClass) 440 return (T) annos[i]; 441 return null; 442 } 443 444 public Annotation[] getDeclaredAnnotations() 445 { 446 Annotation[] result = getDeclaredAnnotationsInternal(); 447 if (result == null) 448 result = new Annotation[0]; 449 return result; 450 } 451 452 public Annotation[][] getParameterAnnotations() 453 { 454 // FIXME: should check that we have the right number 455 // of parameters ...? 456 Annotation[][] result = getParameterAnnotationsInternal(); 457 if (result == null) 458 result = new Annotation[0][0]; 459 return result; 460 } 461 462 private native Annotation[] getDeclaredAnnotationsInternal(); 463 private native Annotation[][] getParameterAnnotationsInternal(); 464 465 private native void getType (); 466 467 // Append a class name to a string buffer. We try to print the 468 // fully-qualified name, the way that a Java programmer would expect 469 // it to be written. Weirdly, Class has no appropriate method for 470 // this. 471 static void appendClassName (StringBuffer buf, Class k) 472 { 473 if (k.isArray ()) 474 { 475 appendClassName (buf, k.getComponentType ()); 476 buf.append ("[]"); 477 } 478 else 479 { 480 // This is correct for primitive and reference types. Really 481 // we'd like `Main$Inner' to be printed as `Main.Inner', I 482 // think, but that is a pain. 483 buf.append (k.getName ()); 484 } 485 } 486 487 // Declaring class. 488 private Class declaringClass; 489 490 // Exception types. 491 Class[] exception_types; 492 // Name cache. (Initially null.) 493 private String name; 494 // Parameter types. 495 Class[] parameter_types; 496 // Return type. 497 Class return_type; 498 499 // Offset in bytes from the start of declaringClass's methods array. 500 private int offset; 501 }