1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/emul/src/main/java/java/lang/reflect/Method.java Tue Dec 04 13:29:17 2012 +0100
1.3 @@ -0,0 +1,767 @@
1.4 +/*
1.5 + * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1.7 + *
1.8 + * This code is free software; you can redistribute it and/or modify it
1.9 + * under the terms of the GNU General Public License version 2 only, as
1.10 + * published by the Free Software Foundation. Oracle designates this
1.11 + * particular file as subject to the "Classpath" exception as provided
1.12 + * by Oracle in the LICENSE file that accompanied this code.
1.13 + *
1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1.17 + * version 2 for more details (a copy is included in the LICENSE file that
1.18 + * accompanied this code).
1.19 + *
1.20 + * You should have received a copy of the GNU General Public License version
1.21 + * 2 along with this work; if not, write to the Free Software Foundation,
1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1.23 + *
1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1.25 + * or visit www.oracle.com if you need additional information or have any
1.26 + * questions.
1.27 + */
1.28 +
1.29 +package java.lang.reflect;
1.30 +
1.31 +import sun.reflect.MethodAccessor;
1.32 +import sun.reflect.Reflection;
1.33 +import sun.reflect.generics.repository.MethodRepository;
1.34 +import sun.reflect.generics.factory.CoreReflectionFactory;
1.35 +import sun.reflect.generics.factory.GenericsFactory;
1.36 +import sun.reflect.generics.scope.MethodScope;
1.37 +import sun.reflect.annotation.AnnotationType;
1.38 +import sun.reflect.annotation.AnnotationParser;
1.39 +import java.lang.annotation.Annotation;
1.40 +import java.lang.annotation.AnnotationFormatError;
1.41 +import java.nio.ByteBuffer;
1.42 +import java.util.Map;
1.43 +
1.44 +/**
1.45 + * A {@code Method} provides information about, and access to, a single method
1.46 + * on a class or interface. The reflected method may be a class method
1.47 + * or an instance method (including an abstract method).
1.48 + *
1.49 + * <p>A {@code Method} permits widening conversions to occur when matching the
1.50 + * actual parameters to invoke with the underlying method's formal
1.51 + * parameters, but it throws an {@code IllegalArgumentException} if a
1.52 + * narrowing conversion would occur.
1.53 + *
1.54 + * @see Member
1.55 + * @see java.lang.Class
1.56 + * @see java.lang.Class#getMethods()
1.57 + * @see java.lang.Class#getMethod(String, Class[])
1.58 + * @see java.lang.Class#getDeclaredMethods()
1.59 + * @see java.lang.Class#getDeclaredMethod(String, Class[])
1.60 + *
1.61 + * @author Kenneth Russell
1.62 + * @author Nakul Saraiya
1.63 + */
1.64 +public final
1.65 + class Method extends AccessibleObject implements GenericDeclaration,
1.66 + Member {
1.67 + private Class<?> clazz;
1.68 + private int slot;
1.69 + // This is guaranteed to be interned by the VM in the 1.4
1.70 + // reflection implementation
1.71 + private String name;
1.72 + private Class<?> returnType;
1.73 + private Class<?>[] parameterTypes;
1.74 + private Class<?>[] exceptionTypes;
1.75 + private int modifiers;
1.76 + // Generics and annotations support
1.77 + private transient String signature;
1.78 + // generic info repository; lazily initialized
1.79 + private transient MethodRepository genericInfo;
1.80 + private byte[] annotations;
1.81 + private byte[] parameterAnnotations;
1.82 + private byte[] annotationDefault;
1.83 + private volatile MethodAccessor methodAccessor;
1.84 + // For sharing of MethodAccessors. This branching structure is
1.85 + // currently only two levels deep (i.e., one root Method and
1.86 + // potentially many Method objects pointing to it.)
1.87 + private Method root;
1.88 +
1.89 + // Generics infrastructure
1.90 +
1.91 + private String getGenericSignature() {return signature;}
1.92 +
1.93 + // Accessor for factory
1.94 + private GenericsFactory getFactory() {
1.95 + // create scope and factory
1.96 + return CoreReflectionFactory.make(this, MethodScope.make(this));
1.97 + }
1.98 +
1.99 + // Accessor for generic info repository
1.100 + private MethodRepository getGenericInfo() {
1.101 + // lazily initialize repository if necessary
1.102 + if (genericInfo == null) {
1.103 + // create and cache generic info repository
1.104 + genericInfo = MethodRepository.make(getGenericSignature(),
1.105 + getFactory());
1.106 + }
1.107 + return genericInfo; //return cached repository
1.108 + }
1.109 +
1.110 + /**
1.111 + * Package-private constructor used by ReflectAccess to enable
1.112 + * instantiation of these objects in Java code from the java.lang
1.113 + * package via sun.reflect.LangReflectAccess.
1.114 + */
1.115 + Method(Class<?> declaringClass,
1.116 + String name,
1.117 + Class<?>[] parameterTypes,
1.118 + Class<?> returnType,
1.119 + Class<?>[] checkedExceptions,
1.120 + int modifiers,
1.121 + int slot,
1.122 + String signature,
1.123 + byte[] annotations,
1.124 + byte[] parameterAnnotations,
1.125 + byte[] annotationDefault)
1.126 + {
1.127 + this.clazz = declaringClass;
1.128 + this.name = name;
1.129 + this.parameterTypes = parameterTypes;
1.130 + this.returnType = returnType;
1.131 + this.exceptionTypes = checkedExceptions;
1.132 + this.modifiers = modifiers;
1.133 + this.slot = slot;
1.134 + this.signature = signature;
1.135 + this.annotations = annotations;
1.136 + this.parameterAnnotations = parameterAnnotations;
1.137 + this.annotationDefault = annotationDefault;
1.138 + }
1.139 +
1.140 + /**
1.141 + * Package-private routine (exposed to java.lang.Class via
1.142 + * ReflectAccess) which returns a copy of this Method. The copy's
1.143 + * "root" field points to this Method.
1.144 + */
1.145 + Method copy() {
1.146 + // This routine enables sharing of MethodAccessor objects
1.147 + // among Method objects which refer to the same underlying
1.148 + // method in the VM. (All of this contortion is only necessary
1.149 + // because of the "accessibility" bit in AccessibleObject,
1.150 + // which implicitly requires that new java.lang.reflect
1.151 + // objects be fabricated for each reflective call on Class
1.152 + // objects.)
1.153 + Method res = new Method(clazz, name, parameterTypes, returnType,
1.154 + exceptionTypes, modifiers, slot, signature,
1.155 + annotations, parameterAnnotations, annotationDefault);
1.156 + res.root = this;
1.157 + // Might as well eagerly propagate this if already present
1.158 + res.methodAccessor = methodAccessor;
1.159 + return res;
1.160 + }
1.161 +
1.162 + /**
1.163 + * Returns the {@code Class} object representing the class or interface
1.164 + * that declares the method represented by this {@code Method} object.
1.165 + */
1.166 + public Class<?> getDeclaringClass() {
1.167 + return clazz;
1.168 + }
1.169 +
1.170 + /**
1.171 + * Returns the name of the method represented by this {@code Method}
1.172 + * object, as a {@code String}.
1.173 + */
1.174 + public String getName() {
1.175 + return name;
1.176 + }
1.177 +
1.178 + /**
1.179 + * Returns the Java language modifiers for the method represented
1.180 + * by this {@code Method} object, as an integer. The {@code Modifier} class should
1.181 + * be used to decode the modifiers.
1.182 + *
1.183 + * @see Modifier
1.184 + */
1.185 + public int getModifiers() {
1.186 + return modifiers;
1.187 + }
1.188 +
1.189 + /**
1.190 + * Returns an array of {@code TypeVariable} objects that represent the
1.191 + * type variables declared by the generic declaration represented by this
1.192 + * {@code GenericDeclaration} object, in declaration order. Returns an
1.193 + * array of length 0 if the underlying generic declaration declares no type
1.194 + * variables.
1.195 + *
1.196 + * @return an array of {@code TypeVariable} objects that represent
1.197 + * the type variables declared by this generic declaration
1.198 + * @throws GenericSignatureFormatError if the generic
1.199 + * signature of this generic declaration does not conform to
1.200 + * the format specified in
1.201 + * <cite>The Java™ Virtual Machine Specification</cite>
1.202 + * @since 1.5
1.203 + */
1.204 + public TypeVariable<Method>[] getTypeParameters() {
1.205 + if (getGenericSignature() != null)
1.206 + return (TypeVariable<Method>[])getGenericInfo().getTypeParameters();
1.207 + else
1.208 + return (TypeVariable<Method>[])new TypeVariable[0];
1.209 + }
1.210 +
1.211 + /**
1.212 + * Returns a {@code Class} object that represents the formal return type
1.213 + * of the method represented by this {@code Method} object.
1.214 + *
1.215 + * @return the return type for the method this object represents
1.216 + */
1.217 + public Class<?> getReturnType() {
1.218 + return returnType;
1.219 + }
1.220 +
1.221 + /**
1.222 + * Returns a {@code Type} object that represents the formal return
1.223 + * type of the method represented by this {@code Method} object.
1.224 + *
1.225 + * <p>If the return type is a parameterized type,
1.226 + * the {@code Type} object returned must accurately reflect
1.227 + * the actual type parameters used in the source code.
1.228 + *
1.229 + * <p>If the return type is a type variable or a parameterized type, it
1.230 + * is created. Otherwise, it is resolved.
1.231 + *
1.232 + * @return a {@code Type} object that represents the formal return
1.233 + * type of the underlying method
1.234 + * @throws GenericSignatureFormatError
1.235 + * if the generic method signature does not conform to the format
1.236 + * specified in
1.237 + * <cite>The Java™ Virtual Machine Specification</cite>
1.238 + * @throws TypeNotPresentException if the underlying method's
1.239 + * return type refers to a non-existent type declaration
1.240 + * @throws MalformedParameterizedTypeException if the
1.241 + * underlying method's return typed refers to a parameterized
1.242 + * type that cannot be instantiated for any reason
1.243 + * @since 1.5
1.244 + */
1.245 + public Type getGenericReturnType() {
1.246 + if (getGenericSignature() != null) {
1.247 + return getGenericInfo().getReturnType();
1.248 + } else { return getReturnType();}
1.249 + }
1.250 +
1.251 +
1.252 + /**
1.253 + * Returns an array of {@code Class} objects that represent the formal
1.254 + * parameter types, in declaration order, of the method
1.255 + * represented by this {@code Method} object. Returns an array of length
1.256 + * 0 if the underlying method takes no parameters.
1.257 + *
1.258 + * @return the parameter types for the method this object
1.259 + * represents
1.260 + */
1.261 + public Class<?>[] getParameterTypes() {
1.262 + return (Class<?>[]) parameterTypes.clone();
1.263 + }
1.264 +
1.265 + /**
1.266 + * Returns an array of {@code Type} objects that represent the formal
1.267 + * parameter types, in declaration order, of the method represented by
1.268 + * this {@code Method} object. Returns an array of length 0 if the
1.269 + * underlying method takes no parameters.
1.270 + *
1.271 + * <p>If a formal parameter type is a parameterized type,
1.272 + * the {@code Type} object returned for it must accurately reflect
1.273 + * the actual type parameters used in the source code.
1.274 + *
1.275 + * <p>If a formal parameter type is a type variable or a parameterized
1.276 + * type, it is created. Otherwise, it is resolved.
1.277 + *
1.278 + * @return an array of Types that represent the formal
1.279 + * parameter types of the underlying method, in declaration order
1.280 + * @throws GenericSignatureFormatError
1.281 + * if the generic method signature does not conform to the format
1.282 + * specified in
1.283 + * <cite>The Java™ Virtual Machine Specification</cite>
1.284 + * @throws TypeNotPresentException if any of the parameter
1.285 + * types of the underlying method refers to a non-existent type
1.286 + * declaration
1.287 + * @throws MalformedParameterizedTypeException if any of
1.288 + * the underlying method's parameter types refer to a parameterized
1.289 + * type that cannot be instantiated for any reason
1.290 + * @since 1.5
1.291 + */
1.292 + public Type[] getGenericParameterTypes() {
1.293 + if (getGenericSignature() != null)
1.294 + return getGenericInfo().getParameterTypes();
1.295 + else
1.296 + return getParameterTypes();
1.297 + }
1.298 +
1.299 +
1.300 + /**
1.301 + * Returns an array of {@code Class} objects that represent
1.302 + * the types of the exceptions declared to be thrown
1.303 + * by the underlying method
1.304 + * represented by this {@code Method} object. Returns an array of length
1.305 + * 0 if the method declares no exceptions in its {@code throws} clause.
1.306 + *
1.307 + * @return the exception types declared as being thrown by the
1.308 + * method this object represents
1.309 + */
1.310 + public Class<?>[] getExceptionTypes() {
1.311 + return (Class<?>[]) exceptionTypes.clone();
1.312 + }
1.313 +
1.314 + /**
1.315 + * Returns an array of {@code Type} objects that represent the
1.316 + * exceptions declared to be thrown by this {@code Method} object.
1.317 + * Returns an array of length 0 if the underlying method declares
1.318 + * no exceptions in its {@code throws} clause.
1.319 + *
1.320 + * <p>If an exception type is a type variable or a parameterized
1.321 + * type, it is created. Otherwise, it is resolved.
1.322 + *
1.323 + * @return an array of Types that represent the exception types
1.324 + * thrown by the underlying method
1.325 + * @throws GenericSignatureFormatError
1.326 + * if the generic method signature does not conform to the format
1.327 + * specified in
1.328 + * <cite>The Java™ Virtual Machine Specification</cite>
1.329 + * @throws TypeNotPresentException if the underlying method's
1.330 + * {@code throws} clause refers to a non-existent type declaration
1.331 + * @throws MalformedParameterizedTypeException if
1.332 + * the underlying method's {@code throws} clause refers to a
1.333 + * parameterized type that cannot be instantiated for any reason
1.334 + * @since 1.5
1.335 + */
1.336 + public Type[] getGenericExceptionTypes() {
1.337 + Type[] result;
1.338 + if (getGenericSignature() != null &&
1.339 + ((result = getGenericInfo().getExceptionTypes()).length > 0))
1.340 + return result;
1.341 + else
1.342 + return getExceptionTypes();
1.343 + }
1.344 +
1.345 + /**
1.346 + * Compares this {@code Method} against the specified object. Returns
1.347 + * true if the objects are the same. Two {@code Methods} are the same if
1.348 + * they were declared by the same class and have the same name
1.349 + * and formal parameter types and return type.
1.350 + */
1.351 + public boolean equals(Object obj) {
1.352 + if (obj != null && obj instanceof Method) {
1.353 + Method other = (Method)obj;
1.354 + if ((getDeclaringClass() == other.getDeclaringClass())
1.355 + && (getName() == other.getName())) {
1.356 + if (!returnType.equals(other.getReturnType()))
1.357 + return false;
1.358 + /* Avoid unnecessary cloning */
1.359 + Class<?>[] params1 = parameterTypes;
1.360 + Class<?>[] params2 = other.parameterTypes;
1.361 + if (params1.length == params2.length) {
1.362 + for (int i = 0; i < params1.length; i++) {
1.363 + if (params1[i] != params2[i])
1.364 + return false;
1.365 + }
1.366 + return true;
1.367 + }
1.368 + }
1.369 + }
1.370 + return false;
1.371 + }
1.372 +
1.373 + /**
1.374 + * Returns a hashcode for this {@code Method}. The hashcode is computed
1.375 + * as the exclusive-or of the hashcodes for the underlying
1.376 + * method's declaring class name and the method's name.
1.377 + */
1.378 + public int hashCode() {
1.379 + return getDeclaringClass().getName().hashCode() ^ getName().hashCode();
1.380 + }
1.381 +
1.382 + /**
1.383 + * Returns a string describing this {@code Method}. The string is
1.384 + * formatted as the method access modifiers, if any, followed by
1.385 + * the method return type, followed by a space, followed by the
1.386 + * class declaring the method, followed by a period, followed by
1.387 + * the method name, followed by a parenthesized, comma-separated
1.388 + * list of the method's formal parameter types. If the method
1.389 + * throws checked exceptions, the parameter list is followed by a
1.390 + * space, followed by the word throws followed by a
1.391 + * comma-separated list of the thrown exception types.
1.392 + * For example:
1.393 + * <pre>
1.394 + * public boolean java.lang.Object.equals(java.lang.Object)
1.395 + * </pre>
1.396 + *
1.397 + * <p>The access modifiers are placed in canonical order as
1.398 + * specified by "The Java Language Specification". This is
1.399 + * {@code public}, {@code protected} or {@code private} first,
1.400 + * and then other modifiers in the following order:
1.401 + * {@code abstract}, {@code static}, {@code final},
1.402 + * {@code synchronized}, {@code native}, {@code strictfp}.
1.403 + */
1.404 + public String toString() {
1.405 + try {
1.406 + StringBuilder sb = new StringBuilder();
1.407 + int mod = getModifiers() & Modifier.methodModifiers();
1.408 + if (mod != 0) {
1.409 + sb.append(Modifier.toString(mod)).append(' ');
1.410 + }
1.411 + sb.append(Field.getTypeName(getReturnType())).append(' ');
1.412 + sb.append(Field.getTypeName(getDeclaringClass())).append('.');
1.413 + sb.append(getName()).append('(');
1.414 + Class<?>[] params = parameterTypes; // avoid clone
1.415 + for (int j = 0; j < params.length; j++) {
1.416 + sb.append(Field.getTypeName(params[j]));
1.417 + if (j < (params.length - 1))
1.418 + sb.append(',');
1.419 + }
1.420 + sb.append(')');
1.421 + Class<?>[] exceptions = exceptionTypes; // avoid clone
1.422 + if (exceptions.length > 0) {
1.423 + sb.append(" throws ");
1.424 + for (int k = 0; k < exceptions.length; k++) {
1.425 + sb.append(exceptions[k].getName());
1.426 + if (k < (exceptions.length - 1))
1.427 + sb.append(',');
1.428 + }
1.429 + }
1.430 + return sb.toString();
1.431 + } catch (Exception e) {
1.432 + return "<" + e + ">";
1.433 + }
1.434 + }
1.435 +
1.436 + /**
1.437 + * Returns a string describing this {@code Method}, including
1.438 + * type parameters. The string is formatted as the method access
1.439 + * modifiers, if any, followed by an angle-bracketed
1.440 + * comma-separated list of the method's type parameters, if any,
1.441 + * followed by the method's generic return type, followed by a
1.442 + * space, followed by the class declaring the method, followed by
1.443 + * a period, followed by the method name, followed by a
1.444 + * parenthesized, comma-separated list of the method's generic
1.445 + * formal parameter types.
1.446 + *
1.447 + * If this method was declared to take a variable number of
1.448 + * arguments, instead of denoting the last parameter as
1.449 + * "<tt><i>Type</i>[]</tt>", it is denoted as
1.450 + * "<tt><i>Type</i>...</tt>".
1.451 + *
1.452 + * A space is used to separate access modifiers from one another
1.453 + * and from the type parameters or return type. If there are no
1.454 + * type parameters, the type parameter list is elided; if the type
1.455 + * parameter list is present, a space separates the list from the
1.456 + * class name. If the method is declared to throw exceptions, the
1.457 + * parameter list is followed by a space, followed by the word
1.458 + * throws followed by a comma-separated list of the generic thrown
1.459 + * exception types. If there are no type parameters, the type
1.460 + * parameter list is elided.
1.461 + *
1.462 + * <p>The access modifiers are placed in canonical order as
1.463 + * specified by "The Java Language Specification". This is
1.464 + * {@code public}, {@code protected} or {@code private} first,
1.465 + * and then other modifiers in the following order:
1.466 + * {@code abstract}, {@code static}, {@code final},
1.467 + * {@code synchronized}, {@code native}, {@code strictfp}.
1.468 + *
1.469 + * @return a string describing this {@code Method},
1.470 + * include type parameters
1.471 + *
1.472 + * @since 1.5
1.473 + */
1.474 + public String toGenericString() {
1.475 + try {
1.476 + StringBuilder sb = new StringBuilder();
1.477 + int mod = getModifiers() & Modifier.methodModifiers();
1.478 + if (mod != 0) {
1.479 + sb.append(Modifier.toString(mod)).append(' ');
1.480 + }
1.481 + TypeVariable<?>[] typeparms = getTypeParameters();
1.482 + if (typeparms.length > 0) {
1.483 + boolean first = true;
1.484 + sb.append('<');
1.485 + for(TypeVariable<?> typeparm: typeparms) {
1.486 + if (!first)
1.487 + sb.append(',');
1.488 + // Class objects can't occur here; no need to test
1.489 + // and call Class.getName().
1.490 + sb.append(typeparm.toString());
1.491 + first = false;
1.492 + }
1.493 + sb.append("> ");
1.494 + }
1.495 +
1.496 + Type genRetType = getGenericReturnType();
1.497 + sb.append( ((genRetType instanceof Class<?>)?
1.498 + Field.getTypeName((Class<?>)genRetType):genRetType.toString()))
1.499 + .append(' ');
1.500 +
1.501 + sb.append(Field.getTypeName(getDeclaringClass())).append('.');
1.502 + sb.append(getName()).append('(');
1.503 + Type[] params = getGenericParameterTypes();
1.504 + for (int j = 0; j < params.length; j++) {
1.505 + String param = (params[j] instanceof Class)?
1.506 + Field.getTypeName((Class)params[j]):
1.507 + (params[j].toString());
1.508 + if (isVarArgs() && (j == params.length - 1)) // replace T[] with T...
1.509 + param = param.replaceFirst("\\[\\]$", "...");
1.510 + sb.append(param);
1.511 + if (j < (params.length - 1))
1.512 + sb.append(',');
1.513 + }
1.514 + sb.append(')');
1.515 + Type[] exceptions = getGenericExceptionTypes();
1.516 + if (exceptions.length > 0) {
1.517 + sb.append(" throws ");
1.518 + for (int k = 0; k < exceptions.length; k++) {
1.519 + sb.append((exceptions[k] instanceof Class)?
1.520 + ((Class)exceptions[k]).getName():
1.521 + exceptions[k].toString());
1.522 + if (k < (exceptions.length - 1))
1.523 + sb.append(',');
1.524 + }
1.525 + }
1.526 + return sb.toString();
1.527 + } catch (Exception e) {
1.528 + return "<" + e + ">";
1.529 + }
1.530 + }
1.531 +
1.532 + /**
1.533 + * Invokes the underlying method represented by this {@code Method}
1.534 + * object, on the specified object with the specified parameters.
1.535 + * Individual parameters are automatically unwrapped to match
1.536 + * primitive formal parameters, and both primitive and reference
1.537 + * parameters are subject to method invocation conversions as
1.538 + * necessary.
1.539 + *
1.540 + * <p>If the underlying method is static, then the specified {@code obj}
1.541 + * argument is ignored. It may be null.
1.542 + *
1.543 + * <p>If the number of formal parameters required by the underlying method is
1.544 + * 0, the supplied {@code args} array may be of length 0 or null.
1.545 + *
1.546 + * <p>If the underlying method is an instance method, it is invoked
1.547 + * using dynamic method lookup as documented in The Java Language
1.548 + * Specification, Second Edition, section 15.12.4.4; in particular,
1.549 + * overriding based on the runtime type of the target object will occur.
1.550 + *
1.551 + * <p>If the underlying method is static, the class that declared
1.552 + * the method is initialized if it has not already been initialized.
1.553 + *
1.554 + * <p>If the method completes normally, the value it returns is
1.555 + * returned to the caller of invoke; if the value has a primitive
1.556 + * type, it is first appropriately wrapped in an object. However,
1.557 + * if the value has the type of an array of a primitive type, the
1.558 + * elements of the array are <i>not</i> wrapped in objects; in
1.559 + * other words, an array of primitive type is returned. If the
1.560 + * underlying method return type is void, the invocation returns
1.561 + * null.
1.562 + *
1.563 + * @param obj the object the underlying method is invoked from
1.564 + * @param args the arguments used for the method call
1.565 + * @return the result of dispatching the method represented by
1.566 + * this object on {@code obj} with parameters
1.567 + * {@code args}
1.568 + *
1.569 + * @exception IllegalAccessException if this {@code Method} object
1.570 + * is enforcing Java language access control and the underlying
1.571 + * method is inaccessible.
1.572 + * @exception IllegalArgumentException if the method is an
1.573 + * instance method and the specified object argument
1.574 + * is not an instance of the class or interface
1.575 + * declaring the underlying method (or of a subclass
1.576 + * or implementor thereof); if the number of actual
1.577 + * and formal parameters differ; if an unwrapping
1.578 + * conversion for primitive arguments fails; or if,
1.579 + * after possible unwrapping, a parameter value
1.580 + * cannot be converted to the corresponding formal
1.581 + * parameter type by a method invocation conversion.
1.582 + * @exception InvocationTargetException if the underlying method
1.583 + * throws an exception.
1.584 + * @exception NullPointerException if the specified object is null
1.585 + * and the method is an instance method.
1.586 + * @exception ExceptionInInitializerError if the initialization
1.587 + * provoked by this method fails.
1.588 + */
1.589 + public Object invoke(Object obj, Object... args)
1.590 + throws IllegalAccessException, IllegalArgumentException,
1.591 + InvocationTargetException
1.592 + {
1.593 + if (!override) {
1.594 + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
1.595 + Class<?> caller = Reflection.getCallerClass(1);
1.596 +
1.597 + checkAccess(caller, clazz, obj, modifiers);
1.598 + }
1.599 + }
1.600 + MethodAccessor ma = methodAccessor; // read volatile
1.601 + if (ma == null) {
1.602 + ma = acquireMethodAccessor();
1.603 + }
1.604 + return ma.invoke(obj, args);
1.605 + }
1.606 +
1.607 + /**
1.608 + * Returns {@code true} if this method is a bridge
1.609 + * method; returns {@code false} otherwise.
1.610 + *
1.611 + * @return true if and only if this method is a bridge
1.612 + * method as defined by the Java Language Specification.
1.613 + * @since 1.5
1.614 + */
1.615 + public boolean isBridge() {
1.616 + return (getModifiers() & Modifier.BRIDGE) != 0;
1.617 + }
1.618 +
1.619 + /**
1.620 + * Returns {@code true} if this method was declared to take
1.621 + * a variable number of arguments; returns {@code false}
1.622 + * otherwise.
1.623 + *
1.624 + * @return {@code true} if an only if this method was declared to
1.625 + * take a variable number of arguments.
1.626 + * @since 1.5
1.627 + */
1.628 + public boolean isVarArgs() {
1.629 + return (getModifiers() & Modifier.VARARGS) != 0;
1.630 + }
1.631 +
1.632 + /**
1.633 + * Returns {@code true} if this method is a synthetic
1.634 + * method; returns {@code false} otherwise.
1.635 + *
1.636 + * @return true if and only if this method is a synthetic
1.637 + * method as defined by the Java Language Specification.
1.638 + * @since 1.5
1.639 + */
1.640 + public boolean isSynthetic() {
1.641 + return Modifier.isSynthetic(getModifiers());
1.642 + }
1.643 +
1.644 + // NOTE that there is no synchronization used here. It is correct
1.645 + // (though not efficient) to generate more than one MethodAccessor
1.646 + // for a given Method. However, avoiding synchronization will
1.647 + // probably make the implementation more scalable.
1.648 + private MethodAccessor acquireMethodAccessor() {
1.649 + // First check to see if one has been created yet, and take it
1.650 + // if so
1.651 + MethodAccessor tmp = null;
1.652 + if (root != null) tmp = root.getMethodAccessor();
1.653 + if (tmp != null) {
1.654 + methodAccessor = tmp;
1.655 + } else {
1.656 + // Otherwise fabricate one and propagate it up to the root
1.657 + tmp = reflectionFactory.newMethodAccessor(this);
1.658 + setMethodAccessor(tmp);
1.659 + }
1.660 +
1.661 + return tmp;
1.662 + }
1.663 +
1.664 + // Returns MethodAccessor for this Method object, not looking up
1.665 + // the chain to the root
1.666 + MethodAccessor getMethodAccessor() {
1.667 + return methodAccessor;
1.668 + }
1.669 +
1.670 + // Sets the MethodAccessor for this Method object and
1.671 + // (recursively) its root
1.672 + void setMethodAccessor(MethodAccessor accessor) {
1.673 + methodAccessor = accessor;
1.674 + // Propagate up
1.675 + if (root != null) {
1.676 + root.setMethodAccessor(accessor);
1.677 + }
1.678 + }
1.679 +
1.680 + /**
1.681 + * @throws NullPointerException {@inheritDoc}
1.682 + * @since 1.5
1.683 + */
1.684 + public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
1.685 + if (annotationClass == null)
1.686 + throw new NullPointerException();
1.687 +
1.688 + return (T) declaredAnnotations().get(annotationClass);
1.689 + }
1.690 +
1.691 + /**
1.692 + * @since 1.5
1.693 + */
1.694 + public Annotation[] getDeclaredAnnotations() {
1.695 + return AnnotationParser.toArray(declaredAnnotations());
1.696 + }
1.697 +
1.698 + private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
1.699 +
1.700 + private synchronized Map<Class<? extends Annotation>, Annotation> declaredAnnotations() {
1.701 + if (declaredAnnotations == null) {
1.702 + declaredAnnotations = AnnotationParser.parseAnnotations(
1.703 + annotations, sun.misc.SharedSecrets.getJavaLangAccess().
1.704 + getConstantPool(getDeclaringClass()),
1.705 + getDeclaringClass());
1.706 + }
1.707 + return declaredAnnotations;
1.708 + }
1.709 +
1.710 + /**
1.711 + * Returns the default value for the annotation member represented by
1.712 + * this {@code Method} instance. If the member is of a primitive type,
1.713 + * an instance of the corresponding wrapper type is returned. Returns
1.714 + * null if no default is associated with the member, or if the method
1.715 + * instance does not represent a declared member of an annotation type.
1.716 + *
1.717 + * @return the default value for the annotation member represented
1.718 + * by this {@code Method} instance.
1.719 + * @throws TypeNotPresentException if the annotation is of type
1.720 + * {@link Class} and no definition can be found for the
1.721 + * default class value.
1.722 + * @since 1.5
1.723 + */
1.724 + public Object getDefaultValue() {
1.725 + if (annotationDefault == null)
1.726 + return null;
1.727 + Class<?> memberType = AnnotationType.invocationHandlerReturnType(
1.728 + getReturnType());
1.729 + Object result = AnnotationParser.parseMemberValue(
1.730 + memberType, ByteBuffer.wrap(annotationDefault),
1.731 + sun.misc.SharedSecrets.getJavaLangAccess().
1.732 + getConstantPool(getDeclaringClass()),
1.733 + getDeclaringClass());
1.734 + if (result instanceof sun.reflect.annotation.ExceptionProxy)
1.735 + throw new AnnotationFormatError("Invalid default: " + this);
1.736 + return result;
1.737 + }
1.738 +
1.739 + /**
1.740 + * Returns an array of arrays that represent the annotations on the formal
1.741 + * parameters, in declaration order, of the method represented by
1.742 + * this {@code Method} object. (Returns an array of length zero if the
1.743 + * underlying method is parameterless. If the method has one or more
1.744 + * parameters, a nested array of length zero is returned for each parameter
1.745 + * with no annotations.) The annotation objects contained in the returned
1.746 + * arrays are serializable. The caller of this method is free to modify
1.747 + * the returned arrays; it will have no effect on the arrays returned to
1.748 + * other callers.
1.749 + *
1.750 + * @return an array of arrays that represent the annotations on the formal
1.751 + * parameters, in declaration order, of the method represented by this
1.752 + * Method object
1.753 + * @since 1.5
1.754 + */
1.755 + public Annotation[][] getParameterAnnotations() {
1.756 + int numParameters = parameterTypes.length;
1.757 + if (parameterAnnotations == null)
1.758 + return new Annotation[numParameters][0];
1.759 +
1.760 + Annotation[][] result = AnnotationParser.parseParameterAnnotations(
1.761 + parameterAnnotations,
1.762 + sun.misc.SharedSecrets.getJavaLangAccess().
1.763 + getConstantPool(getDeclaringClass()),
1.764 + getDeclaringClass());
1.765 + if (result.length != numParameters)
1.766 + throw new java.lang.annotation.AnnotationFormatError(
1.767 + "Parameter annotations don't match number of parameters");
1.768 + return result;
1.769 + }
1.770 +}