diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2008-12-17 18:03:55 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2008-12-17 18:03:55 -0800 |
commit | dd828f42a5c83b4270d4fbf6fce2da1878f1e84a (patch) | |
tree | fdd4b68fa1020f2b6426034c94823419a7236200 /luni-kernel/src | |
parent | fdb2704414a9ed92394ada0d1395e4db86889465 (diff) | |
download | libcore-dd828f42a5c83b4270d4fbf6fce2da1878f1e84a.zip libcore-dd828f42a5c83b4270d4fbf6fce2da1878f1e84a.tar.gz libcore-dd828f42a5c83b4270d4fbf6fce2da1878f1e84a.tar.bz2 |
Code drop from //branches/cupcake/...@124589
Diffstat (limited to 'luni-kernel/src')
27 files changed, 4482 insertions, 2882 deletions
diff --git a/luni-kernel/src/main/java/java/lang/Class.java b/luni-kernel/src/main/java/java/lang/Class.java index e317f80..c65ded9 100644 --- a/luni-kernel/src/main/java/java/lang/Class.java +++ b/luni-kernel/src/main/java/java/lang/Class.java @@ -14,7 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - /* * Copyright (C) 2006-2007 The Android Open Source Project * @@ -30,15 +29,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package java.lang; -// BEGIN android-added import dalvik.system.VMStack; import org.apache.harmony.kernel.vm.StringUtils; import org.apache.harmony.luni.lang.reflect.GenericSignatureParser; import org.apache.harmony.luni.lang.reflect.Types; -// END android-added import java.io.InputStream; import java.io.Serializable; @@ -62,51 +60,65 @@ import java.security.ProtectionDomain; import static java.lang.ClassCache.REFLECT; import static java.lang.ClassCache.compareClassLists; -import static java.lang.ClassCache.getMatchingMethod; +import static java.lang.ClassCache.findMethodByName; +import static java.lang.ClassCache.findFieldByName; /** - * This class must be implemented by the VM vendor. The documented natives must - * be implemented to support other provided class implementations in this - * package. An instance of class Class is the in-image representation of a Java - * class. There are three basic types of Classes - * <dl> - * <dt><em>Classes representing object types (classes or interfaces)</em> - * </dt> - * <dd>These are Classes which represent the class of a simple instance as - * found in the class hierarchy. The name of one of these Classes is simply the - * fully qualified class name of the class or interface that it represents. Its - * <em>signature</em> is the letter "L", followed by its name, followed by a - * semi-colon (";").</dd> - * <dt><em>Classes representing base types</em></dt> - * <dd>These Classes represent the standard Java base types. Although it is not - * possible to create new instances of these Classes, they are still useful for - * providing reflection information, and as the component type of array classes. - * There is one of these Classes for each base type, and their signatures are: + * The in-memory representation of a Java class. This representation serves as + * the starting point for querying class-related information, a process usually + * called "reflection". There are basically three types of {@code Class} + * instances: those representing real classes and interfaces, those representing + * primitive types, and those representing array classes. + * + * <h4>Class instances representing object types (classes or interfaces)</h4> + * <p> + * These represent an ordinary class or interface as found in the class + * hierarchy. The name associated with these {@code Class} instances is simply + * the fully qualified class name of the class or interface that it represents. + * In addition to this human-readable name, each class is also associated by a + * so-called <em>signature</em>, which is the letter "L", followed by the + * class name and a semicolon (";"). The signature is what the runtime system + * uses internally for identifying the class (for example in a DEX file). + * </p> + * <h4>Classes representing primitive types</h4> + * <p> + * These represent the standard Java primitive types and hence share their + * names (for example "int" for the {@code int} primitive type). Although it is + * not possible to create new instances based on these {@code Class} instances, + * they are still useful for providing reflection information, and as the + * component type of array classes. There is one {@code Class} instance for each + * primitive type, and their signatures are: + * </p> * <ul> - * <li><code>B</code> representing the <code>byte</code> base type</li> - * <li><code>S</code> representing the <code>short</code> base type</li> - * <li><code>I</code> representing the <code>int</code> base type</li> - * <li><code>J</code> representing the <code>long</code> base type</li> - * <li><code>F</code> representing the <code>float</code> base type</li> - * <li><code>D</code> representing the <code>double</code> base type</li> - * <li><code>C</code> representing the <code>char</code> base type</li> - * <li><code>Z</code> representing the <code>boolean</code> base type</li> - * <li><code>V</code> representing void function return values</li> + * <li>{@code B} representing the {@code byte} primitive type</li> + * <li>{@code S} representing the {@code short} primitive type</li> + * <li>{@code I} representing the {@code int} primitive type</li> + * <li>{@code J} representing the {@code long} primitive type</li> + * <li>{@code F} representing the {@code float} primitive type</li> + * <li>{@code D} representing the {@code double} primitive type</li> + * <li>{@code C} representing the {@code char} primitive type</li> + * <li>{@code Z} representing the {@code boolean} primitive type</li> + * <li>{@code V} representing void function return values</li> + * </ul> + * <p> + * <h4>Classes representing array classes</h4> + * <p> + * These represent the classes of Java arrays. There is one such {@code Class} + * instance per combination of array leaf component type and arity (number of + * dimensions). In this case, the name associated with the {@code Class} + * consists of one or more left square brackets (one per dimension in the array) + * followed by the signature of the class representing the leaf component type, + * which can be either an object type or a primitive type. The signature of a + * {@code Class} representing an array type is the same as its name. Examples + * of array class signatures are: + * </p> + * <ul> + * <li>{@code [I} representing the {@code int[]} type</li> + * <li>{@code [Ljava/lang/String;} representing the {@code String[]} type</li> + * <li>{@code [[[C} representing the {@code char[][][]} type (three dimensions!)</li> * </ul> - * The name of a Class representing a base type is the keyword which is used to - * represent the type in Java source code (i.e. "int" for the <code>int</code> - * base type.</dd> - * <dt><em>Classes representing array classes</em></dt> - * <dd>These are Classes which represent the classes of Java arrays. There is - * one such Class for all array instances of a given arity (number of - * dimensions) and leaf component type. In this case, the name of the class is - * one or more left square brackets (one per dimension in the array) followed by - * the signature of the class representing the leaf component type, which can - * be either an object type or a base type. The signature of a Class - * representing an array type is the same as its name.</dd> - * </dl> * - * @since 1.0 + * @since Android 1.0 */ public final class Class<T> implements Serializable, AnnotatedElement, GenericDeclaration, Type { @@ -145,33 +157,60 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe native private Object[] getSignatureAnnotation(); /** - * Returns a Class object which represents the class named by the argument. - * The name should be the name of a class as described in the class - * definition of {@link Class}, however Classes representing base types can - * not be found using this method. - * - * @param className The name of the non-base type class to find - * @return the named Class - * @throws ClassNotFoundException If the class could not be found - * @see Class + * Returns a {@code Class} object which represents the class with the + * specified name. The name should be the name of a class as described in + * the {@link Class class definition}; however, {@code Class}es representing + * primitive types can not be found using this method. + * <p> + * If the class has not been loaded so far, it is being loaded and linked + * first. This is done through either the class loader of the calling class + * or one of its parent class loaders. The class is also being initialized, + * which means that a possible static initializer block is executed. + * + * @param className + * the name of the non-primitive-type class to find. + * @return the named {@code Class} instance. + * @throws ClassNotFoundException + * if the requested class can not be found. + * @throws LinkageError + * if an error occurs during linkage + * @throws ExceptionInInitializerError + * if an exception occurs during static initialization of a + * class. + * @since Android 1.0 */ public static Class<?> forName(String className) throws ClassNotFoundException { return forName(className, true, VMStack.getCallingClassLoader()); } /** - * Returns a Class object which represents the class named by the argument. - * The name should be the name of a class as described in the class - * definition of {@link Class}, however Classes representing base types can - * not be found using this method. Security rules will be obeyed. - * - * @param className The name of the non-base type class to find - * @param initializeBoolean A boolean indicating whether the class should be - * initialized - * @param classLoader The class loader to use to load the class - * @return the named class. - * @throws ClassNotFoundException If the class could not be found - * @see Class + * Returns a {@code Class} object which represents the class with the + * specified name. The name should be the name of a class as described in + * the {@link Class class definition}, however {@code Class}es representing + * primitive types can not be found using this method. Security rules will + * be obeyed. + * <p> + * If the class has not been loaded so far, it is being loaded and linked + * first. This is done through either the specified class loader or one of + * its parent class loaders. The caller can also request the class to be + * initialized, which means that a possible static initializer block is + * executed. + * + * @param className + * the name of the non-primitive-type class to find. + * @param initializeBoolean + * indicates whether the class should be initialized. + * @param classLoader + * the class loader to use to load the class. + * @return the named {@code Class} instance. + * @throws ClassNotFoundException + * if the requested class can not be found. + * @throws LinkageError + * if an error occurs during linkage + * @throws ExceptionInInitializerError + * if an exception occurs during static initialization of a + * class. + * @since Android 1.0 */ public static Class<?> forName(String className, boolean initializeBoolean, ClassLoader classLoader) throws ClassNotFoundException { @@ -187,14 +226,30 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe classLoader = ClassLoader.getSystemClassLoader(); } - - return classForName(className, initializeBoolean, classLoader); + // Catch an Exception thrown by the underlying native code. It wraps + // up everything inside a ClassNotFoundException, even if e.g. an + // Error occurred during initialization. This as a workaround for + // an ExceptionInInitilaizerError that's also wrapped. It is actually + // expected to be thrown. Maybe the same goes for other errors. + // Not wrapping up all the errors will break android though. + Class<?> result; + try { + result = classForName(className, initializeBoolean, + classLoader); + } catch (ClassNotFoundException e) { + Throwable cause = e.getCause(); + if (cause instanceof ExceptionInInitializerError) { + throw (ExceptionInInitializerError) cause; + } + throw e; + } + return result; } /* * Returns a class by name without any security checks. * - * @param className The name of the non-base type class to find + * @param className The name of the non-primitive type class to find * @param initializeBoolean A boolean indicating whether the class should be * initialized * @param classLoader The class loader to use to load the class @@ -205,25 +260,36 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe ClassLoader classLoader) throws ClassNotFoundException; /** - * Returns an array containing all public class members of the class which - * the receiver represents and its super classes and interfaces - * - * @return the class' public class members - * @throws SecurityException If member access is not allowed - * @see Class - */ - public Class<?>[] getClasses() { + * Returns an array containing {@code Class} objects for all public classes + * and interfaces that are members of this class. This includes public + * members inherited from super classes and interfaces. If there are no such + * class members or if this object represents a primitive type then an array + * of length 0 is returned. + * + * @return the public class members of the class represented by this object. + * @throws SecurityException + * if a security manager exists and it does not allow member + * access. + * @since Android 1.0 + */ + public Class[] getClasses() { + // BEGIN android-note + // trying to get closer to the RI which returns a raw class array. + // copied from newer version of harmony + // END android-note checkPublicMemberAccess(); return getFullListOfClasses(true); } /** - * Returns the annotation of the given type. If there is no annotation the - * method returns <code>null</code>. + * Returns the annotation of the given type. If there is no such annotation + * then the method returns {@code null}. * - * @param annotationClass the annotation type. - * @return the annotation of the given type, or <code>null</code> if none. - * @since 1.5 + * @param annotationClass + * the annotation type. + * @return the annotation of the given type, or {@code null} if there is no + * such annotation. + * @since Android 1.0 */ @SuppressWarnings("unchecked") public <A extends Annotation> A getAnnotation(Class<A> annotationClass) { @@ -238,10 +304,12 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe } /** - * Returns all the annotations of the receiver. If there are no annotations - * then returns an empty array. + * Returns all the annotations of this class. If there are no annotations + * then an empty array is returned. * - * @return a copy of the array containing the receiver's annotations. + * @return a copy of the array containing this class' annotations. + * @see #getDeclaredAnnotations() + * @since Android 1.0 */ public Annotation[] getAnnotations() { /* @@ -279,11 +347,13 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe } /** - * Returns the canonical name of the receiver. If the receiver does not have - * a canonical name, as defined in the Java Language Specification, then the - * method returns <code>null</code>. + * Returns the canonical name of this class. If this class does not have a + * canonical name as defined in the Java Language Specification, then the + * method returns {@code null}. * - * @return the receiver canonical name, or <code>null</code>. + * @return this class' canonical name, or {@code null} if it does not have a + * canonical name. + * @since Android 1.0 */ public String getCanonicalName() { if (isLocalClass() || isAnonymousClass()) @@ -312,8 +382,6 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * The canonical name of a top-level class or primitive type is * equal to the fully qualified name. */ - - // TODO Check if this works for the primitive types. return getName(); } @@ -325,24 +393,33 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe /** * Returns the class loader which was used to load the class represented by - * the receiver. Returns null if the class was loaded by the bootstrap class - * loader - * - * @return the receiver's class loader or nil + * this {@code Class}. Implementations are free to return {@code null} for + * classes that were loaded by the bootstrap class loader. The Android + * reference implementation, though, returns a reference to an actual + * representation of the bootstrap class loader. + * + * @return the class loader for the represented class. + * @throws SecurityException + * if a security manager exists and it does not allow accessing + * the class loader. * @see ClassLoader + * @since Android 1.0 */ public ClassLoader getClassLoader() { SecurityManager smgr = System.getSecurityManager(); - if (smgr != null) { + ClassLoader loader = getClassLoaderImpl(); + if (smgr != null && loader != null) { ClassLoader calling = VMStack.getCallingClassLoader(); - ClassLoader current = getClassLoaderImpl(); - if (calling != null && !calling.getClass().isInstance(current)) { + if (calling != null && !calling.isAncestorOf(loader)) { smgr.checkPermission(new RuntimePermission("getClassLoader")); } } - ClassLoader loader = getClassLoaderImpl(); + if (this.isPrimitive()) { + return null; + } + if (loader == null) { loader = BootClassLoader.getInstance(); } @@ -375,24 +452,30 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe private static native ClassLoader getClassLoader(Class<?> clazz); /** - * Returns a Class object which represents the receiver's component type if - * the receiver represents an array type. Otherwise returns nil. The - * component type of an array type is the type of the elements of the array. + * Returns a {@code Class} object which represents the component type if + * this class represents an array type. Returns {@code null} if this class + * does not represent an array type. The component type of an array type is + * the type of the elements of the array. * - * @return the component type of the receiver. - * @see Class + * @return the component type of this class. + * @since Android 1.0 */ public native Class<?> getComponentType(); /** - * Returns a public Constructor object which represents the constructor - * described by the arguments. + * Returns a {@code Constructor} object which represents the public + * constructor matching the specified parameter types. * - * @param parameterTypes the types of the arguments. - * @return the constructor described by the arguments. - * @throws NoSuchMethodException if the constructor could not be found. - * @throws SecurityException if member access is not allowed - * @see #getConstructors + * @param parameterTypes + * the parameter types of the requested constructor. + * @return the constructor described by {@code parameterTypes}. + * @throws NoSuchMethodException + * if the constructor can not be found. + * @throws SecurityException + * if a security manager exists and it does not allow member + * access. + * @see #getDeclaredConstructor(Class...) + * @since Android 1.0 */ @SuppressWarnings("unchecked") public Constructor<T> getConstructor(Class... parameterTypes) throws NoSuchMethodException, @@ -402,39 +485,60 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe } /** - * Returns an array containing Constructor objects describing all - * constructors which are visible from the current execution context. - * - * @return all visible constructors starting from the receiver. - * @throws SecurityException if member access is not allowed - * @see #getMethods - */ - public Constructor<T>[] getConstructors() throws SecurityException { + * Returns an array containing {@code Constructor} objects for all public + * constructors for the class represented by this {@code Class}. If there + * are no public constructors or if this {@code Class} represents an array + * class, a primitive type or void then an empty array is returned. + * + * @return an array with the public constructors of the class represented by + * this {@code Class}. + * @throws SecurityException + * if a security manager exists and it does not allow member + * access. + * @see #getDeclaredConstructors() + * @since Android 1.0 + */ + public Constructor[] getConstructors() throws SecurityException { + // BEGIN android-note + // trying to get closer to the RI which returns a raw constructor array. + // copied from newer version of harmony + // END android-note checkPublicMemberAccess(); return getDeclaredConstructors(this, true); } /** - * Returns the annotations that are directly defined on this type. - * Annotations that are inherited are not included in the result. If there - * are no annotations, returns an empty array. + * Returns the annotations that are directly defined on the class + * represented by this {@code Class}. Annotations that are inherited are not + * included in the result. If there are no annotations at all, an empty + * array is returned. * - * @return a copy of the array containing the receiver's defined - * annotations. - * @since 1.5 + * @return a copy of the array containing the annotations defined for the + * class that this {@code Class} represents. + * @see #getAnnotations() + * @since Android 1.0 */ native public Annotation[] getDeclaredAnnotations(); /** - * Returns an array containing all class members of the class which the - * receiver represents. Note that some of the fields which are returned may - * not be visible in the current execution context. - * - * @return the class' class members - * @throws SecurityException if member access is not allowed - * @see Class - */ - public Class<?>[] getDeclaredClasses() throws SecurityException { + * Returns an array containing {@code Class} objects for all classes and + * interfaces that are declared as members of the class which this {@code + * Class} represents. If there are no classes or interfaces declared or if + * this class represents an array class, a primitive type or void, then an + * empty array is returned. + * + * @return an array with {@code Class} objects for all the classes and + * interfaces that are used in member declarations. + * @throws SecurityException + * if a security manager exists and it does not allow member + * access. + * @since Android 1.0 + */ + public Class[] getDeclaredClasses() throws SecurityException { + // BEGIN android-note + // trying to get closer to the RI which returns a raw class array. + // copied from newer version of harmony + // END android-note checkDeclaredMemberAccess(); return getDeclaredClasses(this, false); } @@ -476,14 +580,20 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe boolean publicOnly); /** - * Returns a Constructor object which represents the constructor described - * by the arguments. - * - * @param parameterTypes the types of the arguments. - * @return the constructor described by the arguments. - * @throws NoSuchMethodException if the constructor could not be found. - * @throws SecurityException if member access is not allowed - * @see #getConstructors + * Returns a {@code Constructor} object which represents the constructor + * matching the specified parameter types that is declared by the class + * represented by this {@code Class}. + * + * @param parameterTypes + * the parameter types of the requested constructor. + * @return the constructor described by {@code parameterTypes}. + * @throws NoSuchMethodException + * if the requested constructor can not be found. + * @throws SecurityException + * if a security manager exists and it does not allow member + * access. + * @see #getConstructor(Class...) + * @since Android 1.0 */ @SuppressWarnings("unchecked") public Constructor<T> getDeclaredConstructor(Class... parameterTypes) @@ -493,16 +603,25 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe } /** - * Returns an array containing Constructor objects describing all - * constructor which are defined by the receiver. Note that some of the - * fields which are returned may not be visible in the current execution - * context. + * Returns an array containing {@code Constructor} objects for all + * constructors declared in the class represented by this {@code Class}. If + * there are no constructors or if this {@code Class} represents an array + * class, a primitive type or void then an empty array is returned. + * + * @return an array with the constructors declared in the class represented + * by this {@code Class}. * - * @return the receiver's constructors. - * @throws SecurityException if member access is not allowed - * @see #getMethods + * @throws SecurityException + * if a security manager exists and it does not allow member + * access. + * @see #getConstructors() + * @since Android 1.0 */ - public Constructor<T>[] getDeclaredConstructors() throws SecurityException { + public Constructor[] getDeclaredConstructors() throws SecurityException { + // BEGIN android-note + // trying to get closer to the RI which returns a raw constructor array. + // copied from newer version of harmony + // END android-note checkDeclaredMemberAccess(); return getDeclaredConstructors(this, false); } @@ -538,58 +657,54 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe } /** - * Returns a Field object describing the field in the receiver named by the - * argument. Note that the Constructor may not be visible from the current - * execution context. - * - * @param name The name of the field to look for. - * @return the field in the receiver named by the argument. - * @throws NoSuchFieldException if the requested field could not be found - * @throws SecurityException if member access is not allowed - * @see #getDeclaredFields() - */ - public Field getDeclaredField(String name) throws NoSuchFieldException, SecurityException { + * Returns a {@code Field} object for the field with the specified name + * which is declared in the class represented by this {@code Class}. + * + * @param name + * the name of the requested field. + * @return the requested field in the class represented by this class. + * @throws NoSuchFieldException + * if the requested field can not be found. + * @throws SecurityException + * if a security manager exists and it does not allow member + * access. + * @see #getField(String) + * @since Android 1.0 + */ + public Field getDeclaredField(String name) + throws NoSuchFieldException, SecurityException { checkDeclaredMemberAccess(); - return getMatchingField(getDeclaredFields(this, false), name); + + Field[] fields = getClassCache().getDeclaredFields(); + Field field = findFieldByName(fields, name); + + /* + * Make a copy of the private (to the package) object, so that + * setAccessible() won't alter the private instance. + */ + return REFLECT.clone(field); } /** - * Returns an array containing Field objects describing all fields which are - * defined by the receiver. Note that some of the fields which are returned - * may not be visible in the current execution context. + * Returns an array containing {@code Field} objects for all fields declared + * in the class represented by this {@code Class}. If there are no fields or + * if this {@code Class} represents an array class, a primitive type or void + * then an empty array is returned. * - * @return the receiver's fields. - * @throws SecurityException If member access is not allowed - * @see #getFields + * @return an array with the fields declared in the class represented by + * this class. + * @throws SecurityException + * if a security manager exists and it does not allow member + * access. + * @see #getFields() + * @since Android 1.0 */ public Field[] getDeclaredFields() throws SecurityException { checkDeclaredMemberAccess(); - return getDeclaredFields(this, false); - } - /* - * Returns the list of fields without performing any security checks - * first. This includes the fields inherited from superclasses. If no - * fields exist at all, an empty array is returned. - * - * @param publicOnly reflects whether we want only public fields or all of them - * @return the list of fields - */ - private Field[] getFullListOfFields(boolean publicOnly) { - Field[] result = getDeclaredFields(this, publicOnly); - - // Traverse all superclasses - Class<?> clazz = this.getSuperclass(); - while (clazz != null) { - Field[] temp = getDeclaredFields(clazz, publicOnly); - if (temp.length != 0) { - result = arraycopy(new Field[result.length + temp.length], result, temp); - } - - clazz = clazz.getSuperclass(); - } - - return result; + // Return a copy of the private (to the package) array. + Field[] fields = getClassCache().getDeclaredFields(); + return ClassCache.deepCopy(fields); } /* @@ -601,46 +716,33 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * @return the list of fields */ static native Field[] getDeclaredFields(Class<?> clazz, boolean publicOnly); - - /* - * Finds a field with a given name in a list of fields. - * - * @param fields the list of fields to search through - * @name the name of the field - * @return the field - * @throws NoSuchFieldException if the field does not exist. - */ - private static Field getMatchingField(Field[] fields, String name) - throws NoSuchFieldException { - for (int i = 0; i < fields.length; i++) { - if (fields[i].getName().equals(name)) - return fields[i]; - } - - throw new NoSuchFieldException(name); - } - // BEGIN android-changed - // Changed to raw type to be closer to the RI /** - * Returns a Method object which represents the method described by the - * arguments. Note that the associated method may not be visible from the - * current execution context. - * - * @param name the name of the method - * @param parameterTypes the types of the arguments. - * @return the method described by the arguments. - * @throws NoSuchMethodException if the method could not be found. - * @throws SecurityException If member access is not allowed - * @throws NullPointerException if the name parameter is <code>null</code>. - * @see #getMethods + * Returns a {@code Method} object which represents the method matching the + * specified name and parameter types that is declared by the class + * represented by this {@code Class}. + * + * @param name + * the requested method's name. + * @param parameterTypes + * the parameter types of the requested method. + * @return the method described by {@code name} and {@code parameterTypes}. + * @throws NoSuchMethodException + * if the requested constructor can not be found. + * @throws NullPointerException + * if {@code name} is {@code null}. + * @throws SecurityException + * if a security manager exists and it does not allow member + * access. + * @see #getMethod(String, Class...) + * @since Android 1.0 */ public Method getDeclaredMethod(String name, Class... parameterTypes) throws NoSuchMethodException, SecurityException { checkDeclaredMemberAccess(); Method[] methods = getClassCache().getDeclaredMethods(); - Method method = getMatchingMethod(methods, name, parameterTypes); + Method method = findMethodByName(methods, name, parameterTypes); /* * Make a copy of the private (to the package) object, so that @@ -648,16 +750,20 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe */ return REFLECT.clone(method); } - // END android-changed /** - * Returns an array containing Method objects describing all methods which - * are defined by the receiver. Note that some of the methods which are - * returned may not be visible in the current execution context. + * Returns an array containing {@code Method} objects for all methods + * declared in the class represented by this {@code Class}. If there are no + * methods or if this {@code Class} represents an array class, a primitive + * type or void then an empty array is returned. * - * @return the receiver's methods. - * @throws SecurityException if member access is not allowed - * @see #getMethods + * @return an array with the methods declared in the class represented by + * this {@code Class}. + * @throws SecurityException + * if a security manager exists and it does not allow member + * access. + * @see #getMethods() + * @since Android 1.0 */ public Method[] getDeclaredMethods() throws SecurityException { checkDeclaredMemberAccess(); @@ -698,48 +804,49 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe } /** - * Returns the class which declared the class represented by the receiver. - * This will return null if the receiver is a member of another class. + * Returns the declaring {@code Class} of this {@code Class}. Returns + * {@code null} if the class is not a member of another class or if this + * {@code Class} represents an array class, a primitive type or void. * - * @return the declaring class of the receiver. + * @return the declaring {@code Class} or {@code null}. + * @since Android 1.0 */ native public Class<?> getDeclaringClass(); /** - * Returns the class that directly encloses the receiver. If there is no - * enclosing class the method returns <code>null</code>. + * Returns the enclosing {@code Class} of this {@code Class}. If there is no + * enclosing class the method returns {@code null}. * - * @return the enclosing class or <code>null</code>. + * @return the enclosing {@code Class} or {@code null}. + * @since Android 1.0 */ native public Class<?> getEnclosingClass(); /** - * Gets the {@link Constructor}, which encloses the declaration of this - * class, if it is an anonymous or local/automatic class, otherwise - * <code>null</code>. + * Gets the enclosing {@code Constructor} of this {@code Class}, if it is an + * anonymous or local/automatic class; otherwise {@code null}. * - * @return A {@link Constructor} instance or <code>null</code>. - * @since 1.5 + * @return the enclosing {@code Constructor} instance or {@code null}. + * @since Android 1.0 */ native public Constructor<?> getEnclosingConstructor(); /** - * Gets the {@link Method}, which encloses the declaration of this class, - * if it is an anonymous or local/automatic class, otherwise - * <code>null</code>. + * Gets the enclosing {@code Method} of this {@code Class}, if it is an + * anonymous or local/automatic class; otherwise {@code null}. * - * @return A {@link Method} instance or <code>null</code>. - * @since 1.5 + * @return the enclosing {@code Method} instance or {@code null}. + * @since Android 1.0 */ native public Method getEnclosingMethod(); /** - * Gets the <code>enum</code> constants/fields associated with this class - * if it is an {@linkplain #isEnum() enum}, otherwise <code>null</code>. + * Gets the {@code enum} constants associated with this {@code Class}. + * Returns {@code null} if this {@code Class} does not represent an {@code + * enum} type. * - * @return An array of the <code>enum</code> constants for this class or - * <code>null</code>. - * @since 1.5 + * @return an array with the {@code enum} constants or {@code null}. + * @since Android 1.0 */ @SuppressWarnings("unchecked") public T[] getEnumConstants() { @@ -755,91 +862,133 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe } /** - * Returns a Field object describing the field in the receiver named by the - * argument which must be visible from the current execution context. - * - * @param name The name of the field to look for. - * @return the field in the receiver named by the argument. - * @throws NoSuchFieldException If the given field does not exist - * @throws SecurityException If access is denied - * @see #getDeclaredFields() + * Returns a {@code Field} object which represents the public field with the + * specified name. This method first searches the class C represented by + * this {@code Class}, then the interfaces implemented by C and finally the + * superclasses of C. + * + * @param name + * the name of the requested field. + * @return the public field specified by {@code name}. + * @throws NoSuchFieldException + * if the field can not be found. + * @throws SecurityException + * if a security manager exists and it does not allow member + * access. + * @see #getDeclaredField(String) + * @since Android 1.0 */ public Field getField(String name) throws NoSuchFieldException, SecurityException { checkPublicMemberAccess(); - return getMatchingField(getFullListOfFields(true), name); + + Field[] fields = getClassCache().getAllPublicFields(); + Field field = findFieldByName(fields, name); + + /* + * Make a copy of the private (to the package) object, so that + * setAccessible() won't alter the private instance. + */ + return REFLECT.clone(field); } /** - * Returns an array containing Field objects describing all fields which are - * visible from the current execution context. - * - * @return all visible fields starting from the receiver. - * @throws SecurityException If member access is not allowed + * Returns an array containing {@code Field} objects for all public fields + * for the class C represented by this {@code Class}. Fields may be declared + * in C, the interfaces it implements or in the superclasses of C. The + * elements in the returned array are in no particular order. + * <p> + * If there are no public fields or if this class represents an array class, + * a primitive type or {@code void} then an empty array is returned. + * </p> + * + * @return an array with the public fields of the class represented by this + * {@code Class}. + * @throws SecurityException + * if a security manager exists and it does not allow member + * access. * @see #getDeclaredFields() + * @since Android 1.0 */ public Field[] getFields() throws SecurityException { checkPublicMemberAccess(); - return getFullListOfFields(true); + + // Return a copy of the private (to the package) array. + Field[] fields = getClassCache().getAllPublicFields(); + return ClassCache.deepCopy(fields); } /** - * Gets the {@link Type types} of the interface that this class directly - * implements. + * Gets the {@link Type}s of the interfaces that this {@code Class} directly + * implements. If the {@code Class} represents a primitive type or {@code + * void} then an empty array is returned. * - * @return An array of {@link Type} instances. - * @since 1.5 + * @return an array of {@link Type} instances directly implemented by the + * class represented by this {@code class}. + * @since Android 1.0 */ public Type[] getGenericInterfaces() { - // BEGIN android-changed GenericSignatureParser parser = new GenericSignatureParser(); parser.parseForClass(this, getSignatureAttribute()); return Types.getClonedTypeArray(parser.interfaceTypes); - // END android-changed } /** - * Gets the {@link Type} that represents the super class of this class. + * Gets the {@code Type} that represents the superclass of this {@code + * class}. * - * @return An instance of {@link Type} - * @since 1.5 + * @return an instance of {@code Type} representing the superclass. + * @since Android 1.0 */ public Type getGenericSuperclass() { - // BEGIN android-changed GenericSignatureParser parser = new GenericSignatureParser(); parser.parseForClass(this, getSignatureAttribute()); return Types.getType(parser.superclassType); - // END android-changed } /** - * Returns an array of Class objects which match the interfaces specified in - * the receiver classes <code>implements</code> declaration. The order of - * entries equals the order in the original class declaration. If the - * class doesn't implement any interfaces, an empty array is returned. + * Returns an array of {@code Class} objects that match the interfaces + * specified in the {@code implements} declaration of the class represented + * by this {@code Class}. The order of the elements in the array is + * identical to the order in the original class declaration. If the class + * does not implement any interfaces, an empty array is returned. * - * @return Class[] the interfaces the receiver claims to implement. + * @return an array with the interfaces of the class represented by this + * class. + * @since Android 1.0 */ - public native Class<?>[] getInterfaces(); + public native Class[] getInterfaces(); + // BEGIN android-note + // trying to get closer to the RI which returns a raw class array. + // copied from newer version of harmony + // END android-note - // BEGIN android-changed // Changed to raw type to be closer to the RI /** - * Returns a Method object which represents the method described by the - * arguments. - * - * @param name String the name of the method - * @param parameterTypes Class[] the types of the arguments. - * @return Method the method described by the arguments. - * @throws NoSuchMethodException if the method could not be found. - * @throws SecurityException if member access is not allowed - * @see #getMethods + * Returns a {@code Method} object which represents the public method with + * the specified name and parameter types. This method first searches the + * class C represented by this {@code Class}, then the superclasses of C and + * finally the interfaces implemented by C and finally the superclasses of C + * for a method with matching name. + * + * @param name + * the requested method's name. + * @param parameterTypes + * the parameter types of the requested method. + * @return the public field specified by {@code name}. + * @throws NoSuchMethodException + * if the method can not be found. + * @throws SecurityException + * if a security manager exists and it does not allow member + * access. + * @see #getDeclaredMethod(String, Class...) + * @since Android 1.0 */ public Method getMethod(String name, Class... parameterTypes) throws NoSuchMethodException, SecurityException { checkPublicMemberAccess(); Method[] methods = getClassCache().getAllPublicMethods(); - Method method = getMatchingMethod(methods, name, parameterTypes); + Method method = findMethodByName(methods, name, parameterTypes); /* * Make a copy of the private (to the package) object, so that @@ -847,15 +996,24 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe */ return REFLECT.clone(method); } - // END android-changed /** - * Returns an array containing Method objects describing all methods which - * are visible from the current execution context. - * - * @return Method[] all visible methods starting from the receiver. - * @throws SecurityException if member access is not allowed + * Returns an array containing {@code Method} objects for all public methods + * for the class C represented by this {@code Class}. Methods may be + * declared in C, the interfaces it implements or in the superclasses of C. + * The elements in the returned array are in no particular order. + * <p> + * If there are no public methods or if this {@code Class} represents a + * primitive type or {@code void} then an empty array is returned. + * </p> + * + * @return an array with the methods of the class represented by this + * {@code Class}. + * @throws SecurityException + * if a security manager exists and it does not allow member + * access. * @see #getDeclaredMethods() + * @since Android 1.0 */ public Method[] getMethods() throws SecurityException { checkPublicMemberAccess(); @@ -867,9 +1025,9 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe /** * Performs the security checks regarding the access of a public - * member of this class. + * member of this {@code Class}. * - * <p><b>Note:</b> Because of the <code>getCallingClassLoader2()</code> + * <p><b>Note:</b> Because of the {@code getCallingClassLoader2()} * check, this method must be called exactly one level deep into a * public method on this instance.</p> */ @@ -882,7 +1040,7 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe ClassLoader calling = VMStack.getCallingClassLoader2(); ClassLoader current = getClassLoader(); - if (calling != null && !calling.getClass().isInstance(current)) { + if (calling != null && !calling.isAncestorOf(current)) { smgr.checkPackageAccess(this.getPackage().getName()); } } @@ -890,9 +1048,9 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe /** * Performs the security checks regarding the access of a declared - * member of this class. + * member of this {@code Class}. * - * <p><b>Note:</b> Because of the <code>getCallingClassLoader2()</code> + * <p><b>Note:</b> Because of the {@code getCallingClassLoader2()} * check, this method must be called exactly one level deep into a * public method on this instance.</p> */ @@ -904,18 +1062,19 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe ClassLoader calling = VMStack.getCallingClassLoader2(); ClassLoader current = getClassLoader(); - if (calling != null && !calling.getClass().isInstance(current)) { + if (calling != null && !calling.isAncestorOf(current)) { smgr.checkPackageAccess(this.getPackage().getName()); } } } /** - * Returns an integer which which is the receiver's modifiers. Note that the - * constants which describe the bits which are returned are implemented in - * class {@link Modifier} which may not be available on the target. + * Returns an integer that represents the modifiers of the class represented + * by this {@code Class}. The returned value is a combination of bits + * defined by constants in the {@link Modifier} class. * - * @return the receiver's modifiers + * @return the modifiers of the class represented by this {@code Class}. + * @since Android 1.0 */ public int getModifiers() { return getModifiers(this, false); @@ -931,22 +1090,24 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe private static native int getModifiers(Class<?> clazz, boolean ignoreInnerClassesAttrib); /** - * Returns the name of the class which the receiver represents. For a + * Returns the name of the class represented by this {@code Class}. For a * description of the format which is used, see the class definition of * {@link Class}. * - * @return the receiver's name. - * @see Class + * @return the name of the class represented by this {@code Class}. + * @since Android 1.0 */ public native String getName(); /** - * Returns the simple name of the receiver as defined in the source code. If - * there is no name (the class is anonymous) returns an empty string, and if - * the receiver is an array returns the name of the underlying type with - * square braces appended (e.g. <code>"Integer[]"</code>). + * Returns the simple name of the class represented by this {@code Class} as + * defined in the source code. If there is no name (that is, the class is + * anonymous) then an empty string is returned. If the receiver is an array + * then the name of the underlying type with square braces appended (for + * example {@code "Integer[]"}) is returned. * - * @return the simple name of the receiver. + * @return the simple name of the class represented by this {@code Class}. + * @since Android 1.0 */ public String getSimpleName() { if (isArray()) { @@ -979,39 +1140,43 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe private native String getInnerClassName(); /** - * Returns the ProtectionDomain of the receiver. + * Returns the {@code ProtectionDomain} of the class represented by this + * class. * <p> - * Note: In order to conserve space in embedded targets, we allow this - * method to answer null for classes in the system protection domain (i.e. - * for system classes). System classes are always given full permissions - * (i.e. AllPermission). This is not changeable via the - * java.security.Policy. - * - * @return ProtectionDomain the receiver's ProtectionDomain. - * @see Class + * Note: In order to conserve space in an embedded target like Android, we + * allow this method to return {@code null} for classes in the system + * protection domain (that is, for system classes). System classes are + * always given full permissions (that is, AllPermission). This can not be + * changed through the {@link java.security.Policy} class. + * </p> + * + * @return the {@code ProtectionDomain} of the class represented by this + * class. + * @throws SecurityException + * if a security manager exists and it does not allow member + * access. */ public ProtectionDomain getProtectionDomain() { SecurityManager smgr = System.getSecurityManager(); if (smgr != null) { - ClassLoader calling = VMStack.getCallingClassLoader(); - ClassLoader current = getClassLoaderImpl(); - - if (calling != null && !calling.getClass().isInstance(current)) { - smgr.checkPermission(new RuntimePermission("getProtectionDomain")); - } + // Security check is independent of calling class loader. + smgr.checkPermission(new RuntimePermission("getProtectionDomain")); } return pd; } /** - * Returns a read-only stream on the contents of the resource specified by - * resName. The mapping between the resource name and the stream is managed - * by the class' class loader. + * Returns the URL of the resource specified by {@code resName}. The mapping + * between the resource name and the URL is managed by the class' class + * loader. * - * @param resName the name of the resource. - * @return a stream on the resource. + * @param resName + * the name of the resource. + * @return the requested resource's {@code URL} object or {@code null} if + * the resource can not be found. * @see ClassLoader + * @since Android 1.0 */ public URL getResource(String resName) { // Get absolute resource name, but without the leading slash @@ -1039,14 +1204,17 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe } /** - * Returns a read-only stream on the contents of the resource specified by - * resName. The mapping between the resource name and the stream is managed - * by the class' class loader. + * Returns a read-only stream for the contents of the resource specified by + * {@code resName}. The mapping between the resource name and the stream is + * managed by the class' class loader. * - * @param resName the name of the resource. - * @return a stream on the resource. + * @param resName + * the name of the resource. + * @return a stream for the requested resource or {@code null} if no + * resource with the specified name can be found. * @see ClassLoader - */ + * @since Android 1.0 + */ public InputStream getResourceAsStream(String resName) { // Get absolute resource name, but without the leading slash if (resName.startsWith("/")) { @@ -1073,11 +1241,12 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe } /** - * Returns the signers for the class represented by the receiver, or null if - * there are no signers. + * Returns the signers for the class represented by this {@code Class} or + * {@code null} if either there are no signers or this {@code Class} + * represents a primitive type or void. * - * @return the signers of the receiver. - * @see #getMethods + * @return the signers of the class represented by this {@code Class}. + * @since Android 1.0 */ public Object[] getSigners() { // TODO Delegate this to class loader somehow? What are these signers? @@ -1085,37 +1254,39 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe } /** - * Returns the Class which represents the receiver's superclass. For Classes - * which represent base types, interfaces, and for {@link Object} the method - * returns null. + * Returns the {@code Class} object which represents the superclass of the + * class represented by this {@code Class}. If this {@code Class} represents + * the {@code Object} class, a primitive type, an interface or void then the + * method returns {@code null}. If this {@code Class} represents an array + * class then the {@code Object} class is returned. * - * @return the receiver's superclass. + * @return the superclass of the class represented by this {@code Class}. + * @since Android 1.0 */ public native Class<? super T> getSuperclass(); /** - * Gets the type variables associated with this class. Returns an empty - * array if the class is not generic or does not make use of type - * variables otherwise. + * Returns an array containing {@code TypeVariable} objects for type + * variables declared by the generic class represented by this {@code + * Class}. Returns an empty array if the class is not generic. * - * @return An array of {@link TypeVariable} instances. - * @since 1.5 + * @return an array with the type variables of the class represented by this + * class. + * @since Android 1.0 */ @SuppressWarnings("unchecked") public synchronized TypeVariable<Class<T>>[] getTypeParameters() { - // BEGIN android-changed GenericSignatureParser parser = new GenericSignatureParser(); parser.parseForClass(this, getSignatureAttribute()); return parser.formalTypeParameters.clone(); - // END android-changed } /** - * Indicates whether or not this class is an annotation. + * Indicates whether this {@code Class} represents an annotation class. * - * @return A value of <code>true</code> if this class is an annotation, - * otherwise <code>false</code>. - * @since 1.5 + * @return {@code true} if this {@code Class} represents an annotation + * class; {@code false} otherwise. + * @since Android 1.0 */ public boolean isAnnotation() { final int ACC_ANNOTATION = 0x2000; // not public in reflect.Modifiers @@ -1124,86 +1295,100 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe } /** - * Indicates whether or not the given annotation is present for this class. + * Indicates whether the specified annotation is present for the class + * represented by this {@code Class}. * - * @param annotationClass The annotation to look for in this class. - * @return A value of <code>true</code> if the annotation is present, - * otherwise <code>false</code>. - * @since 1.5 + * @param annotationClass + * the annotation to look for. + * @return {@code true} if the class represented by this {@code Class} is + * annotated with {@code annotationClass}; {@code false} otherwise. + * @since Android 1.0 */ public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) { return getAnnotation(annotationClass) != null; } /** - * Indicates whether or not this class was anonymously declared. + * Indicates whether the class represented by this {@code Class} is + * anonymously declared. * - * @return A value of <code>true</code> if this class is anonymous, - * otherwise <code>false</code>. - * @since 1.5 + * @return {@code true} if the class represented by this {@code Class} is + * anonymous; {@code false} otherwise. + * @since Android 1.0 */ native public boolean isAnonymousClass(); /** - * Returns true if the receiver represents an array class. + * Indicates whether the class represented by this {@code Class} is an array + * class. * - * @return <code>true</code> if the receiver represents an array class - * <code>false</code> if it does not represent an array class + * @return {@code true} if the class represented by this {@code Class} is an + * array class; {@code false} otherwise. + * @since Android 1.0 */ public boolean isArray() { return getComponentType() != null; } /** - * Returns true if the type represented by the argument can be converted via - * an identity conversion or a widening reference conversion (i.e. if either - * the receiver or the argument represent primitive types, only the identity - * conversion applies). + * Indicates whether the specified class type can be converted to the class + * represented by this {@code Class}. Conversion may be done via an identity + * conversion or a widening reference conversion (if either the receiver or + * the argument represent primitive types, only the identity conversion + * applies). * - * @return <code>true</code> the argument can be assigned into the - * receiver <code>false</code> the argument cannot be assigned - * into the receiver - * @param cls Class the class to test - * @throws NullPointerException if the parameter is null + * @param cls + * the class to check. + * @return {@code true} if {@code cls} can be converted to the class + * represented by this {@code Class}; {@code false} otherwise. + * @throws NullPointerException + * if {@code cls} is {@code null}. + * @since Android 1.0 */ public native boolean isAssignableFrom(Class<?> cls); /** - * Indicates whether or not this class is an <code>enum</code>. + * Indicates whether the class represented by this {@code Class} is an + * {@code enum}. * - * @return A value of <code>true</code> if this class is an {@link Enum}, - * otherwise <code>false</code>. - * @since 1.5 + * @return {@code true} if the class represented by this {@code Class} is an + * {@code enum}; {@code false} otherwise. + * @since Android 1.0 */ public boolean isEnum() { return ((getModifiers() & 0x4000) != 0) && (getSuperclass() == Enum.class); } /** - * Returns true if the argument is non-null and can be cast to the type of - * the receiver. This is the runtime version of the <code>instanceof</code> - * operator. + * Indicates whether the specified object can be cast to the class + * represented by this {@code Class}. This is the runtime version of the + * {@code instanceof} operator. * - * @return <code>true</code> the argument can be cast to the type of the - * receiver <code>false</code> the argument is null or cannot be - * cast to the type of the receiver - * @param object Object the object to test + * @param object + * the object to check. + * @return {@code true} if {@code object} can be cast to the type + * represented by this {@code Class}; {@code false} if {@code + * object} is {@code null} or cannot be cast. + * @since Android 1.0 */ public native boolean isInstance(Object object); /** - * Returns true if the receiver represents an interface. + * Indicates whether this {@code Class} represents an interface. * - * @return <code>true</code> if the receiver represents an interface - * <code>false</code> if it does not represent an interface + * @return {@code true} if this {@code Class} represents an interface; + * {@code false} otherwise. + * @since Android 1.0 */ public native boolean isInterface(); /** - * Returns whether the receiver is defined locally. + * Indicates whether the class represented by this {@code Class} is defined + * locally. * - * @return <code>true</code> if the class is local, otherwise - * <code>false</code>. + * @return {@code true} if the class represented by this {@code Class} is + * defined locally; {@code false} otherwise. + * @since Android 1.0 */ public boolean isLocalClass() { boolean enclosed = (getEnclosingMethod() != null || @@ -1212,28 +1397,32 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe } /** - * Returns whether the receiver is a member class. + * Indicates whether the class represented by this {@code Class} is a member + * class. * - * @return <code>true</code> if the class is a member class, otherwise - * <code>false</code>. + * @return {@code true} if the class represented by this {@code Class} is a + * member class; {@code false} otherwise. + * @since Android 1.0 */ public boolean isMemberClass() { return getDeclaringClass() != null; } /** - * Returns true if the receiver represents a base type. + * Indicates whether this {@code Class} represents a primitive type. * - * @return <code>true</code> if the receiver represents a base type - * <code>false</code> if it does not represent a base type + * @return {@code true} if this {@code Class} represents a primitive type; + * {@code false} otherwise. + * @since Android 1.0 */ public native boolean isPrimitive(); /** - * Returns whether the receiver is a synthetic type. + * Indicates whether this {@code Class} represents a synthetic type. * - * @return <code>true</code> if the receiver is a synthetic type and - * <code>false</code> otherwise. + * @return {@code true} if this {@code Class} represents a synthetic type; + * {@code false} otherwise. + * @since Android 1.0 */ public boolean isSynthetic() { final int ACC_SYNTHETIC = 0x1000; // not public in reflect.Modifiers @@ -1242,27 +1431,33 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe } /** - * Returns a new instance of the class represented by the receiver, created - * by invoking the default (i.e. zero-argument) constructor. If there is no - * such constructor, or if the creation fails (either because of a lack of - * available memory or because an exception is thrown by the constructor), - * an InstantiationException is thrown. If the default constructor exists, - * but is not accessible from the context where this message is sent, an - * IllegalAccessException is thrown. - * - * @return a new instance of the class represented by the receiver. - * @throws IllegalAccessException if the constructor is not visible to the - * sender. - * @throws InstantiationException if the instance could not be created. - */ - public native T newInstance() throws IllegalAccessException, InstantiationException; + * Returns a new instance of the class represented by this {@code Class}, + * created by invoking the default (that is, zero-argument) constructor. If + * there is no such constructor, or if the creation fails (either because of + * a lack of available memory or because an exception is thrown by the + * constructor), an {@code InstantiationException} is thrown. If the default + * constructor exists but is not accessible from the context where this + * method is invoked, an {@code IllegalAccessException} is thrown. + * + * @return a new instance of the class represented by this {@code Class}. + * @throws IllegalAccessException + * if the default constructor is not visible. + * @throws InstantiationException + * if the instance can not be created. + * @throws SecurityException + * if a security manager exists and it does not allow creating + * new instances. + * @since Android 1.0 + */ + public T newInstance() throws IllegalAccessException, + InstantiationException { + checkPublicMemberAccess(); + return newInstanceImpl(); + } + + private native T newInstanceImpl() throws IllegalAccessException, + InstantiationException; - /** - * Returns a string containing a concise, human-readable description of the - * receiver. - * - * @return a printable representation for the receiver. - */ @Override public String toString() { if (isPrimitive()) { @@ -1273,10 +1468,13 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe } /** - * Returns the Package of which this class is a member. A class has a - * Package if it was loaded from a SecureClassLoader + * Returns the {@code Package} of which the class represented by this + * {@code Class} is a member. Returns {@code null} if no {@code Package} + * object was created by the class loader of the class. * - * @return Package the Package of which this class is a member or null + * @return Package the {@code Package} of which this {@code Class} is a + * member or {@code null}. + * @since Android 1.0 */ public Package getPackage() { // TODO This might be a hack, but the VM doesn't have the necessary info. @@ -1291,40 +1489,55 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe } /** - * Returns the assertion status for this class. Assertion is - * enabled/disabled based on class loader default, package or class default - * at runtime + * Returns the assertion status for the class represented by this {@code + * Class}. Assertion is enabled / disabled based on the class loader, + * package or class default at runtime. * - * @return the assertion status for this class + * @return the assertion status for the class represented by this {@code + * Class}. + * @since Android 1.0 */ public native boolean desiredAssertionStatus(); /** - * Casts the receiver to a subclass of the given class. If successful - * returns the receiver, otherwise if the cast cannot be made throws a - * <code>ClassCastException</code>. + * Casts this {@code Class} to represent a subclass of the specified class. + * If successful, this {@code Class} is returned; otherwise a {@code + * ClassCastException} is thrown. * - * @param clazz the required type. - * @return this class cast as a subclass of the given type. - * @throws ClassCastException if the class cannot be cast to the given type. + * @param clazz + * the required type. + * @return this {@code Class} cast as a subclass of the given type. + * @throws ClassCastException + * if this {@code Class} cannot be cast to the specified type. + * @since Android 1.0 */ @SuppressWarnings("unchecked") public <U> Class<? extends U> asSubclass(Class<U> clazz) { - return (Class<? extends U>)this; + if (clazz.isAssignableFrom(this)) { + return (Class<? extends U>)this; + } + throw new ClassCastException(); } /** - * Cast the given object to the type <code>T</code>. - * If the object is <code>null</code> the result is also - * <code>null</code>. + * Casts the specified object to the type represented by this {@code Class}. + * If the object is {@code null} then the result is also {@code null}. * - * @param obj the object to cast - * @return The object that has been cast. - * @throws ClassCastException if the object cannot be cast to the given type. + * @param obj + * the object to cast. + * @return the object that has been cast. + * @throws ClassCastException + * if the object cannot be cast to the specified type. + * @since Android 1.0 */ @SuppressWarnings("unchecked") public T cast(Object obj) { - return (T)obj; + if (obj == null) { + return null; + } else if (this.isInstance(obj)) { + return (T)obj; + } + throw new ClassCastException(); } /** @@ -1395,17 +1608,3 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe } } - -/** - * TODO Open issues - * - Check whether contracts of all (native) methods are ok. Some return null, - * others return empty arrays. Same throw exceptions, other don't. - * - Check whether reflection methods for lists of fields etc. are ok. Some take - * superclasses into account, others don't. - * - Check whether handling of naming for primitive classes is ok. - * - Searching for specific members could be implemented more efficently. - * - Test getInterfaces() - * - Test getEnumConstants() - * - Check various TODOs in code. - * - Complete ticket - */ diff --git a/luni-kernel/src/main/java/java/lang/ClassCache.java b/luni-kernel/src/main/java/java/lang/ClassCache.java index c7e087c..5ea6992 100644 --- a/luni-kernel/src/main/java/java/lang/ClassCache.java +++ b/luni-kernel/src/main/java/java/lang/ClassCache.java @@ -68,6 +68,18 @@ import java.util.HashSet; /** null-ok; list of all public methods, both direct and inherited */ private volatile Method[] allPublicMethods; + /** null-ok; list of all declared fields */ + private volatile Field[] declaredFields; + + /** null-ok; list of all public declared fields */ + private volatile Field[] declaredPublicFields; + + /** null-ok; list of all fields, both direct and inherited */ + private volatile Field[] allFields; + + /** null-ok; list of all public fields, both direct and inherited */ + private volatile Field[] allPublicFields; + /** * null-ok; array of enumerated values in their original order, if this * instance's class is an enumeration @@ -125,6 +137,10 @@ import java.util.HashSet; this.allPublicMethods = null; this.enumValuesInOrder = null; this.enumValuesByName = null; + this.declaredFields = null; + this.declaredPublicFields = null; + this.allFields = null; + this.allPublicFields = null; } /** @@ -204,7 +220,7 @@ import java.util.HashSet; ArrayList<Method> methods = new ArrayList<Method>(); HashSet<String> seen = new HashSet<String>(); - getFullListOfMethods(clazz, methods, seen, publicOnly); + findAllMethods(clazz, methods, seen, publicOnly); return methods.toArray(new Method[methods.size()]); } @@ -222,7 +238,7 @@ import java.util.HashSet; * @param publicOnly reflects whether we want only public methods * or all of them */ - private static void getFullListOfMethods(Class<?> clazz, + private static void findAllMethods(Class<?> clazz, ArrayList<Method> methods, HashSet<String> seen, boolean publicOnly) { StringBuilder builder = new StringBuilder(); @@ -234,11 +250,11 @@ import java.util.HashSet; clazz.getClassCache().getDeclaredMethods(publicOnly); int length = declaredMethods.length; if (length != 0) { - for (int i = 0; i < length; i++) { + for (Method method : declaredMethods) { builder.setLength(0); - builder.append(declaredMethods[i].getName()); + builder.append(method.getName()); builder.append('('); - Class<?>[] types = declaredMethods[i].getParameterTypes(); + Class<?>[] types = method.getParameterTypes(); if (types.length != 0) { builder.append(types[0].getName()); for (int j = 1; j < types.length; j++) { @@ -250,7 +266,7 @@ import java.util.HashSet; String signature = builder.toString(); if (!seen.contains(signature)) { - methods.add(declaredMethods[i]); + methods.add(method); seen.add(signature); } } @@ -261,8 +277,8 @@ import java.util.HashSet; // Traverse all interfaces, and do the same recursively. Class<?>[] interfaces = origClass.getInterfaces(); - for (int i = 0; i < interfaces.length; i++) { - getFullListOfMethods(interfaces[i], methods, seen, publicOnly); + for (Class<?> intf : interfaces) { + findAllMethods(intf, methods, seen, publicOnly); } } @@ -273,10 +289,13 @@ import java.util.HashSet; * @param list non-null; the list of methods to search through * @param parameterTypes non-null; the formal parameter list * @return non-null; the matching method - * @throws NoSuchMethodExcpetion thrown if the method does not exist + * @throws NoSuchMethodException thrown if the method does not exist */ - public static Method getMatchingMethod(Method[] list, String name, + public static Method findMethodByName(Method[] list, String name, Class<?>[] parameterTypes) throws NoSuchMethodException { + if (name == null) { + throw new NullPointerException("Method name must not be null."); + } for (int i = list.length - 1; i >= 0; i--) { Method method = list[i]; if (method.getName().equals(name) @@ -348,6 +367,173 @@ import java.util.HashSet; } /** + * Gets the list of all declared fields. + * + * @return non-null; the list of all declared fields + */ + public Field[] getDeclaredFields() { + if (declaredFields == null) { + declaredFields = Class.getDeclaredFields(clazz, false); + } + + return declaredFields; + } + + /** + * Gets the list of all declared public fields. + * + * @return non-null; the list of all declared public fields + */ + public Field[] getDeclaredPublicFields() { + if (declaredPublicFields == null) { + declaredPublicFields = Class.getDeclaredFields(clazz, true); + } + + return declaredPublicFields; + } + + /** + * Gets either the list of declared fields or the list of declared + * public fields. + * + * @param publicOnly whether to only return public fields + */ + public Field[] getDeclaredFields(boolean publicOnly) { + return publicOnly ? getDeclaredPublicFields() : getDeclaredFields(); + } + + /** + * Gets the list of all fields, both directly + * declared and inherited. + * + * @return non-null; the list of all fields + */ + public Field[] getAllFields() { + if (allFields == null) { + allFields = getFullListOfFields(false); + } + + return allFields; + } + + /** + * Gets the list of all public fields, both directly + * declared and inherited. + * + * @return non-null; the list of all public fields + */ + public Field[] getAllPublicFields() { + if (allPublicFields == null) { + allPublicFields = getFullListOfFields(true); + } + + return allPublicFields; + } + + /* + * Returns the list of fields without performing any security checks + * first. This includes the fields inherited from superclasses. If no + * fields exist at all, an empty array is returned. + * + * @param publicOnly reflects whether we want only public fields + * or all of them + * @return the list of fields + */ + private Field[] getFullListOfFields(boolean publicOnly) { + ArrayList<Field> fields = new ArrayList<Field>(); + HashSet<String> seen = new HashSet<String>(); + + findAllfields(clazz, fields, seen, publicOnly); + + return fields.toArray(new Field[fields.size()]); + } + + /** + * Collects the list of fields without performing any security checks + * first. This includes the fields inherited from superclasses and from + * all implemented interfaces. The latter may also implement multiple + * interfaces, so we (potentially) recursively walk through a whole tree of + * classes. If no fields exist at all, an empty array is returned. + * + * @param clazz non-null; class to inspect + * @param fields non-null; the target list to add the results to + * @param seen non-null; a set of signatures we've already seen + * @param publicOnly reflects whether we want only public fields + * or all of them + */ + private static void findAllfields(Class<?> clazz, + ArrayList<Field> fields, HashSet<String> seen, + boolean publicOnly) { + + // Traverse class and superclasses, get rid of dupes by signature + while (clazz != null) { + Field[] declaredFields = + clazz.getClassCache().getDeclaredFields(publicOnly); + for (Field field : declaredFields) { + String signature = field.toString(); + if (!seen.contains(signature)) { + fields.add(field); + seen.add(signature); + } + } + + // Traverse all interfaces, and do the same recursively. + Class<?>[] interfaces = clazz.getInterfaces(); + for (Class<?> intf : interfaces) { + findAllfields(intf, fields, seen, publicOnly); + } + + clazz = clazz.getSuperclass(); + } + } + + /** + * Finds and returns a field with a given name and signature. Use + * this with one of the field lists returned by instances of this class. + * + * @param list non-null; the list of fields to search through + * @return non-null; the matching field + * @throws NoSuchFieldException thrown if the field does not exist + */ + public static Field findFieldByName(Field[] list, String name) + throws NoSuchFieldException { + if (name == null) { + throw new NullPointerException("Field name must not be null."); + } + for (int i = 0; i < list.length; i++) { + Field field = list[i]; + if (field.getName().equals(name)) { + return field; + } + } + + throw new NoSuchFieldException(name); + } + + /** + * Makes a deep copy of the given array of fields. This is useful + * when handing out arrays from the public API. + * + * <p><b>Note:</b> In such cases, it is insufficient to just make + * a shallow copy of the array, since field objects aren't + * immutable due to the existence of {@link + * AccessibleObject#setAccessible}.</p> + * + * @param orig non-null; array to copy + * @return non-null; a deep copy of the given array + */ + public static Field[] deepCopy(Field[] orig) { + int length = orig.length; + Field[] result = new Field[length]; + + for (int i = length - 1; i >= 0; i--) { + result[i] = REFLECT.clone(orig[i]); + } + + return result; + } + + /** * Gets the enumerated value with a given name. * * @param name non-null; name of the value @@ -444,7 +630,7 @@ import java.util.HashSet; try { Method[] methods = getDeclaredPublicMethods(); - method = getMatchingMethod(methods, "values", (Class[]) null); + method = findMethodByName(methods, "values", (Class[]) null); method = REFLECT.accessibleClone(method); } catch (NoSuchMethodException ex) { // This shouldn't happen if the class is a well-formed enum. @@ -485,7 +671,7 @@ import java.util.HashSet; Class.getDeclaredMethods(AccessibleObject.class, false); try { - Method method = getMatchingMethod(methods, "getReflectionAccess", + Method method = findMethodByName(methods, "getReflectionAccess", (Class[]) null); Class.setAccessibleNoCheck(method, true); return (ReflectionAccess) method.invoke((Object[]) null); diff --git a/luni-kernel/src/main/java/java/lang/ClassLoader.java b/luni-kernel/src/main/java/java/lang/ClassLoader.java index d57abeb..95bfd41 100644 --- a/luni-kernel/src/main/java/java/lang/ClassLoader.java +++ b/luni-kernel/src/main/java/java/lang/ClassLoader.java @@ -31,41 +31,44 @@ import dalvik.system.PathClassLoader; import dalvik.system.VMStack; /** + * Loads classes and resources from a repository. One or more class loaders are + * installed at runtime. These are consulted whenever the runtime system needs a + * specific class that is not yet available in-memory. Typically, class loaders + * are grouped into a tree where child class loaders delegate all requests to + * parent class loaders. Only if the parent class loader cannot satisfy the + * request, the child class loader itself tries to handle it. * <p> - * A ClassLoader is used for loading classes. + * {@code ClassLoader} is an abstract class that implements the common + * infrastructure required by all class loaders. Android provides several + * concrete implementations of the class, with + * {@link dalvik.system.PathClassLoader} being the one typically used. Other + * applications may implement subclasses of {@code ClassLoader} to provide + * special ways for loading classes. * </p> * - * <h4>VM Implementors Note</h4> - * <p> - * This class must be implemented by the VM. The documented methods and natives - * must be implemented to support other provided class implementations in this - * package. - * </p> - * - * @since 1.0 + * @since Android 1.0 * @see Class */ public abstract class ClassLoader { -// BEGIN android-note + // BEGIN android-note /* - * Because of a potential class initialization race between ClassLoader - * and java.lang.System, reproducible when using JDWP with "suspend=y", - * we defer creation of the system class loader until first use. We - * use a static inner class to get synchronization at init time without - * having to sync on every access. + * Because of a potential class initialization race between ClassLoader and + * java.lang.System, reproducible when using JDWP with "suspend=y", we defer + * creation of the system class loader until first use. We use a static + * inner class to get synchronization at init time without having to sync on + * every access. */ -// END android-note - + // END android-note /** * The 'System' ClassLoader - the one that is responsible for loading - * classes from the classpath. It is not equal to the bootstrap class - * loader - that one handles the built-in classes. - * + * classes from the classpath. It is not equal to the bootstrap class loader - + * that one handles the built-in classes. + * * @see #getSystemClassLoader() */ static private class SystemClassLoader { - public static ClassLoader loader= ClassLoader.createSystemClassLoader(); + public static ClassLoader loader = ClassLoader.createSystemClassLoader(); }; /** @@ -79,53 +82,51 @@ public abstract class ClassLoader { private Map<String, Package> packages = new HashMap<String, Package>(); /** - * Create the system class loader. - * - * Note this is NOT the bootstrap class loader (which is managed by - * the VM). We use a null value for the parent to indicate that the - * bootstrap loader is our parent. + * Create the system class loader. Note this is NOT the bootstrap class + * loader (which is managed by the VM). We use a null value for the parent + * to indicate that the bootstrap loader is our parent. */ private static ClassLoader createSystemClassLoader() { String classPath = System.getProperty("java.class.path", "."); -// String[] paths = classPath.split(":"); -// URL[] urls = new URL[paths.length]; -// for (int i = 0; i < paths.length; i++) { -// try { -// urls[i] = new URL("file://" + paths[i]); -// } -// catch (Exception ex) { -// ex.printStackTrace(); -// } -// } -// -// return new java.net.URLClassLoader(urls, null); - + // String[] paths = classPath.split(":"); + // URL[] urls = new URL[paths.length]; + // for (int i = 0; i < paths.length; i++) { + // try { + // urls[i] = new URL("file://" + paths[i]); + // } + // catch (Exception ex) { + // ex.printStackTrace(); + // } + // } + // + // return new java.net.URLClassLoader(urls, null); + // TODO Make this a java.net.URLClassLoader once we have those? return new PathClassLoader(classPath, BootClassLoader.getInstance()); } /** - * Returns the system class loader. This is the parent for new ClassLoader - * instances, and is typically the class loader used to start the - * application. If a security manager is present, and the caller's class - * loader is not null and the caller's class loader is not the same as or an - * ancestor of the system class loader, then this method calls the security - * manager's checkPermission method with a - * RuntimePermission("getClassLoader") permission to ensure it's ok to - * access the system class loader. If not, a SecurityException will be - * thrown. + * Returns the system class loader. This is the parent for new + * {@code ClassLoader} instances and is typically the class loader used to + * start the application. If a security manager is present and the caller's + * class loader is neither {@code null} nor the same as or an ancestor of + * the system class loader, then this method calls the security manager's + * checkPermission method with a RuntimePermission("getClassLoader") + * permission to ensure that it is ok to access the system class loader. If + * not, a {@code SecurityException} is thrown. * - * @return The system classLoader. - * @throws SecurityException if a security manager exists and it does not - * allow access to the system class loader. + * @return the system class loader. + * @throws SecurityException + * if a security manager exists and it does not allow access to + * the system class loader. + * @since Android 1.0 */ public static ClassLoader getSystemClassLoader() { SecurityManager smgr = System.getSecurityManager(); if (smgr != null) { ClassLoader caller = VMStack.getCallingClassLoader(); - if (caller != null && - !caller.isAncestorOf(SystemClassLoader.loader)) { + if (caller != null && !caller.isAncestorOf(SystemClassLoader.loader)) { smgr.checkPermission(new RuntimePermission("getClassLoader")); } } @@ -134,38 +135,48 @@ public abstract class ClassLoader { } /** - * Returns an URL specifying a resource which can be found by looking up - * resName using the system class loader's resource lookup algorithm. + * Finds the URL of the resource with the specified name. The system class + * loader's resource lookup algorithm is used to find the resource. * - * @return A URL specifying a system resource or null. - * @param resName The name of the resource to find. + * @return the {@code URL} object for the requested resource or {@code null} + * if the resource can not be found. + * @param resName + * the name of the resource to find. * @see Class#getResource + * @since Android 1.0 */ public static URL getSystemResource(String resName) { return SystemClassLoader.loader.getResource(resName); } /** - * Returns an Enumeration of URLs containing all resources which can be - * found by looking up resName using the system class loader's resource - * lookup algorithm. + * Returns an enumeration of URLs for the resource with the specified name. + * The system class loader's resource lookup algorithm is used to find the + * resource. * - * @return An Enumeration of URLs containing the system resources - * @param resName String the name of the resource to find. + * @return an enumeration of {@code URL} objects containing the requested + * resources. + * @param resName + * the name of the resource to find. + * @throws IOException + * if an I/O error occurs. + * @since Android 1.0 */ public static Enumeration<URL> getSystemResources(String resName) throws IOException { return SystemClassLoader.loader.getResources(resName); } /** - * Returns a stream on a resource found by looking up resName using the - * system class loader's resource lookup algorithm. Basically, the contents - * of the java.class.path are searched in order, looking for a path which - * matches the specified resource. + * Returns a stream for the resource with the specified name. The system + * class loader's resource lookup algorithm is used to find the resource. + * Basically, the contents of the java.class.path are searched in order, + * looking for a path which matches the specified resource. * - * @return A stream on the resource or null. - * @param resName The name of the resource to find. + * @return a stream for the resource or {@code null}. + * @param resName + * the name of the resource to find. * @see Class#getResourceAsStream + * @since Android 1.0 */ public static InputStream getSystemResourceAsStream(String resName) { return SystemClassLoader.loader.getResourceAsStream(resName); @@ -175,27 +186,31 @@ public abstract class ClassLoader { * Constructs a new instance of this class with the system class loader as * its parent. * - * @throws SecurityException if a security manager exists and it does not - * allow the creation of new ClassLoaders. + * @throws SecurityException + * if a security manager exists and it does not allow the + * creation of a new {@code ClassLoader}. + * @since Android 1.0 */ protected ClassLoader() { SecurityManager smgr = System.getSecurityManager(); if (smgr != null) { smgr.checkCreateClassLoader(); } - + parent = getSystemClassLoader(); } /** - * Constructs a new instance of this class with the given class loader as - * its parent. + * Constructs a new instance of this class with the specified class loader + * as its parent. * - * @param parentLoader The ClassLoader to use as the new class loaders - * parent. - * @throws SecurityException if a security manager exists and it does not - * allow the creation of new ClassLoaders. - * @throws NullPointerException if the parent is null. + * @param parentLoader + * The {@code ClassLoader} to use as the new class loader's + * parent. + * @throws SecurityException + * if a security manager exists and it does not allow the + * creation of new a new {@code ClassLoader}. + * @since Android 1.0 */ protected ClassLoader(ClassLoader parentLoader) { SecurityManager smgr = System.getSecurityManager(); @@ -204,10 +219,10 @@ public abstract class ClassLoader { } // TODO Shouldn't we check for null values here? -// if (parent == null) { -// throw new NullPointerException(); -// } - + // if (parent == null) { + // throw new NullPointerException(); + // } + parent = parentLoader; } @@ -215,15 +230,27 @@ public abstract class ClassLoader { * Constructs a new class from an array of bytes containing a class * definition in class file format. * - * @param classRep A memory image of a class file. - * @param offset The offset into the classRep. - * @param length The length of the class file. + * @param classRep + * the memory image of a class file. + * @param offset + * the offset into {@code classRep}. + * @param length + * the length of the class file. + * @return the {@code Class} object created from the specified subset of + * data in {@code classRep}. + * @throws ClassFormatError + * if {@code classRep} does not contain a valid class. + * @throws IndexOutOfBoundsException + * if {@code offset < 0}, {@code length < 0} or if + * {@code offset + length} is greater than the length of + * {@code classRep}. * @deprecated Use {@link #defineClass(String, byte[], int, int)} + * @since Android 1.0 */ @Deprecated protected final Class<?> defineClass(byte[] classRep, int offset, int length) throws ClassFormatError { - + return VMClassLoader.defineClass(this, classRep, offset, length, null); } @@ -231,13 +258,27 @@ public abstract class ClassLoader { * Constructs a new class from an array of bytes containing a class * definition in class file format. * - * @param className The name of the new class - * @param classRep A memory image of a class file - * @param offset The offset into the classRep - * @param length The length of the class file + * @param className + * the expected name of the new class, may be {@code null} if not + * known. + * @param classRep + * the memory image of a class file. + * @param offset + * the offset into {@code classRep}. + * @param length + * the length of the class file. + * @return the {@code Class} object created from the specified subset of + * data in {@code classRep}. + * @throws ClassFormatError + * if {@code classRep} does not contain a valid class. + * @throws IndexOutOfBoundsException + * if {@code offset < 0}, {@code length < 0} or if + * {@code offset + length} is greater than the length of + * {@code classRep}. + * @since Android 1.0 */ - protected final Class<?> defineClass(String className, byte[] classRep, int offset, - int length) throws ClassFormatError { + protected final Class<?> defineClass(String className, byte[] classRep, int offset, int length) + throws ClassFormatError { // TODO Define a default ProtectionDomain on first use return defineClass(className, classRep, offset, length, null); @@ -245,112 +286,153 @@ public abstract class ClassLoader { /** * Constructs a new class from an array of bytes containing a class - * definition in class file format and assigns the new class to the - * specified protection domain. - * - * @param className The name of the new class. - * @param classRep A memory image of a class file. - * @param offset The offset into the classRep. - * @param length The length of the class file. - * @param protectionDomain The protection domain this class should belongs - * to. - */ - protected final Class<?> defineClass(String className, byte[] classRep, int offset, - int length, ProtectionDomain protectionDomain) throws java.lang.ClassFormatError { - + * definition in class file format and assigns the specified protection + * domain to the new class. If the provided protection domain is + * {@code null} then a default protection domain is assigned to the class. + * + * @param className + * the expected name of the new class, may be {@code null} if not + * known. + * @param classRep + * the memory image of a class file. + * @param offset + * the offset into {@code classRep}. + * @param length + * the length of the class file. + * @param protectionDomain + * the protection domain to assign to the loaded class, may be + * {@code null}. + * @return the {@code Class} object created from the specified subset of + * data in {@code classRep}. + * @throws ClassFormatError + * if {@code classRep} does not contain a valid class. + * @throws IndexOutOfBoundsException + * if {@code offset < 0}, {@code length < 0} or if + * {@code offset + length} is greater than the length of + * {@code classRep}. + * @throws NoClassDefFoundError + * if {@code className} is not equal to the name of the class + * contained in {@code classRep}. + * @since Android 1.0 + */ + protected final Class<?> defineClass(String className, byte[] classRep, int offset, int length, + ProtectionDomain protectionDomain) throws java.lang.ClassFormatError { + return VMClassLoader.defineClass(this, className, classRep, offset, length, protectionDomain); } /** - * <p> - * Defines a new class for the name, bytecodes in the byte buffer and the - * protection domain. - * </p> + * Defines a new class with the specified name, byte code from the byte + * buffer and the optional protection domain. If the provided protection + * domain is {@code null} then a default protection domain is assigned to + * the class. * - * @param name The name of the class to define. - * @param b The byte buffer containing the bytecodes of the new class. - * @param protectionDomain The protection domain this class belongs to. - * @return The defined class. - * @throws ClassFormatError if an invalid class file is defined. - * @since 1.5 + * @param name + * the expected name of the new class, may be {@code null} if not + * known. + * @param b + * the byte buffer containing the byte code of the new class. + * @param protectionDomain + * the protection domain to assign to the loaded class, may be + * {@code null}. + * @return the {@code Class} object created from the data in {@code b}. + * @throws ClassFormatError + * if {@code b} does not contain a valid class. + * @throws NoClassDefFoundError + * if {@code className} is not equal to the name of the class + * contained in {@code b}. + * @since Android 1.0 */ protected final Class<?> defineClass(String name, ByteBuffer b, ProtectionDomain protectionDomain) throws ClassFormatError { - + byte[] temp = new byte[b.remaining()]; b.get(temp); return defineClass(name, temp, 0, temp.length, protectionDomain); } /** - * Overridden by subclasses, by default throws ClassNotFoundException. This - * method is called by loadClass() after the parent ClassLoader has failed - * to find a loaded class of the same name. + * Overridden by subclasses, throws a {@code ClassNotFoundException} by + * default. This method is called by {@code loadClass} after the parent + * {@code ClassLoader} has failed to find a loaded class of the same name. * - * @return The class or null. - * @param className The name of the class to search for. - * @throws ClassNotFoundException if the class cannot be found. + * @param className + * the name of the class to look for. + * @return the {@code Class} object that is found. + * @throws ClassNotFoundException + * if the class cannot be found. + * @since Android 1.0 */ protected Class<?> findClass(String className) throws ClassNotFoundException { throw new ClassNotFoundException(className); } /** - * Attempts to find and return a class which has already been loaded by the - * virtual machine. Note that the class may not have been linked and the - * caller should call resolveClass() on the result if necessary. + * Returns the class with the specified name if it has already been loaded + * by the virtual machine or {@code null} if it has not yet been loaded. * - * @return The class or null. - * @param className The name of the class to search for. + * @param className + * the name of the class to look for. + * @return the {@code Class} object or {@code null} if the requested class + * has not been loaded. + * @since Android 1.0 */ protected final Class<?> findLoadedClass(String className) { - // BEGIN android-changed ClassLoader loader; if (this == BootClassLoader.getInstance()) loader = null; else loader = this; return VMClassLoader.findLoadedClass(loader, className); - // END android-changed } /** - * Attempts to load a class using the system class loader. Note that the - * class has already been been linked. + * Finds the class with the specified name, loading it using the system + * class loader if necessary. * - * @return The class which was loaded. - * @param className The name of the class to search for. - * @throws ClassNotFoundException if the class cannot be found. + * @param className + * the name of the class to look for. + * @return the {@code Class} object with the requested {@code className}. + * @throws ClassNotFoundException + * if the class can not be found. + * @since Android 1.0 */ protected final Class<?> findSystemClass(String className) throws ClassNotFoundException { return Class.forName(className, false, getSystemClassLoader()); } /** - * Returns the specified ClassLoader's parent. + * Returns this class loader's parent. * - * @return The class or null. - * @throws SecurityException if a security manager exists and it does not - * allow the parent loader to be retrieved. + * @return this class loader's parent or {@code null}. + * @throws SecurityException + * if a security manager exists and it does not allow to + * retrieve the parent class loader. + * @since Android 1.0 */ public final ClassLoader getParent() { SecurityManager smgr = System.getSecurityManager(); if (smgr != null) { smgr.checkPermission(new RuntimePermission("getClassLoader")); } - + return parent; } /** - * Returns an URL which can be used to access the resource described by - * resName, using the class loader's resource lookup algorithm. The default - * behavior is just to return null. + * Returns the URL of the resource with the specified name. This + * implementation first tries to use the parent class loader to find the + * resource; if this fails then {@link #findResource(String)} is called to + * find the requested resource. * - * @return The location of the resource. - * @param resName String the name of the resource to find. + * @param resName + * the name of the resource to find. + * @return the {@code URL} object for the requested resource or {@code null} + * if either the resource can not be found or a security manager + * does not allow to access the resource. * @see Class#getResource + * @since Android 1.0 */ public URL getResource(String resName) { URL resource = null; @@ -367,12 +449,18 @@ public abstract class ClassLoader { } /** - * Returns an Enumeration of URL which can be used to access the resources - * described by resName, using the class loader's resource lookup algorithm. - * The default behavior is just to return an empty Enumeration. + * Returns an enumeration of URLs for the resource with the specified name. + * This implementation first uses this class loader's parent to find the + * resource, then it calls {@link #findResources(String)} to get additional + * URLs. The returned enumeration contains the {@code URL} objects of both + * find operations. * - * @return The location of the resources. - * @param resName String the name of the resource to find. + * @return an enumeration of {@code URL} objects for the requested resource. + * @param resName + * the name of the resource to find. + * @throws IOException + * if an I/O error occurs. + * @since Android 1.0 */ @SuppressWarnings("unchecked") public Enumeration<URL> getResources(String resName) throws IOException { @@ -388,13 +476,17 @@ public abstract class ClassLoader { } /** - * Returns a stream on a resource found by looking up resName using the - * class loader's resource lookup algorithm. The default behavior is just to - * return null. + * Returns a stream for the resource with the specified name. See + * {@link #getResource(String)} for a description of the lookup algorithm + * used to find the resource. * - * @return A stream on the resource or null. - * @param resName String the name of the resource to find. + * @return a stream for the resource or {@code null} if either the resource + * can not be found or a security manager does not allow to access + * the resource. + * @param resName + * the name of the resource to find. * @see Class#getResourceAsStream + * @since Android 1.0 */ public InputStream getResourceAsStream(String resName) { try { @@ -403,41 +495,60 @@ public abstract class ClassLoader { return url.openStream(); } } catch (IOException ex) { - // Don't want to see the exception. + // Don't want to see the exception. } - + return null; } /** - * Invoked by the Virtual Machine when resolving class references. - * Equivalent to loadClass(className, false); + * Loads the class with the specified name. Invoking this method is + * equivalent to calling {@code loadClass(className, false)}. + * <p> + * <strong>Note:</strong> In the Android reference implementation, the + * second parameter of {@link #loadClass(String, boolean)} is ignored + * anyway. + * </p> * - * @return The Class object. - * @param className The name of the class to search for. - * @throws ClassNotFoundException if the class could not be found. + * @return the {@code Class} object. + * @param className + * the name of the class to look for. + * @throws ClassNotFoundException + * if the class can not be found. + * @since Android 1.0 */ public Class<?> loadClass(String className) throws ClassNotFoundException { return loadClass(className, false); } - // BEGIN android-changed - // Made resolveClass a no-op and changed the documentation accordingly. /** - * Loads the class with the specified name, optionally linking the class - * after load. Steps are: 1) Call findLoadedClass(className) to determine if - * class is loaded 2) Call loadClass(className, resolveClass) on the parent - * loader. 3) Call findClass(className) to find the class + * Loads the class with the specified name, optionally linking it after + * loading. The following steps are performed: + * <ol> + * <li> Call {@link #findLoadedClass(String)} to determine if the requested + * class has already been loaded.</li> + * <li>If the class has not yet been loaded: Invoke this method on the + * parent class loader.</li> + * <li>If the class has still not been loaded: Call + * {@link #findClass(String)} to find the class.</li> + * </ol> + * <p> + * <strong>Note:</strong> In the Android reference implementation, the + * {@code resolve} parameter is ignored; classes are never linked. + * </p> * - * @return The Class object. - * @param className The name of the class to search for. - * @param resolve Indicates if class should be resolved after loading. - * Note: On the android reference implementation this parameter - * does not have any effect. - * @throws ClassNotFoundException if the class could not be found. + * @return the {@code Class} object. + * @param className + * the name of the class to look for. + * @param resolve + * Indicates if the class should be resolved after loading. This + * parameter is ignored on the Android reference implementation; + * classes are not resolved. + * @throws ClassNotFoundException + * if the class can not be found. + * @since Android 1.0 */ - protected Class<?> loadClass(String className, boolean resolve) - throws ClassNotFoundException { + protected Class<?> loadClass(String className, boolean resolve) throws ClassNotFoundException { Class<?> clazz = findLoadedClass(className); if (clazz == null) { @@ -460,35 +571,35 @@ public abstract class ClassLoader { /** * Forces a class to be linked (initialized). If the class has already been * linked this operation has no effect. + * <p> + * <strong>Note:</strong> In the Android reference implementation, this + * method has no effect. + * </p> * - * Note that for the android reference implementation this method does not - * have any effect. - * - * @param clazz The Class to link. - * @throws NullPointerException if clazz is null. - * @see Class#getResource + * @param clazz + * the class to link. + * @since Android 1.0 */ protected final void resolveClass(Class<?> clazz) { // no-op, doesn't make sense on android. } - // END android-changed - + /** - * <p> - * This method must be provided by the VM vendor, as it is used by other - * provided class implementations in this package. A sample implementation - * of this method is provided by the reference implementation. This method - * is used by SecurityManager.classLoaderDepth(), currentClassLoader() and + * Indicates whether this class loader is the system class loader. This + * method must be provided by the virtual machine vendor, as it is used by + * other provided class implementations in this package. A sample + * implementation of this method is provided by the reference + * implementation. This method is used by + * SecurityManager.classLoaderDepth(), currentClassLoader() and * currentLoadedClass(). Returns true if the receiver is a system class * loader. - * </p> * <p> * Note that this method has package visibility only. It is defined here to * avoid the security manager check in getSystemClassLoader, which would be * required to implement this method anywhere else. * </p> * - * @return <code>true</code> if the receiver is a system class loader + * @return {@code true} if the receiver is a system class loader * @see Class#getClassLoaderImpl() */ final boolean isSystemClassLoader() { @@ -507,39 +618,48 @@ public abstract class ClassLoader { * places where class loaders are accesses. * </p> * - * @param child A child candidate - * @return <code>true</code> if the receiver is ancestor of, or equal to, + * @param child + * A child candidate + * @return {@code true} if the receiver is ancestor of, or equal to, * the parameter */ final boolean isAncestorOf(ClassLoader child) { - return (child == this || isAncestorOf(child.getParent())); + for (ClassLoader current = child; current != null; + current = child.parent) { + if (current == this) { + return true; + } + } + return false; } /** - * Returns an URL which can be used to access the resource described by - * resName, using the class loader's resource lookup algorithm. The default - * behavior is just to return null. This should be implemented by a - * ClassLoader. + * Finds the URL of the resource with the specified name. This + * implementation just returns {@code null}; it should be overridden in + * subclasses. * - * @return The location of the resource. - * @param resName The name of the resource to find. + * @param resName + * the name of the resource to find. + * @return the {@code URL} object for the requested resource. + * @since Android 1.0 */ protected URL findResource(String resName) { return null; } /** - * Returns an Enumeration of URL which can be used to access the resources - * described by resName, using the class loader's resource lookup algorithm. - * The default behavior is just to return an empty Enumeration. - * - * @param resName The name of the resource to find. - * - * @return The locations of the resources. + * Finds an enumeration of URLs for the resource with the specified name. + * This implementation just returns an empty {@code Enumeration}; it should + * be overridden in subclasses. * - * @throws IOException when an error occurs + * @param resName + * the name of the resource to find. + * @return an enumeration of {@code URL} objects for the requested resource. + * @throws IOException + * if an I/O error occurs. + * @since Android 1.0 */ - @SuppressWarnings({ + @SuppressWarnings( { "unchecked", "unused" }) protected Enumeration<URL> findResources(String resName) throws IOException { @@ -547,23 +667,32 @@ public abstract class ClassLoader { } /** - * Returns the absolute path of the file containing the library associated - * with the given name, or null. If null is answered, the system searches - * the directories specified by the system property "java.library.path". + * Returns the absolute path of the native library with the specified name, + * or {@code null}. If this method returns {@code null} then the virtual + * machine searches the directories specified by the system property + * "java.library.path". + * <p> + * This implementation always returns {@code null}. + * </p> * - * @return The library file name or null. - * @param libName The name of the library to find. + * @param libName + * the name of the library to find. + * @return the absolute path of the library. + * @since Android 1.0 */ protected String findLibrary(String libName) { return null; } /** - * Attempt to locate the requested package. If no package information can be - * located, null is returned. + * Returns the package with the specified name. Package information is + * searched in this class loader. * - * @param name The name of the package to find - * @return The package requested, or null + * @param name + * the name of the package to find. + * @return the package with the requested name; {@code null} if the package + * can not be found. + * @since Android 1.0 */ protected Package getPackage(String name) { synchronized (packages) { @@ -573,77 +702,101 @@ public abstract class ClassLoader { } /** - * Attempt to locate the requested package using the given class loader. - * If no package information can be located, null is returned. + * Gets the package with the specified name, searching it in the specified + * class loader. * - * @param loader The class loader to use - * @param name The name of the package to find - * @return The package requested, or null + * @param loader + * the class loader to search the package in. + * @param name + * the name of the package to find. + * @return the package with the requested name; {@code null} if the package + * can not be found. + * @since Android 1.0 */ static Package getPackage(ClassLoader loader, String name) { return loader.getPackage(name); } /** - * Return all the packages known to this class loader. + * Returns all the packages known to this class loader. * - * @return All the packages known to this classloader + * @return an array with all packages known to this class loader. + * @since Android 1.0 */ protected Package[] getPackages() { synchronized (packages) { Collection<Package> col = packages.values(); - return (Package[]) col.toArray(); + return (Package[])col.toArray(); } } /** - * Define a new Package using the specified information. + * Defines and returns a new {@code Package} using the specified + * information. If {@code sealBase} is {@code null}, the package is left + * unsealed. Otherwise, the package is sealed using this URL. * - * @param name The name of the package - * @param specTitle The title of the specification for the Package - * @param specVersion The version of the specification for the Package - * @param specVendor The vendor of the specification for the Package - * @param implTitle The implementation title of the Package - * @param implVersion The implementation version of the Package - * @param implVendor The specification vendor of the Package - * @param sealBase If sealBase is null, the package is left unsealed. - * Otherwise, the the package is sealed using this URL. - * @return The Package created - * @throws IllegalArgumentException if the Package already exists + * @param name + * the name of the package. + * @param specTitle + * the title of the specification. + * @param specVersion + * the version of the specification. + * @param specVendor + * the vendor of the specification. + * @param implTitle + * the implementation title. + * @param implVersion + * the implementation version. + * @param implVendor + * the specification vendor. + * @param sealBase + * the URL used to seal this package or {@code null} to leave the + * package unsealed. + * @return the {@code Package} object that has been created. + * @throws IllegalArgumentException + * if a package with the specified name already exists. + * @since Android 1.0 */ protected Package definePackage(String name, String specTitle, String specVersion, - String specVendor, String implTitle, String implVersion, String implVendor, - URL sealBase) throws IllegalArgumentException { + String specVendor, String implTitle, String implVersion, String implVendor, URL sealBase) + throws IllegalArgumentException { - synchronized(packages) { + synchronized (packages) { if (packages.containsKey(name)) { throw new IllegalArgumentException("Package " + name + " already defined"); } - - Package newPackage = new Package(name, specTitle, specVersion, - specVendor, implTitle, implVersion, implVendor, sealBase); + + Package newPackage = new Package(name, specTitle, specVersion, specVendor, implTitle, + implVersion, implVendor, sealBase); packages.put(name, newPackage); - + return newPackage; } } /** - * Gets the signers of a class. + * Gets the signers of the specified class. This implementation returns + * {@code null}. * - * @param c The Class object - * @return signers The signers for the class + * @param c + * the {@code Class} object for which to get the signers. + * @return signers the signers of {@code c}. + * @since Android 1.0 */ final Object[] getSigners(Class<?> c) { return null; } /** - * Sets the signers of a class. + * Sets the signers of the specified class. This implementation does + * nothing. * - * @param c The Class object - * @param signers The signers for the class + * @param c + * the {@code Class} object for which to set the signers. + * @param signers + * the signers for {@code c}. + * @since Android 1.0 */ protected final void setSigners(Class<?> c, Object[] signers) { return; @@ -675,25 +828,16 @@ public abstract class ClassLoader { * <li>The item at depth zero is the caller of this method</li> * </ul> * - * @param depth the stack depth of the requested ClassLoader + * @param depth + * the stack depth of the requested ClassLoader * @return the ClassLoader at the specified depth */ static final ClassLoader getStackClassLoader(int depth) { - return null; - } - - /** - * This method must be included, as it is used by System.load(), - * System.loadLibrary(). The reference implementation of this method uses - * the getStackClassLoader() method. Returns the ClassLoader of the method - * that called the caller. i.e. A.x() calls B.y() calls callerClassLoader(), - * A's ClassLoader will be returned. Returns null for the bootstrap - * ClassLoader. - * - * @return a ClassLoader or null for the bootstrap ClassLoader - */ - static ClassLoader callerClassLoader() { - return null; + Class<?>[] stack = VMStack.getClasses(depth + 1, false); + if(stack.length < depth + 1) { + return null; + } + return stack[depth].getClassLoader(); } /** @@ -703,10 +847,18 @@ public abstract class ClassLoader { * ClassLoader of the calling method. Loads and links the library specified * by the argument. * - * @param libName the name of the library to load - * @param loader the classloader in which to load the library - * @throws UnsatisfiedLinkError if the library could not be loaded - * @throws SecurityException if the library was not allowed to be loaded + * @param libName + * the name of the library to load + * @param loader + * the classloader in which to load the library + * @throws UnsatisfiedLinkError + * if the library could not be loaded + * @throws SecurityException + * if the library was not allowed to be loaded + * <p> + * <strong>Note: </strong>This method does nothing in the Android reference + * implementation. + * </p> */ static void loadLibraryWithClassLoader(String libName, ClassLoader loader) { return; @@ -718,48 +870,82 @@ public abstract class ClassLoader { * the library is loaded using the ClassLoader of the calling method. Loads * and links the library specified by the argument. No security check is * done. + * <p> + * <strong>Note: </strong>This method does nothing in the Android reference + * implementation. + * </p> * - * @param libName the name of the library to load - * @param loader the classloader in which to load the library - * @param libraryPath the library path to search, or null - * @throws UnsatisfiedLinkError if the library could not be loaded + * @param libName + * the name of the library to load + * @param loader + * the classloader in which to load the library + * @param libraryPath + * the library path to search, or null + * @throws UnsatisfiedLinkError + * if the library could not be loaded */ static void loadLibraryWithPath(String libName, ClassLoader loader, String libraryPath) { return; } /** - * Sets the assertion status of a class. + * Sets the assertion status of the class with the specified name. + * <p> + * <strong>Note: </strong>This method does nothing in the Android reference + * implementation. + * </p> * - * @param cname Class name - * @param enable Enable or disable assertion + * @param cname + * the name of the class for which to set the assertion status. + * @param enable + * the new assertion status. + * @since Android 1.0 */ public void setClassAssertionStatus(String cname, boolean enable) { return; } /** - * Sets the assertion status of a package. + * Sets the assertion status of the package with the specified name. + * <p> + * <strong>Note: </strong>This method does nothing in the Android reference + * implementation. + * </p> * - * @param pname Package name - * @param enable Enable or disable assertion - */ + * @param pname + * the name of the package for which to set the assertion status. + * @param enable + * the new assertion status. + * @since Android 1.0 + */ public void setPackageAssertionStatus(String pname, boolean enable) { return; } /** - * Sets the default assertion status of a classloader + * Sets the default assertion status for this class loader. + * <p> + * <strong>Note: </strong>This method does nothing in the Android reference + * implementation. + * </p> * - * @param enable Enable or disable assertion + * @param enable + * the new assertion status. + * @since Android 1.0 */ public void setDefaultAssertionStatus(boolean enable) { return; } /** - * Clears the default, package and class assertion status of a classloader + * Sets the default assertion status for this class loader to {@code false} + * and removes any package default and class assertion status settings. + * <p> + * <strong>Note:</strong> This method does nothing in the Android reference + * implementation. + * </p> * + * @since Android 1.0 */ public void clearAssertionStatus() { return; @@ -773,7 +959,8 @@ public abstract class ClassLoader { * 0 for disabled. * * @return the assertion status. - * @param cname the name of class. + * @param cname + * the name of class. */ boolean getClassAssertionStatus(String cname) { return false; @@ -786,7 +973,8 @@ public abstract class ClassLoader { * 0 for disabled. * * @return the assertion status. - * @param pname the name of package. + * @param pname + * the name of package. */ boolean getPackageAssertionStatus(String pname) { return false; @@ -795,7 +983,7 @@ public abstract class ClassLoader { /** * Returns the default assertion status * - * @return boolean the default assertion status. + * @return the default assertion status. */ boolean getDefaultAssertionStatus() { return false; @@ -810,14 +998,14 @@ public abstract class ClassLoader { class TwoEnumerationsInOne implements Enumeration<URL> { private Enumeration<URL> first; - + private Enumeration<URL> second; - + public TwoEnumerationsInOne(Enumeration<URL> first, Enumeration<URL> second) { this.first = first; this.second = second; } - + public boolean hasMoreElements() { return first.hasMoreElements() || second.hasMoreElements(); } @@ -825,11 +1013,11 @@ class TwoEnumerationsInOne implements Enumeration<URL> { public URL nextElement() { if (first.hasMoreElements()) { return first.nextElement(); - } else { + } else { return second.nextElement(); } } - + } /** @@ -878,14 +1066,14 @@ class BootClassLoader extends ClassLoader { /** * Returns package information for the given package. Unfortunately, the - * BootClassLoader doesn't really have this information, and as a + * Android BootClassLoader doesn't really have this information, and as a * non-secure ClassLoader, it isn't even required to, according to the spec. * Yet, we want to provide it, in order to make all those hopeful callers of - * <code>myClass.getPackage().getName()</code> happy. Thus we construct a - * Package object the first time it is being requested and fill most of the - * fields with dummy values. The Package object is then put into the - * ClassLoader's Package cache, so we see the same one next time. We don't - * create Package objects for null arguments or for the default package. + * {@code myClass.getPackage().getName()} happy. Thus we construct a Package + * object the first time it is being requested and fill most of the fields + * with dummy values. The Package object is then put into the ClassLoader's + * Package cache, so we see the same one next time. We don't create Package + * objects for null arguments or for the default package. * <p> * There a limited chance that we end up with multiple Package objects * representing the same package: It can happen when when a package is @@ -896,26 +1084,24 @@ class BootClassLoader extends ClassLoader { @Override protected Package getPackage(String name) { if (name != null && !"".equals(name)) { - synchronized(this) { + synchronized (this) { Package pack = super.getPackage(name); - + if (pack == null) { - pack = definePackage(name, "Unknown", "0.0", "Unknown", "Unknown", "0.0", "Unknown", null); + pack = definePackage(name, "Unknown", "0.0", "Unknown", "Unknown", "0.0", + "Unknown", null); } - + return pack; - } + } } - + return null; } - + } /** - * TODO Open issues - * - Missing / empty methods - * - Signer stuff - * - Protection domains - * - Assertions + * TODO Open issues - Missing / empty methods - Signer stuff - Protection + * domains - Assertions */ diff --git a/luni-kernel/src/main/java/java/lang/Compiler.java b/luni-kernel/src/main/java/java/lang/Compiler.java index 06c15bf..cf41f06 100644 --- a/luni-kernel/src/main/java/java/lang/Compiler.java +++ b/luni-kernel/src/main/java/java/lang/Compiler.java @@ -18,11 +18,13 @@ package java.lang; /** - * This class must be implemented by the VM vendor. This class is a placeholder - * for environments which explicitly manage the action of a "Just In Time" - * compiler. + * Placeholder class for environments which explicitly manage the action of a + * <em>Just In Time (JIT)</em> compiler. This class is usually implemented by + * the virtual machine vendor. The Android reference implementation does not + * (yet) contain such a JIT compiler, though other implementations may choose to + * provide one. * - * @see Cloneable + * @since Android 1.0 */ public final class Compiler { @@ -34,51 +36,62 @@ public final class Compiler { } /** - * Low level interface to the JIT compiler. Can return any object, or null - * if no JIT compiler is available. + * Executes an operation according to the specified command object. This + * method is the low-level interface to the JIT compiler. It may return any + * object or {@code null} if no JIT compiler is available. * - * @return Object result of executing command - * @param cmd Object a command for the JIT compiler + * @param cmd + * the command object for the JIT compiler. + * @return the result of executing command or {@code null}. + * @since Android 1.0 */ public static Object command(Object cmd) { return null; } /** - * Compiles the class using the JIT compiler. Returns true if the - * compilation was successful, or false if it failed or there was no JIT - * compiler available. + * Compiles the specified class using the JIT compiler and indicates if + * compilation has been successful. * - * @return boolean indicating compilation success - * @param classToCompile java.lang.Class the class to JIT compile + * @param classToCompile + * java.lang.Class the class to JIT compile + * @return {@code true} if the compilation has been successful; + * {@code false} if it has failed or if there is no JIT compiler + * available. + * @since Android 1.0 */ public static boolean compileClass(Class<?> classToCompile) { return false; } /** - * Compiles all classes whose name matches the argument using the JIT - * compiler. Returns true if the compilation was successful, or false if it - * failed or there was no JIT compiler available. + * Compiles all classes whose name matches the specified name using the JIT + * compiler and indicates if compilation has been successful. * - * @return boolean indicating compilation success - * @param nameRoot String the string to match against class names + * @param nameRoot + * the string to match class names with. + * @return {@code true} if the compilation has been successful; + * {@code false} if it has failed or if there is no JIT compiler + * available. + * @since Android 1.0 */ public static boolean compileClasses(String nameRoot) { return false; } /** - * Disable the JIT compiler + * Disables the JIT compiler. * + * @since Android 1.0 */ public static void disable() { return; } /** - * Disable the JIT compiler + * Enables the JIT compiler. * + * @since Android 1.0 */ public static void enable() { return; diff --git a/luni-kernel/src/main/java/java/lang/Object.java b/luni-kernel/src/main/java/java/lang/Object.java index 70d05da..4fef609 100644 --- a/luni-kernel/src/main/java/java/lang/Object.java +++ b/luni-kernel/src/main/java/java/lang/Object.java @@ -14,33 +14,65 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package java.lang; /** - * This class must be implemented by the vm vendor. Object is the root of the - * java class hierarchy. All non-base types respond to the messages defined in - * this class. + * The root class of the Java class hierarchy. All non-primitive types + * (including arrays) inherit either directly or indirectly from this class. + * <p> + * {@code Object} provides some fundamental methods for accessing the + * {@link Class} of an object, getting its {@link #hashCode()}, or checking + * whether one object {@link #equals(Object)} another. The {@link #toString()} + * method can be used to convert an object reference into a printable string and + * is often overridden in subclasses. + * <p> + * The {@link #wait()} and {@link #notify()} methods provide a foundation for + * synchronization, acquiring and releasing an internal monitor associated with + * each {@code Object}. * + * @since Android 1.0 */ public class Object { /** - * Constructs a new instance of this class. + * Constructs a new instance of {@code Object}. + * + * @since Android 1.0 */ public Object() { } /** - * Returns a new instance of the same class as the receiver, whose slots - * have been filled in with the values in the slots of the receiver. - * <p> - * Classes which wish to support cloning must specify that they implement - * the Cloneable interface, since the implementation checks for this. + * Creates and returns a copy of this {@code Object}. The default + * implementation returns a so-called "shallow" copy: It creates a new + * instance of the same class and then copies the field values (including + * object references) from this instance to the new instance. A "deep" copy, + * in contrast, would also recursively clone nested objects. A subclass that + * needs to implement this kind of cloning should call {@code super.clone()} + * to create the new instance and then create deep copies of the nested, + * mutable objects. * - * @return Object a shallow copy of this object. - * @throws CloneNotSupportedException if the receiver's class does not - * implement the interface Cloneable. + * @return a copy of this object. + * @throws CloneNotSupportedException + * if this object's class does not implement the {@code + * Cloneable} interface. + * @since Android 1.0 */ protected Object clone() throws CloneNotSupportedException { if (!(this instanceof Cloneable)) { @@ -56,77 +88,146 @@ public class Object { private native Object internalClone(Cloneable o); /** - * Compares the argument to the receiver, and returns true if they represent - * the <em>same</em> object using a class specific comparison. The - * implementation in Object returns true only if the argument is the exact - * same object as the receiver (==). + * Compares this instance with the specified object and indicates if they + * are equal. In order to be equal, {@code o} must represent the same object + * as this instance using a class-specific comparison. The general contract + * is that this comparison should be both transitive and reflexive. + * <p> + * The implementation in {@code Object} returns {@code true} only if {@code + * o} is the exact same object as the receiver (using the == operator for + * comparison). Subclasses often implement {@code equals(Object)} so that + * it takes into account the two object's types and states. + * </p> + * <p> + * The general contract for the {@code equals(Object)} and {@link + * #hashCode()} methods is that if {@code equals} returns {@code true} for + * any two objects, then {@code hashCode()} must return the same value for + * these objects. This means that subclasses of {@code Object} usually + * override either both methods or none of them. + * </p> * - * @param o Object the object to compare with this object. - * @return boolean <code>true</code> if the object is the same as this - * object <code>false</code> if it is different from this object. + * @param o + * the object to compare this instance with. + * @return {@code true} if the specified object is equal to this {@code + * Object}; {@code false} otherwise. * @see #hashCode + * @since Android 1.0 */ public boolean equals(Object o) { return this == o; } /** - * Called by the virtual machine when there are no longer any (non-weak) - * references to the receiver. Subclasses can use this facility to guarantee - * that any associated resources are cleaned up before the receiver is - * garbage collected. Uncaught exceptions which are thrown during the - * running of the method cause it to terminate immediately, but are - * otherwise ignored. + * Is called before the object's memory is being reclaimed by the VM. This + * can only happen once the VM has detected, during a run of the garbage + * collector, that the object is no longer reachable by any thread of the + * running application. + * <p> + * The method can be used to free system resources or perform other cleanup + * before the object is garbage collected. The default implementation of the + * method is empty, which is also expected by the VM, but subclasses can + * override {@code finalize()} as required. Uncaught exceptions which are + * thrown during the execution of this method cause it to terminate + * immediately but are otherwise ignored. * <p> - * Note: The virtual machine assumes that the implementation in class Object - * is empty. + * Note that the VM does guarantee that {@code finalize()} is called at most + * once for any object, but it doesn't guarantee when (if at all) {@code + * finalize()} will be called. For example, object B's {@code finalize()} + * can delay the execution of object A's {@code finalize()} method and + * therefore it can delay the reclamation of A's memory. To be safe, use a + * {@link java.lang.ref.ReferenceQueue}, because it provides more control + * over the way the VM deals with references during garbage collection. + * </p> * - * @throws Throwable The virtual machine ignores any exceptions which are - * thrown during finalization. + * @throws Throwable + * any exception which is raised during finalization; these are + * ignored by the virtual machine. + * @since Android 1.0 */ protected void finalize() throws Throwable { } /** - * Returns the unique instance of java.lang.Class which represents the class - * of the receiver. + * Returns the unique instance of {@link Class} which represents this + * object's class. Note that {@code getClass()} is a special case in that it + * actually returns {@code Class<? extends Foo>} where {@code Foo} is the + * erasure of the type of expression {@code getClass()} was called upon. + * <p> + * As an example, the following code actually compiles, although one might + * think it shouldn't: + * <p> + * <pre> + * List<Integer> l = new ArrayList<Integer>(); + * Class<? extends List> c = l.getClass(); + * </pre> * - * @return Class the receiver's Class + * @return this object's {@code Class} instance. + * @since Android 1.0 */ public final native Class<? extends Object> getClass(); /** - * Returns an integer hash code for the receiver. Any two objects which - * answer <code>true</code> when passed to <code>.equals</code> must - * answer the same value for this method. + * Returns an integer hash code for this object. By contract, any two + * objects for which {@code equals(Object)} returns {@code true} must return + * the same hash code value. This means that subclasses of {@code Object} + * usually override both methods or neither method. * - * @return int the receiver's hash. + * @return this object's hash code. * @see #equals + * @since Android 1.0 */ public native int hashCode(); /** - * Causes one thread which is <code>wait</code> ing on the receiver to be - * made ready to run. This does not guarantee that the thread will - * immediately run. The method can only be invoked by a thread which owns - * the receiver's monitor. + * Causes a thread which is waiting on this object's monitor (by means of + * calling one of the {@code wait()} methods) to be woken up. If more than + * one thread is waiting, one of them is chosen at the discretion of the + * virtual machine. The chosen thread will not run immediately. The thread + * that called {@code notify()} has to release the object's monitor first. + * Also, the chosen thread still has to compete against other threads that + * try to synchronize on the same object. + * <p> + * This method can only be invoked by a thread which owns this object's + * monitor. A thread becomes owner of an object's monitor + * </p> + * <ul> + * <li>by executing a synchronized method of that object;</li> + * <li>by executing the body of a {@code synchronized} statement that + * synchronizes on the object;</li> + * <li>by executing a synchronized static method if the object is of type + * {@code Class}.</li> + * </ul> * * @see #notifyAll * @see #wait() * @see #wait(long) * @see #wait(long,int) * @see java.lang.Thread + * @since Android 1.0 */ public final native void notify(); /** - * Causes all threads which are <code>wait</code> ing on the receiver to - * be made ready to run. The threads are scheduled according to their - * priorities as specified in class Thread. Between any two threads of the - * same priority the one which waited first will be the first thread that - * runs after being notified. The method can only be invoked by a thread - * which owns the receiver's monitor. + * Causes all threads which are waiting on this object's monitor (by means + * of calling one of the {@code wait()} methods) to be woken up. The threads + * will not run immediately. The thread that called {@code notify()} has to + * release the object's monitor first. Also, the threads still have to + * compete against other threads that try to synchronize on the same object. + * <p> + * This method can only be invoked by a thread which owns this object's + * monitor. A thread becomes owner of an object's monitor + * </p> + * <ul> + * <li>by executing a synchronized method of that object;</li> + * <li>by executing the body of a {@code synchronized} statement that + * synchronizes on the object;</li> + * <li>by executing a synchronized static method if the object is of type + * {@code Class}.</li> + * </ul> * + * @throws IllegalMonitorStateException + * if the thread calling this method is not the owner of this + * object's monitor. * @see #notify * @see #wait() * @see #wait(long) @@ -136,86 +237,132 @@ public class Object { public final native void notifyAll(); /** - * Returns a string containing a concise, human-readable description of the - * receiver. + * Returns a string containing a concise, human-readable description of this + * object. Subclasses are encouraged to override this method and provide an + * implementation that takes into account the object's type and data. The + * default implementation simply concatenates the class name, the '@' sign + * and a hexadecimal representation of the object's {@link #hashCode()}, + * that is, it is equivalent to the following expression: + * + * <pre> + * getClass().getName() + '@' + Integer.toHexString(hashCode()) + * </pre> * - * @return String a printable representation for the receiver. + * @return a printable representation of this object. + * @since Android 1.0 */ public String toString() { return getClass().getName() + '@' + Integer.toHexString(hashCode()); } /** - * Causes the thread which sent this message to be made not ready to run - * pending some change in the receiver (as indicated by <code>notify</code> - * or <code>notifyAll</code>). The method can only be invoked by a thread - * which owns the receiver's monitor. A waiting thread can be sent - * <code>interrupt()</code> to cause it to prematurely stop waiting, so - * senders of wait should check that the condition they were waiting for has - * been met. + * Causes the calling thread to wait until another thread calls the {@code + * notify()} or {@code notifyAll()} method of this object. This method can + * only be invoked by a thread which owns this object's monitor; see + * {@link #notify()} on how a thread can become the owner of a monitor. * <p> - * When the thread waits, it gives up ownership of the receiver's monitor. - * When it is notified (or interrupted) it re-acquires the monitor before it - * starts running. + * A waiting thread can be sent {@code interrupt()} to cause it to + * prematurely stop waiting, so {@code wait} should be called in a loop to + * check that the condition that has been waited for has been met before + * continuing. + * </p> + * <p> + * While the thread waits, it gives up ownership of this object's monitor. + * When it is notified (or interrupted), it re-acquires the monitor before + * it starts running. + * </p> * - * @throws InterruptedException to interrupt the wait. - * @see Thread#interrupt + * @throws IllegalMonitorStateException + * if the thread calling this method is not the owner of this + * object's monitor. + * @throws InterruptedException + * if another thread interrupts this thread while it is waiting. * @see #notify * @see #notifyAll * @see #wait(long) * @see #wait(long,int) * @see java.lang.Thread + * @since Android 1.0 */ public final void wait() throws InterruptedException { wait(0 ,0); } /** - * Causes the thread which sent this message to be made not ready to run - * either pending some change in the receiver (as indicated by - * <code>notify</code> or <code>notifyAll</code>) or the expiration of - * the timeout. The method can only be invoked by a thread which owns the - * receiver's monitor. A waiting thread can be sent <code>interrupt()</code> - * to cause it to prematurely stop waiting, so senders of wait should check - * that the condition they were waiting for has been met. + * Causes the calling thread to wait until another thread calls the {@code + * notify()} or {@code notifyAll()} method of this object or until the + * specified timeout expires. This method can only be invoked by a thread + * which owns this object's monitor; see {@link #notify()} on how a thread + * can become the owner of a monitor. + * <p> + * A waiting thread can be sent {@code interrupt()} to cause it to + * prematurely stop waiting, so {@code wait} should be called in a loop to + * check that the condition that has been waited for has been met before + * continuing. + * </p> * <p> - * When the thread waits, it gives up ownership of the receiver's monitor. - * When it is notified (or interrupted) it re-acquires the monitor before it - * starts running. + * While the thread waits, it gives up ownership of this object's monitor. + * When it is notified (or interrupted), it re-acquires the monitor before + * it starts running. + * </p> * - * @param time long The maximum time to wait in milliseconds. - * @throws InterruptedException to interrupt the wait. + * @param millis + * the maximum time to wait in milliseconds. + * @throws IllegalArgumentException + * if {@code millis < 0}. + * @throws IllegalMonitorStateException + * if the thread calling this method is not the owner of this + * object's monitor. + * @throws InterruptedException + * if another thread interrupts this thread while it is waiting. * @see #notify * @see #notifyAll * @see #wait() * @see #wait(long,int) * @see java.lang.Thread + * @since Android 1.0 */ - public final void wait(long time) throws InterruptedException { - wait(time, 0); + public final void wait(long millis) throws InterruptedException { + wait(millis, 0); } /** - * Causes the thread which sent this message to be made not ready to run - * either pending some change in the receiver (as indicated by - * <code>notify</code> or <code>notifyAll</code>) or the expiration of - * the timeout. The method can only be invoked by a thread which owns the - * receiver's monitor. A waiting thread can be sent <code>interrupt()</code> - * to cause it to prematurely stop waiting, so senders of wait should check - * that the condition they were waiting for has been met. + * Causes the calling thread to wait until another thread calls the {@code + * notify()} or {@code notifyAll()} method of this object or until the + * specified timeout expires. This method can only be invoked by a thread + * that owns this object's monitor; see {@link #notify()} on how a thread + * can become the owner of a monitor. + * <p> + * A waiting thread can be sent {@code interrupt()} to cause it to + * prematurely stop waiting, so {@code wait} should be called in a loop to + * check that the condition that has been waited for has been met before + * continuing. + * </p> * <p> - * When the thread waits, it gives up ownership of the receiver's monitor. - * When it is notified (or interrupted) it re-acquires the monitor before it - * starts running. + * While the thread waits, it gives up ownership of this object's monitor. + * When it is notified (or interrupted), it re-acquires the monitor before + * it starts running. + * </p> * - * @param time long The maximum time to wait in milliseconds. - * @param frac int The fraction of a mSec to wait, specified in nanoseconds. - * @throws InterruptedException to interrupt the wait. + * @param millis + * the maximum time to wait in milliseconds. + * @param nanos + * the fraction of a millisecond to wait, specified in + * nanoseconds. + * @throws IllegalArgumentException + * if {@code millis < 0}, {@code nanos < 0} or {@code nanos > + * 999999}. + * @throws IllegalMonitorStateException + * if the thread calling this method is not the owner of this + * object's monitor. + * @throws InterruptedException + * if another thread interrupts this thread while it is waiting. * @see #notify * @see #notifyAll * @see #wait() - * @see #wait(long) + * @see #wait(long,int) * @see java.lang.Thread + * @since Android 1.0 */ - public final native void wait(long time, int frac) throws InterruptedException; + public final native void wait(long millis, int nanos) throws InterruptedException; } diff --git a/luni-kernel/src/main/java/java/lang/Package.java b/luni-kernel/src/main/java/java/lang/Package.java index 8c6eb2b..2817404 100644 --- a/luni-kernel/src/main/java/java/lang/Package.java +++ b/luni-kernel/src/main/java/java/lang/Package.java @@ -14,23 +14,39 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package java.lang; +import dalvik.system.VMStack; + import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; import java.net.URL; /** - * This class must be implemented by the vm vendor. - * - * An instance of class Package contains information about a Java package. This - * includes implementation and specification versions. Typically this - * information is retrieved from the manifest. + * Contains information about a Java package. This includes implementation and + * specification versions. Typically this information is retrieved from the + * manifest. * <p> * Packages are managed by class loaders. All classes loaded by the same loader - * from the same package share a Package instance. - * + * from the same package share a {@code Package} instance. + * </p> + * @since Android 1.0 * * @see java.lang.ClassLoader */ @@ -53,12 +69,14 @@ public class Package implements AnnotatedElement { } /** - * Gets the annotation associated with the given annotation type and this - * package. + * Gets the annotation associated with the specified annotation type and + * this package, if present. * - * @return An instance of {@link Annotation} or <code>null</code>. - * @since 1.5 + * @param annotationType + * the annotation type to look for. + * @return an instance of {@link Annotation} or {@code null}. * @see java.lang.reflect.AnnotatedElement#getAnnotation(java.lang.Class) + * @since Android 1.0 */ @SuppressWarnings("unchecked") public <T extends Annotation> T getAnnotation(Class<T> annotationType) { @@ -73,22 +91,22 @@ public class Package implements AnnotatedElement { } /** - * Gets all of the annotations associated with this package. + * Gets all annotations associated with this package, if any. * - * @return An array of {@link Annotation} instances, which may be empty. - * @since 1.5 + * @return an array of {@link Annotation} instances, which may be empty. * @see java.lang.reflect.AnnotatedElement#getAnnotations() + * @since Android 1.0 */ public Annotation[] getAnnotations() { return getDeclaredAnnotations(this, true); } /** - * Gets all of the annotations directly declared on this element. + * Gets all annotations directly declared on this package, if any. * - * @return An array of {@link Annotation} instances, which may be empty. - * @since 1.5 + * @return an array of {@link Annotation} instances, which may be empty. * @see java.lang.reflect.AnnotatedElement#getDeclaredAnnotations() + * @since Android 1.0 */ public Annotation[] getDeclaredAnnotations() { return getDeclaredAnnotations(this, false); @@ -99,147 +117,154 @@ public class Package implements AnnotatedElement { * If no annotations exist, an empty array is returned. * * @param pkg the package of interest - * @param publicOnly reflects whether we want only public annotation or all of them + * @param publicOnly reflects whether we want only public annotation or all + * of them. * @return the list of annotations */ // TODO(Google) Provide proper (native) implementation. - private static native Annotation[] getDeclaredAnnotations(Package pkg, boolean publicOnly); + private static native Annotation[] getDeclaredAnnotations(Package pkg, + boolean publicOnly); /** - * Indicates whether or not the given annotation is present. + * Indicates whether the specified annotation is present. * - * @return A value of <code>true</code> if the annotation is present, - * otherwise <code>false</code>. - * @since 1.5 + * @param annotationType + * the annotation type to look for. + * @return {@code true} if the annotation is present; {@code false} + * otherwise. * @see java.lang.reflect.AnnotatedElement#isAnnotationPresent(java.lang.Class) + * @since Android 1.0 */ - public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) { + public boolean isAnnotationPresent( + Class<? extends Annotation> annotationType) { return getAnnotation(annotationType) != null; } /** - * Return the title of the implementation of this package, or null if this - * is unknown. The format of this string is unspecified. + * Returns the title of the implementation of this package, or {@code null} + * if this is unknown. The format of this string is unspecified. * - * @return The implementation title, or null + * @return the implementation title, may be {@code null}. + * @since Android 1.0 */ public String getImplementationTitle() { return implTitle; } /** - * Return the name of the vendor or organization that provided this - * implementation of the package, or null if this is unknown. The format of - * this string is unspecified. + * Returns the name of the vendor or organization that provides this + * implementation of the package, or {@code null} if this is unknown. The + * format of this string is unspecified. * - * @return The implementation vendor name, or null + * @return the implementation vendor name, may be {@code null}. + * @since Android 1.0 */ public String getImplementationVendor() { return implVendor; } /** - * Return the version of the implementation of this package, or null if this - * is unknown. The format of this string is unspecified. + * Returns the version of the implementation of this package, or {@code + * null} if this is unknown. The format of this string is unspecified. * - * @return The implementation version, or null + * @return the implementation version, may be {@code null}. + * @since Android 1.0 */ public String getImplementationVersion() { return implVersion; } /** - * Return the name of this package in the standard dot notation; for + * Returns the name of this package in the standard dot notation; for * example: "java.lang". * - * @return The name of this package + * @return the name of this package. + * @since Android 1.0 */ public String getName() { return name; } /** - * Attempt to locate the requested package in the caller's class loader. If - * no package information can be located, null is returned. + * Attempts to locate the requested package in the caller's class loader. If + * no package information can be located, {@code null} is returned. * * @param packageName - * The name of the package to find - * @return The package requested, or null - * + * the name of the package to find. + * @return the requested package, or {@code null}. * @see ClassLoader#getPackage(java.lang.String) + * @since Android 1.0 */ public static Package getPackage(String packageName) { - ClassLoader classloader = ClassLoader.callerClassLoader(); + ClassLoader classloader = VMStack.getCallingClassLoader(); return classloader.getPackage(packageName); } /** - * Return all the packages known to the caller's class loader. - * - * @return All the packages known to the caller's classloader + * Returns all the packages known to the caller's class loader. * + * @return all the packages known to the caller's class loader. * @see ClassLoader#getPackages + * @since Android 1.0 */ public static Package[] getPackages() { - ClassLoader classloader = ClassLoader.callerClassLoader(); + ClassLoader classloader = VMStack.getCallingClassLoader(); return classloader.getPackages(); } /** - * Return the title of the specification this package implements, or null if - * this is unknown. + * Returns the title of the specification this package implements, or + * {@code null} if this is unknown. * - * @return The specification title, or null + * @return the specification title, may be {@code null}. + * @since Android 1.0 */ public String getSpecificationTitle() { return specTitle; } /** - * Return the name of the vendor or organization that owns and maintains the - * specification this package implements, or null if this is unknown. + * Returns the name of the vendor or organization that owns and maintains + * the specification this package implements, or {@code null} if this is + * unknown. * - * @return The specification vendor name, or null + * @return the specification vendor name, may be {@code null}. + * @since Android 1.0 */ public String getSpecificationVendor() { return specVendor; } /** - * Return the version of the specification this package implements, or null - * if this is unknown. The version string is a sequence of non-negative - * integers separated by dots; for example: "1.2.3". + * Returns the version of the specification this package implements, or + * {@code null} if this is unknown. The version string is a sequence of + * non-negative integers separated by dots; for example: "1.2.3". * - * @return The specification version string, or null + * @return the specification version string, may be {@code null}. + * @since Android 1.0 */ public String getSpecificationVersion() { return specVersion; } - /** - * Returns an integer hash code for the receiver. Any two objects which - * answer <code>true</code> when passed to <code>equals</code> must - * answer the same value for this method. - * - * @return the receiver's hash - */ @Override public int hashCode() { return name.hashCode(); } /** - * Return true if this package's specification version is compatible with + * Indicates whether this package's specification version is compatible with * the specified version string. Version strings are compared by comparing * each dot separated part of the version as an integer. * * @param version - * The version string to compare against - * @return true if the package versions are compatible, false otherwise - * + * the version string to compare against. + * @return {@code true} if the package versions are compatible; {@code + * false} otherwise. * @throws NumberFormatException - * if the package's version string or the one provided is not in - * the correct format + * if this package's version string or the one provided are not + * in the correct format. + * @since Android 1.0 */ public boolean isCompatibleWith(String version) throws NumberFormatException { @@ -265,32 +290,29 @@ public class Package implements AnnotatedElement { } /** - * Return true if this package is sealed, false otherwise. + * Indicates whether this package is sealed. * - * @return true if this package is sealed, false otherwise + * @return {@code true} if this package is sealed; {@code false} otherwise. + * @since Android 1.0 */ public boolean isSealed() { return sealBase != null; } /** - * Return true if this package is sealed with respect to the specified URL, - * false otherwise. + * Indicates whether this package is sealed with respect to the specified + * URL. * * @param url - * the URL to test - * @return true if this package is sealed, false otherwise + * the URL to check. + * @return {@code true} if this package is sealed with {@code url}; {@code + * false} otherwise + * @since Android 1.0 */ public boolean isSealed(URL url) { return sealBase != null && sealBase.sameFile(url); } - /** - * Returns a string containing a concise, human-readable description of the - * receiver. - * - * @return a printable representation for the receiver. - */ @Override public String toString() { return "package " + name; diff --git a/luni-kernel/src/main/java/java/lang/ProcessManager.java b/luni-kernel/src/main/java/java/lang/ProcessManager.java index 0dfa78d..09ee067 100644 --- a/luni-kernel/src/main/java/java/lang/ProcessManager.java +++ b/luni-kernel/src/main/java/java/lang/ProcessManager.java @@ -324,7 +324,7 @@ final class ProcessManager { super.close(); } finally { synchronized (this) { - if (fd != null) { + if (fd != null && fd.valid()) { try { ProcessManager.close(fd); } finally { @@ -352,7 +352,7 @@ final class ProcessManager { super.close(); } finally { synchronized (this) { - if (fd != null) { + if (fd != null && fd.valid()) { try { ProcessManager.close(fd); } finally { diff --git a/luni-kernel/src/main/java/java/lang/Runtime.java b/luni-kernel/src/main/java/java/lang/Runtime.java index 7681afe..28cc96f 100644 --- a/luni-kernel/src/main/java/java/lang/Runtime.java +++ b/luni-kernel/src/main/java/java/lang/Runtime.java @@ -14,33 +14,52 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package java.lang; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.PipedInputStream; +import java.io.PipedOutputStream; import java.io.Reader; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.io.Writer; -import java.io.OutputStreamWriter; import java.util.StringTokenizer; import java.util.List; import java.util.ArrayList; -// BEGIN android-added import dalvik.system.VMDebug; import dalvik.system.VMStack; -// END android-added /** - * This class, with the exception of the exec() APIs, must be implemented by the - * VM vendor. The exec() APIs must first do any required security checks, and - * then call org.apache.harmony.luni.internal.process.SystemProcess.create(). - * The Runtime interface. + * Allows Java applications to interface with the environment in which they are + * running. Applications can not create an instance of this class, but they can + * get a singleton instance by invoking {@link #getRuntime()}. + * + * @see System + * + * @since Android 1.0 */ public class Runtime { @@ -101,52 +120,77 @@ public class Runtime { } /** - * Execute progArray[0] in a separate platform process The new process - * inherits the environment of the caller. + * Executes the specified command and its arguments in a separate native + * process. The new process inherits the environment of the caller. Calling + * this method is equivalent to calling {@code exec(progArray, null, null)}. * - * @param progArray the array containing the program to execute as well as - * any arguments to the program. - * @throws java.io.IOException if the program cannot be executed - * @throws SecurityException if the current SecurityManager disallows - * program execution + * @param progArray + * the array containing the program to execute as well as any + * arguments to the program. + * @return the new {@code Process} object that represents the native + * process. + * @throws IOException + * if the requested program can not be executed. + * @throws SecurityException + * if the current {@code SecurityManager} disallows program + * execution. * @see SecurityManager#checkExec + * @since Android 1.0 */ public Process exec(String[] progArray) throws java.io.IOException { return exec(progArray, null, null); } /** - * Execute progArray[0] in a separate platform process The new process uses - * the environment provided in envp + * Executes the specified command and its arguments in a separate native + * process. The new process uses the environment provided in {@code envp}. + * Calling this method is equivalent to calling + * {@code exec(progArray, envp, null)}. * - * @param progArray the array containing the program to execute a well as - * any arguments to the program. - * @param envp the array containing the environment to start the new process - * in. - * @throws java.io.IOException if the program cannot be executed - * @throws SecurityException if the current SecurityManager disallows - * program execution + * @param progArray + * the array containing the program to execute as well as any + * arguments to the program. + * @param envp + * the array containing the environment to start the new process + * in. + * @return the new {@code Process} object that represents the native + * process. + * @throws IOException + * if the requested program can not be executed. + * @throws SecurityException + * if the current {@code SecurityManager} disallows program + * execution. * @see SecurityManager#checkExec - */ + * @since Android 1.0 + */ public Process exec(String[] progArray, String[] envp) throws java.io.IOException { return exec(progArray, envp, null); } /** - * Execute progArray[0] in a separate platform process. The new process uses - * the environment provided in envp + * Executes the specified command and its arguments in a separate native + * process. The new process uses the environment provided in {@code envp} + * and the working directory specified by {@code directory}. * - * @param progArray the array containing the program to execute a well as - * any arguments to the program. - * @param envp the array containing the environment to start the new process - * in. - * @param directory the directory in which to execute progArray[0]. If null, - * execute in same directory as parent process. - * @throws java.io.IOException if the program cannot be executed - * @throws SecurityException if the current SecurityManager disallows - * program execution + * @param progArray + * the array containing the program to execute as well as any + * arguments to the program. + * @param envp + * the array containing the environment to start the new process + * in. + * @param directory + * the directory in which to execute the program. If {@code null}, + * execute if in the same directory as the parent process. + * @return the new {@code Process} object that represents the native + * process. + * @throws IOException + * if the requested program can not be executed. + * @throws SecurityException + * if the current {@code SecurityManager} disallows program + * execution. * @see SecurityManager#checkExec - */ + * @since Android 1.0 + */ public Process exec(String[] progArray, String[] envp, File directory) throws java.io.IOException { @@ -182,48 +226,72 @@ public class Runtime { } /** - * Execute program in a separate platform process The new process inherits - * the environment of the caller. + * Executes the specified program in a separate native process. The new + * process inherits the environment of the caller. Calling this method is + * equivalent to calling {@code exec(prog, null, null)}. * - * @param prog the name of the program to execute - * @throws java.io.IOException if the program cannot be executed - * @throws SecurityException if the current SecurityManager disallows - * program execution + * @param prog + * the name of the program to execute. + * @return the new {@code Process} object that represents the native + * process. + * @throws IOException + * if the requested program can not be executed. + * @throws SecurityException + * if the current {@code SecurityManager} disallows program + * execution. * @see SecurityManager#checkExec + * @since Android 1.0 */ public Process exec(String prog) throws java.io.IOException { return exec(prog, null, null); } /** - * Execute prog in a separate platform process The new process uses the - * environment provided in envp + * Executes the specified program in a separate native process. The new + * process uses the environment provided in {@code envp}. Calling this + * method is equivalent to calling {@code exec(prog, envp, null)}. * - * @param prog the name of the program to execute - * @param envp the array containing the environment to start the new process - * in. - * @throws java.io.IOException if the program cannot be executed - * @throws SecurityException if the current SecurityManager disallows - * program execution + * @param prog + * the name of the program to execute. + * @param envp + * the array containing the environment to start the new process + * in. + * @return the new {@code Process} object that represents the native + * process. + * @throws IOException + * if the requested program can not be executed. + * @throws SecurityException + * if the current {@code SecurityManager} disallows program + * execution. * @see SecurityManager#checkExec + * @since Android 1.0 */ public Process exec(String prog, String[] envp) throws java.io.IOException { return exec(prog, envp, null); } /** - * Execute prog in a separate platform process The new process uses the - * environment provided in envp + * Executes the specified program in a separate native process. The new + * process uses the environment provided in {@code envp} and the working + * directory specified by {@code directory}. * - * @param prog the name of the program to execute - * @param envp the array containing the environment to start the new process - * in. - * @param directory the initial directory for the subprocess, or null to use - * the directory of the current process - * @throws java.io.IOException if the program cannot be executed - * @throws SecurityException if the current SecurityManager disallows - * program execution + * @param prog + * the name of the program to execute. + * @param envp + * the array containing the environment to start the new process + * in. + * @param directory + * the directory in which to execute the program. If {@code null}, + * execute if in the same directory as the parent process. + * @return the new {@code Process} object that represents the native + * process. + * @throws IOException + * if the requested program can not be executed. + * @throws SecurityException + * if the current {@code SecurityManager} disallows program + * execution. * @see SecurityManager#checkExec + * @since Android 1.0 */ public Process exec(String prog, String[] envp, File directory) throws java.io.IOException { // Sanity checks @@ -246,14 +314,19 @@ public class Runtime { } /** - * Causes the virtual machine to stop running, and the program to exit. If - * runFinalizersOnExit(true) has been invoked, then all finalizers will be - * run first. + * Causes the virtual machine to stop running and the program to exit. If + * {@link #runFinalizersOnExit(boolean)} has been previously invoked with a + * {@code true} argument, then all all objects will be properly + * garbage-collected and finalized first. * - * @param code the return code. - * @throws SecurityException if the running thread is not allowed to cause - * the vm to exit. + * @param code + * the return code. By convention, non-zero return codes indicate + * abnormal terminations. + * @throws SecurityException + * if the current {@code SecurityManager} does not allow the + * running thread to terminate the virtual machine. * @see SecurityManager#checkExit + * @since Android 1.0 */ public void exit(int code) { // Security checks @@ -266,26 +339,33 @@ public class Runtime { synchronized(this) { if (!shuttingDown) { shuttingDown = true; - + + Thread[] hooks; + synchronized (shutdownHooks) { + // create a copy of the hooks + hooks = new Thread[shutdownHooks.size()]; + shutdownHooks.toArray(hooks); + } + // Start all shutdown hooks concurrently - for (int i = 0; i < shutdownHooks.size(); i++) { - shutdownHooks.get(i).start(); + for (int i = 0; i < hooks.length; i++) { + hooks[i].start(); } - + // Wait for all shutdown hooks to finish - for (int i = 0; i < shutdownHooks.size(); i++) { + for (Thread hook : hooks) { try { - shutdownHooks.get(i).join(); + hook.join(); } catch (InterruptedException ex) { // Ignore, since we are at VM shutdown. } } - + // Ensure finalization on exit, if requested if (finalizeOnExit) { runFinalization(true); } - + // Get out of here finally... nativeExit(code, true); } @@ -296,31 +376,45 @@ public class Runtime { * Returns the amount of free memory resources which are available to the * running program. * + * @return the approximate amount of free memory, measured in bytes. + * @since Android 1.0 */ public native long freeMemory(); /** - * Indicates to the virtual machine that it would be a good time to collect - * available memory. Note that, this is a hint only. + * Indicates to the virtual machine that it would be a good time to run the + * garbage collector. Note that this is a hint only. There is no guarantee + * that the garbage collector will actually be run. * + * @since Android 1.0 */ public native void gc(); /** - * Return the single Runtime instance + * Returns the single {@code Runtime} instance. * + * @return the {@code Runtime} object for the current application. + * @since Android 1.0 */ public static Runtime getRuntime() { return mRuntime; } /** - * Loads and links the library specified by the argument. + * Loads and links the dynamic library that is identified through the + * specified path. This method is similar to {@link #loadLibrary(String)}, + * but it accepts a full path specification whereas {@code loadLibrary} just + * accepts the name of the library to load. * - * @param pathName the absolute (ie: platform dependent) path to the library - * to load - * @throws UnsatisfiedLinkError if the library could not be loaded - * @throws SecurityException if the library was not allowed to be loaded + * @param pathName + * the absolute (platform dependent) path to the library to load. + * @throws UnsatisfiedLinkError + * if the library can not be loaded. + * @throws SecurityException + * if the current {@code SecurityManager} does not allow to load + * the library. + * @see SecurityManager#checkLink + * @since Android 1.0 */ public void load(String pathName) { // Security checks @@ -329,24 +423,36 @@ public class Runtime { smgr.checkLink(pathName); } - // BEGIN android-changed load(pathName, VMStack.getCallingClassLoader()); - // END android-changed } /* * Loads and links a library without security checks. */ void load(String filename, ClassLoader loader) { - nativeLoad(filename, loader); + if (filename == null) { + throw new NullPointerException("library path was null."); + } + if (!nativeLoad(filename, loader)) { + throw new UnsatisfiedLinkError( + "Library " + filename + " not found"); + } } /** - * Loads and links the library specified by the argument. + * Loads and links the library with the specified name. The mapping of the + * specified library name to the full path for loading the library is + * implementation-dependent. * - * @param libName the name of the library to load - * @throws UnsatisfiedLinkError if the library could not be loaded - * @throws SecurityException if the library was not allowed to be loaded + * @param libName + * the name of the library to load. + * @throws UnsatisfiedLinkError + * if the library can not be loaded. + * @throws SecurityException + * if the current {@code SecurityManager} does not allow to load + * the library. + * @see SecurityManager#checkLink + * @since Android 1.0 */ public void loadLibrary(String libName) { // Security checks @@ -354,10 +460,8 @@ public class Runtime { if (smgr != null) { smgr.checkLink(libName); } - - // BEGIN android-changed + loadLibrary(libName, VMStack.getCallingClassLoader()); - // END android-changed } /* @@ -402,35 +506,51 @@ public class Runtime { /** * Provides a hint to the virtual machine that it would be useful to attempt * to perform any outstanding object finalizations. + * + * @since Android 1.0 */ public void runFinalization() { runFinalization(false); } /** - * Ensure that, when the virtual machine is about to exit, all objects are - * finalized. Note that all finalization which occurs when the system is - * exiting is performed after all running threads have been terminated. + * Sets the flag that indicates whether all objects are finalized when the + * virtual machine is about to exit. Note that all finalization which occurs + * when the system is exiting is performed after all running threads have + * been terminated. * - * @param run true means finalize all on exit. + * @param run + * {@code true} to enable finalization on exit, {@code false} to + * disable it. * @deprecated This method is unsafe. + * @since Android 1.0 */ @Deprecated public static void runFinalizersOnExit(boolean run) { - finalizeOnExit = true; + SecurityManager smgr = System.getSecurityManager(); + if (smgr != null) { + smgr.checkExit(0); + } + finalizeOnExit = run; } /** - * Returns the total amount of memory resources which is available to (or in - * use by) the running program. + * Returns the total amount of memory which is available to the running + * program. * + * @return the total amount of memory, measured in bytes. + * @since Android 1.0 */ public native long totalMemory(); /** - * Turns the output of debug information for instructions on or off. + * Switches the output of debug information for instructions on or off. + * For the Android 1.0 reference implementation, this method does nothing. * - * @param enable if true, turn trace on. false turns trace off. + * @param enable + * {@code true} to switch tracing on, {@code false} to switch it + * off. + * @since Android 1.0 */ public void traceInstructions(boolean enable) { // TODO(Google) Provide some implementation for this. @@ -438,12 +558,14 @@ public class Runtime { } /** - * Turns the output of debug information for methods on or off. + * Switches the output of debug information for methods on or off. * - * @param enable if true, turn trace on. false turns trace off. + * @param enable + * {@code true} to switch tracing on, {@code false} to switch it + * off. + * @since Android 1.0 */ public void traceMethodCalls(boolean enable) { - // BEGIN android-changed if (enable != tracingMethods) { if (enable) { VMDebug.startMethodTracing(); @@ -452,86 +574,161 @@ public class Runtime { } tracingMethods = enable; } - // END android-changed } /** - * @deprecated Use {@link InputStreamReader} + * Returns the localized version of the specified input stream. The input + * stream that is returned automatically converts all characters from the + * local character set to Unicode after reading them from the underlying + * stream. + * + * @param stream + * the input stream to localize. + * @return the localized input stream. + * @deprecated Use {@link InputStreamReader}. + * @since Android 1.0 */ @Deprecated public InputStream getLocalizedInputStream(InputStream stream) { - try { - return new ReaderInputStream(new InputStreamReader(stream, "UTF-8")); - } - catch (UnsupportedEncodingException ex) { - // Should never happen, since UTF-8 is mandatory. - throw new RuntimeException(ex); + if (System.getProperty("file.encoding", "UTF-8").equals("UTF-8")) { + return stream; } + return new ReaderInputStream(stream); } /** - * @deprecated Use {@link OutputStreamWriter} - */ + * Returns the localized version of the specified output stream. The output + * stream that is returned automatically converts all characters from + * Unicode to the local character set before writing them to the underlying + * stream. + * + * @param stream + * the output stream to localize. + * @return the localized output stream. + * @deprecated Use {@link OutputStreamWriter}. + * @since Android 1.0 + */ @Deprecated public OutputStream getLocalizedOutputStream(OutputStream stream) { - try { - return new WriterOutputStream(new OutputStreamWriter(stream, "UTF-8")); - } - catch (UnsupportedEncodingException ex) { - // Should never happen, since UTF-8 is mandatory. - throw new RuntimeException(ex); + if (System.getProperty("file.encoding", "UTF-8").equals("UTF-8")) { + return stream; } + return new WriterOutputStream(stream ); } /** - * Registers a new virtual-machine shutdown hook. + * Registers a virtual-machine shutdown hook. A shutdown hook is a + * {@code Thread} that is ready to run, but has not yet been started. All + * registered shutdown hooks will be executed once the virtual machine shuts + * down properly. A proper shutdown happens when either the + * {@link #exit(int)} method is called or the surrounding system decides to + * terminate the application, for example in response to a {@code CTRL-C} or + * a system-wide shutdown. A termination of the virtual machine due to the + * {@link #halt(int)} method, an {@link Error} or a {@code SIGKILL}, in + * contrast, is not considered a proper shutdown. In these cases the + * shutdown hooks will not be run. + * <p> + * Shutdown hooks are run concurrently and in an unspecified order. Hooks + * failing due to an unhandled exception are not a problem, but the stack + * trace might be printed to the console. Once initiated, the whole shutdown + * process can only be terminated by calling {@code halt()}. + * <p> + * If {@link #runFinalizersOnExit(boolean)} has been called with a {@code + * true} argument, garbage collection and finalization will take place after + * all hooks are either finished or have failed. Then the virtual machine + * terminates. + * <p> + * It is recommended that shutdown hooks do not do any time-consuming + * activities, in order to not hold up the shutdown process longer than + * necessary. * - * @param hook the hook (a Thread) to register + * @param hook + * the shutdown hook to register. + * @throws IllegalArgumentException + * if the hook has already been started or if it has already + * been registered. + * @throws IllegalStateException + * if the virtual machine is already shutting down. + * @throws SecurityException + * if a SecurityManager is registered and the calling code + * doesn't have the RuntimePermission("shutdownHooks"). */ public void addShutdownHook(Thread hook) { // Sanity checks if (hook == null) { - throw new NullPointerException("null is not allowed here"); + throw new NullPointerException("Hook may not be null."); } if (shuttingDown) { - throw new IllegalArgumentException("VM already shutting down"); + throw new IllegalStateException("VM already shutting down"); + } + + if (hook.hasBeenStarted) { + throw new IllegalArgumentException("Hook has already been started"); + } + + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(new RuntimePermission("shutdownHooks")); } - if (!shutdownHooks.contains(hook)) { + synchronized (shutdownHooks) { + if (shutdownHooks.contains(hook)) { + throw new IllegalArgumentException("Hook already registered."); + } + shutdownHooks.add(hook); } } /** - * De-registers a previously-registered virtual-machine shutdown hook. + * Unregisters a previously registered virtual machine shutdown hook. * - * @param hook the hook (a Thread) to de-register - * @return true if the hook could be de-registered + * @param hook + * the shutdown hook to remove. + * @return {@code true} if the hook has been removed successfully; {@code + * false} otherwise. + * @throws IllegalStateException + * if the virtual machine is already shutting down. + * @throws SecurityException + * if a SecurityManager is registered and the calling code + * doesn't have the RuntimePermission("shutdownHooks"). */ public boolean removeShutdownHook(Thread hook) { // Sanity checks if (hook == null) { - throw new NullPointerException("null is not allowed here"); + throw new NullPointerException("Hook may not be null."); } if (shuttingDown) { - throw new IllegalArgumentException("VM already shutting down"); + throw new IllegalStateException("VM already shutting down"); + } + + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(new RuntimePermission("shutdownHooks")); + } + + synchronized (shutdownHooks) { + return shutdownHooks.remove(hook); } - - return shutdownHooks.remove(hook); } /** * Causes the virtual machine to stop running, and the program to exit. - * Finalizers will not be run first. Shutdown hooks will not be run. + * Neither shutdown hooks nor finalizers are run before. * * @param code - * the return code. + * the return code. By convention, non-zero return codes indicate + * abnormal terminations. * @throws SecurityException - * if the running thread is not allowed to cause the vm to - * exit. + * if the current {@code SecurityManager} does not allow the + * running thread to terminate the virtual machine. * @see SecurityManager#checkExit + * @see #addShutdownHook(Thread) + * @see #removeShutdownHook(Thread) + * @see #runFinalizersOnExit(boolean) + * @since Android 1.0 */ public void halt(int code) { // Security checks @@ -545,15 +742,23 @@ public class Runtime { } /** - * Return the number of processors, always at least one. + * Returns the number of processors available to the virtual machine. The + * Android reference implementation (currently) always returns 1. + * + * @return the number of available processors, at least 1. + * @since Android 1.0 */ public int availableProcessors() { return 1; } /** - * Return the maximum memory that will be used by the virtual machine, or - * Long.MAX_VALUE. + * Returns the maximum amount of memory that may be used by the virtual + * machine, or {@code Long.MAX_VALUE} if there is no such limit. + * + * @return the maximum amount of memory that the virtual machine will try to + * allocate, measured in bytes. + * @since Android 1.0 */ public native long maxMemory(); @@ -561,23 +766,35 @@ public class Runtime { /* * Internal helper class for creating a localized InputStream. A reader - * wrapped in an InputStream. Bytes are read from characters in big-endian - * fashion. + * wrapped in an InputStream. */ class ReaderInputStream extends InputStream { - + private Reader reader; - private byte[] bytes = new byte[256]; + private Writer writer; + + ByteArrayOutputStream out = new ByteArrayOutputStream(256); + + private byte[] bytes; private int nextByte; private int numBytes; - public ReaderInputStream(Reader reader) { - this.reader = reader; - } + String encoding = System.getProperty("file.encoding", "UTF-8"); + public ReaderInputStream(InputStream stream) { + try { + reader = new InputStreamReader(stream, "UTF-8"); + writer = new OutputStreamWriter(out, encoding); + } catch (UnsupportedEncodingException e) { + // Should never happen, since UTF-8 and platform encoding must be + // supported. + throw new RuntimeException(e); + } + } + @Override public int read() throws IOException { if (nextByte >= numBytes) { @@ -586,17 +803,19 @@ class ReaderInputStream extends InputStream { return (numBytes < 0) ? -1 : bytes[nextByte++]; } - + private void readBuffer() throws IOException { char[] chars = new char[128]; - int numChars = reader.read(chars); - - for (int i = 0; i < chars.length; i++) { - bytes[2 * i ] = (byte)(chars[i] >> 8); - bytes[2 * i + 1] = (byte)(chars[i] & 0xFF); + int read = reader.read(chars); + if (read < 0) { + numBytes = read; + return; } - - numBytes = numChars * 2; + + writer.write(chars, 0, read); + writer.flush(); + bytes = out.toByteArray(); + numBytes = bytes.length; nextByte = 0; } @@ -608,38 +827,63 @@ class ReaderInputStream extends InputStream { * fashion. */ class WriterOutputStream extends OutputStream { - + + private Reader reader; + private Writer writer; - - private byte[] bytes = new byte[256]; - + + private PipedOutputStream out; + + private PipedInputStream pipe; + private int numBytes; - - public WriterOutputStream(Writer writer) { - this.writer = writer; + + private String enc = System.getProperty("file.encoding", "UTF-8"); + + public WriterOutputStream(OutputStream stream) { + try { + // sink + this.writer = new OutputStreamWriter(stream, enc); + + // transcriber + out = new PipedOutputStream(); + pipe = new PipedInputStream(out); + this.reader = new InputStreamReader(pipe, "UTF-8"); + + } catch (UnsupportedEncodingException e) { + // Should never happen, since platform encoding must be supported. + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } } - + @Override public void write(int b) throws IOException { - bytes[numBytes++] = (byte)b; - - if (numBytes >= bytes.length) { - writeBuffer(); + out.write(b); + if( ++numBytes > 256) { + flush(); + numBytes = 0; } } - + @Override public void flush() throws IOException { - writeBuffer(); - writer.flush(); - } - - private void writeBuffer() throws IOException { + out.flush(); char[] chars = new char[128]; - for (int i = 0; i < chars.length; i++) { - chars[i] = (char)(bytes[2 * i] << 8 | bytes[2 * i + 1]); + if (pipe.available() > 0) { + int read = reader.read(chars); + if (read > 0) { + writer.write(chars, 0, read); + } } - - writer.write(chars); - } + writer.flush(); + } + + @Override + public void close() throws IOException { + out.close(); + flush(); + writer.close(); + } } diff --git a/luni-kernel/src/main/java/java/lang/StackTraceElement.java b/luni-kernel/src/main/java/java/lang/StackTraceElement.java index cdfa97f..5394ae9 100644 --- a/luni-kernel/src/main/java/java/lang/StackTraceElement.java +++ b/luni-kernel/src/main/java/java/lang/StackTraceElement.java @@ -20,19 +20,20 @@ package java.lang; import java.io.Serializable; /** - * An implementation of this class is provided, but the documented constructor - * can be used by the VM specific implementation to create instances. - * - * StackTraceElement represents a stack frame. + * A representation of a single stack frame. Arrays of {@code StackTraceElement} + * are stored in {@link Throwable} objects to represent the whole state of the + * call stack at the time a {@code Throwable} gets thrown. * * @see Throwable#getStackTrace() - * @since 1.4 + * @since Android 1.0 */ public final class StackTraceElement implements Serializable { private static final long serialVersionUID = 6992337162326171013L; + // BEGIN android-added private static final int NATIVE_LINE_NUMBER = -2; + // END android-added String declaringClass; @@ -43,22 +44,22 @@ public final class StackTraceElement implements Serializable { int lineNumber; /** - * <p> - * Constructs a <code>StackTraceElement</code> for an execution point. - * </p> + * Constructs a new {@code StackTraceElement} for a specified execution + * point. * - * @param cls The fully qualified name of the class where execution is at. - * @param method The name of the method where execution is at. - * @param file The name of the file where execution is at or - * <code>null</code>. - * @param line The line of the file where execution is at, a negative number - * if unknown or <code>-2</code> if the execution is in a native - * method. - * - * @throws NullPointerException if <code>cls</code> or <code>method</code> - * is <code>null</code>. - * - * @since 1.5 + * @param cls + * the fully qualified name of the class where execution is at. + * @param method + * the name of the method where execution is at. + * @param file + * The name of the file where execution is at or {@code null}. + * @param line + * the line of the file where execution is at, a negative number + * if unknown or {@code -2} if the execution is in a native + * method. + * @throws NullPointerException + * if {@code cls} or {@code method} is {@code null}. + * @since Android 1.0 */ public StackTraceElement(String cls, String method, String file, int line) { super(); @@ -76,15 +77,28 @@ public final class StackTraceElement implements Serializable { * Private, nullary constructor for VM use only. * </p> */ - @SuppressWarnings("unused") private StackTraceElement() { super(); } /** - * Compare this object with the object passed in + * Compares this instance with the specified object and indicates if they + * are equal. In order to be equal, the following conditions must be + * fulfilled: + * <ul> + * <li>{@code obj} must be a stack trace element,</li> + * <li>the method names of this stack trace element and of {@code obj} must + * not be {@code null},</li> + * <li>the class, method and file names as well as the line number of this + * stack trace element and of {@code obj} must be equal.</li> + * </ul> * - * @param obj Object to compare with + * @param obj + * the object to compare this instance with. + * @return {@code true} if the specified object is equal to this + * {@code StackTraceElement}; {@code false} otherwise. + * @see #hashCode + * @since Android 1.0 */ @Override public boolean equals(Object obj) { @@ -125,57 +139,52 @@ public final class StackTraceElement implements Serializable { } /** - * Returns the full name (i.e. including the package) of the class where - * this stack trace element is executing. + * Returns the fully qualified name of the class belonging to this + * {@code StackTraceElement}. * - * @return the fully qualified type name of the class where this stack trace - * element is executing. + * @return the fully qualified type name of the class + * @since Android 1.0 */ public String getClassName() { return (declaringClass == null) ? "<unknown class>" : declaringClass; } /** - * If available, returns the name of the file containing the Java code - * source which was compiled into the class where this stack trace element - * is executing. + * Returns the name of the Java source file containing class belonging to + * this {@code StackTraceElement}. * - * @return if available, the name of the file containing the Java code - * source for the stack trace element's executing class. If no such - * detail is available, a <code>null</code> value is returned. + * @return the name of the file, or {@code null} if this information is not + * available. + * @since Android 1.0 */ public String getFileName() { return fileName; } /** - * If available, returns the line number in the source for the class where - * this stack trace element is executing. + * Returns the line number in the source for the class belonging to this + * {@code StackTraceElement}. * - * @return if available, the line number in the source file for the class - * where this stack trace element is executing. If no such detail is - * available, a number less than <code>0</code>. + * @return the line number, or a negative number if this information is not + * available. + * @since Android 1.0 */ public int getLineNumber() { return lineNumber; } /** - * Returns the name of the method where this stack trace element is - * executing. + * Returns the name of the method belonging to this {@code + * StackTraceElement}. * - * @return the name of the method where this stack trace element is - * executing. + * @return the name of the method, or "<unknown method>" if this information + * is not available. + * @since Android 1.0 */ public String getMethodName() { return (methodName == null) ? "<unknown method>" : methodName; } - /** - * Return this StackTraceElement objects hash code - * - * @return This objects hash code - */ @Override public int hashCode() { /* @@ -191,21 +200,19 @@ public final class StackTraceElement implements Serializable { } /** - * Returns <code>true</code> if the method name returned by - * {@link #getMethodName()} is implemented as a native method. + * Indicates if the method name returned by {@link #getMethodName()} is + * implemented as a native method. * - * @return if the method in which this stack trace element is executing is a - * native method + * @return {@code true} if the method in which this stack trace element is + * executing is a native method; {@code false} otherwise. + * @since Android 1.0 */ public boolean isNativeMethod() { + // BEGIN android-changed return lineNumber == NATIVE_LINE_NUMBER; + // END android-changed } - /** - * Return a String representing this StackTraceElement object - * - * @return String representing this object - */ @Override public String toString() { StringBuilder buf = new StringBuilder(80); diff --git a/luni-kernel/src/main/java/java/lang/System.java b/luni-kernel/src/main/java/java/lang/System.java index 70759c0..b97a75a 100644 --- a/luni-kernel/src/main/java/java/lang/System.java +++ b/luni-kernel/src/main/java/java/lang/System.java @@ -14,6 +14,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package java.lang; @@ -23,10 +38,8 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.PrintStream; - import java.nio.channels.Channel; import java.nio.channels.spi.SelectorProvider; - import java.security.SecurityPermission; import java.util.Collection; import java.util.HashMap; @@ -35,39 +48,48 @@ import java.util.Properties; import java.util.PropertyPermission; import java.util.Set; -// BEGIN android-added import dalvik.system.VMStack; -// END android-added /** - * Class System provides a standard place for programs to find system related - * information. All System API is static. + * Provides access to system-related information and resources including + * standard input and output. Enables clients to dynamically load native + * libraries. All methods of this class are accessed in a static way and the + * class itself can not be instantiated. * + * @see Runtime + * + * @since Android 1.0 */ public final class System { /** - * Default input stream + * Default input stream. + * + * @since Android 1.0 */ public static final InputStream in; /** - * Default output stream + * Default output stream. + * + * @since Android 1.0 */ public static final PrintStream out; /** - * Default error output stream + * Default error output stream. + * + * @since Android 1.0 */ public static final PrintStream err; /** - * The System Properties table + * The System Properties table. */ private static Properties systemProperties; /** - * The System default SecurityManager + * The System default SecurityManager. */ private static SecurityManager securityManager; @@ -76,10 +98,9 @@ public final class System { */ static { /* - * Set up standard in, out, and err. - * - * TODO err and out are String.ConsolePrintStream. All three are - * buffered in Harmony. Check and possibly change this later. + * Set up standard in, out, and err. TODO err and out are + * String.ConsolePrintStream. All three are buffered in Harmony. Check + * and possibly change this later. */ err = new PrintStream(new FileOutputStream(FileDescriptor.err)); out = new PrintStream(new FileOutputStream(FileDescriptor.out)); @@ -87,38 +108,63 @@ public final class System { } /** - * Sets the value of the static slot "in" in the receiver to the passed in - * argument. + * Sets the standard input stream to the given user defined input stream. * - * @param newIn the new value for in. + * @param newIn + * the user defined input stream to set as the standard input + * stream. + * @throws SecurityException + * if a {@link SecurityManager} is installed and its {@code + * checkPermission()} method does not allow the change of the + * stream. + * @since Android 1.0 */ - @SuppressWarnings("unused") public static void setIn(InputStream newIn) { SecurityManager secMgr = System.getSecurityManager(); + if(secMgr != null) { + secMgr.checkPermission(RuntimePermission.permissionToSetIO); + } setFieldImpl("in", "Ljava/io/InputStream;", newIn); } /** - * Sets the value of the static slot "out" in the receiver to the passed in - * argument. + * Sets the standard output stream to the given user defined output stream. * - * @param newOut the new value for out. + * @param newOut + * the user defined output stream to set as the standard output + * stream. + * @throws SecurityException + * if a {@link SecurityManager} is installed and its {@code + * checkPermission()} method does not allow the change of the + * stream. + * @since Android 1.0 */ - @SuppressWarnings("unused") public static void setOut(java.io.PrintStream newOut) { SecurityManager secMgr = System.getSecurityManager(); + if(secMgr != null) { + secMgr.checkPermission(RuntimePermission.permissionToSetIO); + } setFieldImpl("out", "Ljava/io/PrintStream;", newOut); } /** - * Sets the value of the static slot "err" in the receiver to the passed in - * argument. + * Sets the standard error output stream to the given user defined output + * stream. * - * @param newErr the new value for err. + * @param newErr + * the user defined output stream to set as the standard error + * output stream. + * @throws SecurityException + * if a {@link SecurityManager} is installed and its {@code + * checkPermission()} method does not allow the change of the + * stream. + * @since Android 1.0 */ - @SuppressWarnings("unused") public static void setErr(java.io.PrintStream newErr) { SecurityManager secMgr = System.getSecurityManager(); + if(secMgr != null) { + secMgr.checkPermission(RuntimePermission.permissionToSetIO); + } setFieldImpl("err", "Ljava/io/PrintStream;", newErr); } @@ -129,93 +175,120 @@ public final class System { } /** - * Copies the contents of <code>array1</code> starting at offset - * <code>start1</code> into <code>array2</code> starting at offset - * <code>start2</code> for <code>length</code> elements. + * Copies the number of {@code length} elements of the Array {@code src} + * starting at the offset {@code srcPos} into the Array {@code dest} at + * the position {@code destPos}. * - * @param array1 the array to copy out of - * @param start1 the starting index in array1 - * @param array2 the array to copy into - * @param start2 the starting index in array2 - * @param length the number of elements in the array to copy + * @param src + * the source array to copy the content. + * @param srcPos + * the starting index of the content in {@code src}. + * @param dest + * the destination array to copy the data into. + * @param destPos + * the starting index for the copied content in {@code dest}. + * @param length + * the number of elements of the {@code array1} content they have + * to be copied. + * @since Android 1.0 */ - public static native void arraycopy(Object array1, int start1, Object array2, int start2, int length); + public static native void arraycopy(Object src, int srcPos, Object dest, + int destPos, int length); /** - * Returns the current time expressed as milliseconds since the time - * 00:00:00 UTC on January 1, 1970. + * Returns the current system time in milliseconds since January 1, 1970 + * 00:00:00 UTC. This method shouldn't be used for measuring timeouts or + * other elapsed time measurements, as changing the system time can affect + * the results. * - * @return the time in milliseconds. + * @return the local system time in milliseconds. + * @since Android 1.0 */ public static native long currentTimeMillis(); /** - * <p> - * Returns the most precise time measurement in nanoseconds that's - * available. - * </p> + * Returns the current timestamp of the most precise timer available on the + * local system. This timestamp can only be used to measure an elapsed + * period by comparing it against another timestamp. It cannot be used as a + * very exact system time expression. * - * @return The current time in nanoseconds. + * @return the current timestamp in nanoseconds. + * @since Android 1.0 */ public static native long nanoTime(); /** - * Causes the virtual machine to stop running, and the program to exit. If - * runFinalizersOnExit(true) has been invoked, then all finalizers will be - * run first. - * - * @param code the return code. - * - * @throws SecurityException if the running thread is not allowed to cause - * the vm to exit. + * Causes the virtual machine to stop running and the program to exit. If + * {@link #runFinalizersOnExit(boolean)} has been previously invoked with a + * {@code true} argument, then all all objects will be properly + * garbage-collected and finalized first. * + * @param code + * the return code. + * @throws SecurityException + * if the running thread has not enough permission to exit the + * virtual machine. * @see SecurityManager#checkExit + * @since Android 1.0 */ public static void exit(int code) { Runtime.getRuntime().exit(code); } /** - * Indicate to the virtual machine that it would be a good time to collect - * available memory. Note that, this is a hint only. + * Indicates to the virtual machine that it would be a good time to run the + * garbage collector. Note that this is a hint only. There is no guarantee + * that the garbage collector will actually be run. + * + * @since Android 1.0 */ public static void gc() { Runtime.getRuntime().gc(); } /** - * Returns an environment variable. + * Returns the value of the environment variable with the given name {@code + * var}. * - * @param var the name of the environment variable - * @return the value of the specified environment variable + * @param name + * the name of the environment variable. + * @return the value of the specified environment variable or {@code null} + * if no variable exists with the given name. + * @throws SecurityException + * if a {@link SecurityManager} is installed and its {@code + * checkPermission()} method does not allow the querying of + * single environment variables. + * + * @since Android 1.0 */ - public static String getenv(String var) { - if (var == null) { + public static String getenv(String name) { + if (name == null) { throw new NullPointerException(); } SecurityManager secMgr = System.getSecurityManager(); if (secMgr != null) { - secMgr.checkPermission(new RuntimePermission("getenv." + var)); + secMgr.checkPermission(new RuntimePermission("getenv." + name)); } - return getEnvByName(var); + return getEnvByName(name); } /* - * Returns an environment variable. No security checks are - * performed. - * + * Returns an environment variable. No security checks are performed. * @param var the name of the environment variable * @return the value of the specified environment variable */ - private static native String getEnvByName(String var); - + private static native String getEnvByName(String name); + /** - * <p> - * Returns all environment variables. - * </p> + * Returns an unmodifiable map of all available environment variables. * - * @return A Map of all environment variables. + * @return the map representing all environment variables. + * @throws SecurityException + * if a {@link SecurityManager} is installed and its {@code + * checkPermission()} method does not allow the querying of + * all environment variables. + * @since Android 1.0 */ public static Map<String, String> getenv() { SecurityManager secMgr = System.getSecurityManager(); @@ -224,15 +297,15 @@ public final class System { } Map<String, String> map = new HashMap<String, String>(); - + int index = 0; String entry = getEnvByIndex(index++); - while(entry != null) { + while (entry != null) { int pos = entry.indexOf('='); if (pos != -1) { map.put(entry.substring(0, pos), entry.substring(pos + 1)); } - + entry = getEnvByIndex(index++); } @@ -240,26 +313,25 @@ public final class System { } /* - * Returns an environment variable. No security checks are - * performed. The safe way of traversing the environment is - * to start at index zero and count upwards until a null - * pointer is encountered. This marks the end of the Unix - * environment. - * + * Returns an environment variable. No security checks are performed. The + * safe way of traversing the environment is to start at index zero and + * count upwards until a null pointer is encountered. This marks the end of + * the Unix environment. * @param index the index of the environment variable * @return the value of the specified environment variable */ private static native String getEnvByIndex(int index); - + /** - * <p> - * Returns the inherited channel from the system-wide provider. - * </p> + * Returns the inherited channel from the creator of the current virtual + * machine. * - * @return A {@link Channel} or <code>null</code>. + * @return the inherited {@link Channel} or {@code null} if none exists. * @throws IOException + * if an I/O error occurred. * @see SelectorProvider * @see SelectorProvider#inheritedChannel() + * @since Android 1.0 */ public static Channel inheritedChannel() throws IOException { return SelectorProvider.provider().inheritedChannel(); @@ -269,17 +341,19 @@ public final class System { * Returns the system properties. Note that this is not a copy, so that * changes made to the returned Properties object will be reflected in * subsequent calls to getProperty and getProperties. - * <p> - * Security managers should restrict access to this API if possible. * - * @return the system properties + * @return the system properties. + * @throws SecurityException + * if a {@link SecurityManager} is installed and its {@code + * checkPropertiesAccess()} method does not allow the operation. + * @since Android 1.0 */ public static Properties getProperties() { SecurityManager secMgr = System.getSecurityManager(); if (secMgr != null) { secMgr.checkPropertiesAccess(); } - + return internalGetProperties(); } @@ -296,13 +370,13 @@ public final class System { props.postInit(); System.systemProperties = props; } - + return systemProperties; } /** - * Returns the value of a particular system property. Returns null if no - * such property exists, + * Returns the value of a particular system property or {@code null} if no + * such property exists. * <p> * The properties currently provided by the virtual machine are: * @@ -325,22 +399,34 @@ public final class System { * java.home * </pre> * - * @param prop the system property to look up - * @return the value of the specified system property, or null if the - * property doesn't exist + * @param prop + * the name of the system property to look up. + * @return the value of the specified system property or {@code null} if the + * property doesn't exist. + * @throws SecurityException + * if a {@link SecurityManager} is installed and its {@code + * checkPropertyAccess()} method does not allow the operation. + * @since Android 1.0 */ public static String getProperty(String prop) { return getProperty(prop, null); } /** - * Returns the value of a particular system property. If no such property is - * found, returns the defaultValue. + * Returns the value of a particular system property. The {@code + * defaultValue} will be returned if no such property has been found. * - * @param prop the system property to look up - * @param defaultValue return value if system property is not found - * @return the value of the specified system property, or defaultValue if - * the property doesn't exist + * @param prop + * the name of the system property to look up. + * @param defaultValue + * the return value if the system property with the given name + * does not exist. + * @return the value of the specified system property or the {@code + * defaultValue} if the property does not exist. + * @throws SecurityException + * if a {@link SecurityManager} is installed and its {@code + * checkPropertyAccess()} method does not allow the operation. + * @since Android 1.0 */ public static String getProperty(String prop, String defaultValue) { if (prop.length() == 0) { @@ -350,16 +436,23 @@ public final class System { if (secMgr != null) { secMgr.checkPropertyAccess(prop); } - + return internalGetProperties().getProperty(prop, defaultValue); } /** * Sets the value of a particular system property. * - * @param prop the system property to change - * @param value the value to associate with prop - * @return the old value of the property, or null + * @param prop + * the name of the system property to be changed. + * @param value + * the value to associate with the given property {@code prop}. + * @return the old value of the property or {@code null} if the property + * didn't exist. + * @throws SecurityException + * if a security manager exists and write access to the + * specified property is not allowed. + * @since Android 1.0 */ public static String setProperty(String prop, String value) { if (prop.length() == 0) { @@ -369,29 +462,23 @@ public final class System { if (secMgr != null) { secMgr.checkPermission(new PropertyPermission(prop, "write")); } - return (String) internalGetProperties().setProperty(prop, value); + return (String)internalGetProperties().setProperty(prop, value); } /** - * <p> - * Removes the system property for the specified key. - * </p> + * Removes a specific system property. * - * <p> - * Please see the Java SE API documentation for further - * information on this method. - * <p> - * - * @param key the system property to be removed. - * @return previous value or null if no value existed - * - * @throws NullPointerException if the <code>key</code> argument is - * <code>null</code>. - * @throws IllegalArgumentException if the <code>key</code> argument is - * empty. - * @throws SecurityException if a security manager exists and write access - * to the specified property is not allowed. - * @since 1.5 + * @param key + * the name of the system property to be removed. + * @return the property value or {@code null} if the property didn't exist. + * @throws NullPointerException + * if the argument {@code key} is {@code null}. + * @throws IllegalArgumentException + * if the argument {@code key} is empty. + * @throws SecurityException + * if a security manager exists and write access to the + * specified property is not allowed. + * @since Android 1.0 */ public static String clearProperty(String key) { if (key == null) { @@ -405,13 +492,14 @@ public final class System { if (secMgr != null) { secMgr.checkPermission(new PropertyPermission(key, "write")); } - return (String) internalGetProperties().remove(key); + return (String)internalGetProperties().remove(key); } /** * Returns the active security manager. * * @return the system security manager object. + * @since Android 1.0 */ public static SecurityManager getSecurityManager() { return securityManager; @@ -419,63 +507,75 @@ public final class System { /** * Returns an integer hash code for the parameter. The hash code returned is - * the same one that would be returned by java.lang.Object.hashCode(), - * whether or not the object's class has overridden hashCode(). The hash - * code for null is 0. - * - * @param anObject the object - * @return the hash code for the object + * the same one that would be returned by the method {@code + * java.lang.Object.hashCode()}, whether or not the object's class has + * overridden hashCode(). The hash code for {@code null} is {@code 0}. * + * @param anObject + * the object to calculate the hash code. + * @return the hash code for the given object. * @see java.lang.Object#hashCode + * @since Android 1.0 */ public static native int identityHashCode(Object anObject); /** * Loads the specified file as a dynamic library. * - * @param pathName the path of the file to be loaded + * @param pathName + * the path of the file to be loaded. + * @throws SecurityException + * if the library was not allowed to be loaded. + * @since Android 1.0 */ public static void load(String pathName) { SecurityManager smngr = System.getSecurityManager(); if (smngr != null) { smngr.checkLink(pathName); } - // BEGIN android-changed Runtime.getRuntime().load(pathName, VMStack.getCallingClassLoader()); - // END android-changed } /** - * Loads and links the library specified by the argument. - * - * @param libName the name of the library to load + * Loads and links the shared library with the given name {@code libName}. + * The file will be searched in the default directory for shared libraries + * of the local system. * - * @throws UnsatisfiedLinkError if the library could not be loaded - * @throws SecurityException if the library was not allowed to be loaded + * @param libName + * the name of the library to load. + * @throws UnsatisfiedLinkError + * if the library could not be loaded. + * @throws SecurityException + * if the library was not allowed to be loaded. + * @since Android 1.0 */ public static void loadLibrary(String libName) { - // BEGIN android-changed + SecurityManager smngr = System.getSecurityManager(); + if (smngr != null) { + smngr.checkLink(libName); + } Runtime.getRuntime().loadLibrary(libName, VMStack.getCallingClassLoader()); - // END android-changed } /** * Provides a hint to the virtual machine that it would be useful to attempt * to perform any outstanding object finalizations. + * + * @since Android 1.0 */ public static void runFinalization() { Runtime.getRuntime().runFinalization(); } /** - * Ensure that, when the virtual machine is about to exit, all objects are + * Ensures that, when the virtual machine is about to exit, all objects are * finalized. Note that all finalization which occurs when the system is * exiting is performed after all running threads have been terminated. * * @param flag - * true means finalize all on exit. - * - * @deprecated This method is unsafe. + * the flag determines if finalization on exit is enabled. + * @deprecated this method is unsafe. + * @since Android 1.0 */ @SuppressWarnings("deprecation") @Deprecated @@ -484,14 +584,14 @@ public final class System { } /** - * Returns the system properties. Note that the object which is passed in - * not copied, so that subsequent changes made to the object will be - * reflected in calls to getProperty and getProperties. - * <p> - * Security managers should restrict access to this API if possible. + * Sets all system properties. * * @param p - * the property to set + * the new system property. + * @throws SecurityException + * if a {@link SecurityManager} is installed and its {@code + * checkPropertiesAccess()} method does not allow the operation. + * @since Android 1.0 */ public static void setProperties(Properties p) { SecurityManager secMgr = System.getSecurityManager(); @@ -504,35 +604,36 @@ public final class System { /** * Sets the active security manager. Note that once the security manager has - * been set, it can not be changed. Attempts to do so will cause a security - * exception. + * been set, it can not be changed. Attempts to do that will cause a + * security exception. * * @param sm - * the new security manager - * + * the new security manager. * @throws SecurityException * if the security manager has already been set and if its * checkPermission method does not allow to redefine the - * security manager. + * security manager. + * @since Android 1.0 */ public static void setSecurityManager(final SecurityManager sm) { if (securityManager != null) { - securityManager - .checkPermission(new java.lang.RuntimePermission("setSecurityManager")); + securityManager.checkPermission(new java.lang.RuntimePermission("setSecurityManager")); } if (sm != null) { - // before the new manager assumed office, make a pass through + // before the new manager assumed office, make a pass through // the common operations and let it load needed classes (if any), - // to avoid infinite recursion later on + // to avoid infinite recursion later on try { - sm.checkPermission(new SecurityPermission("getProperty.package.access")); - } catch (Exception ignore) {} + sm.checkPermission(new SecurityPermission("getProperty.package.access")); + } catch (Exception ignore) { + } try { - sm.checkPackageAccess("java.lang"); - } catch (Exception ignore) {} + sm.checkPackageAccess("java.lang"); + } catch (Exception ignore) { + } } - + securityManager = sm; } @@ -542,7 +643,8 @@ public final class System { * * @param userLibName * the name of the library to look up. - * @return the platform specific filename for the library + * @return the platform specific filename for the library. + * @since Android 1.0 */ public static native String mapLibraryName(String userLibName); @@ -560,13 +662,13 @@ public final class System { } /** - * Internal class holding the System properties. Needed by the Dalvik VM for - * the two native methods. Must not be a local class, since we don't have a - * System instance. + * Internal class holding the System properties. Needed by the Dalvik VM for the + * two native methods. Must not be a local class, since we don't have a System + * instance. */ class SystemProperties extends Properties { // Dummy, just to make the compiler happy. - + native void preInit(); native void postInit(); @@ -582,13 +684,13 @@ class SystemProperties extends Properties { class SystemEnvironment implements Map { private Map<String, String> map; - + public SystemEnvironment(Map<String, String> map) { this.map = map; } - + public void clear() { - throw new UnsupportedOperationException("Can't modify environment"); + throw new UnsupportedOperationException("Can't modify environment"); } @SuppressWarnings("cast") @@ -631,15 +733,15 @@ class SystemEnvironment implements Map { } public String put(Object key, Object value) { - throw new UnsupportedOperationException("Can't modify environment"); + throw new UnsupportedOperationException("Can't modify environment"); } public void putAll(Map map) { - throw new UnsupportedOperationException("Can't modify environment"); + throw new UnsupportedOperationException("Can't modify environment"); } public String remove(Object key) { - throw new UnsupportedOperationException("Can't modify environment"); + throw new UnsupportedOperationException("Can't modify environment"); } public int size() { @@ -649,5 +751,5 @@ class SystemEnvironment implements Map { public Collection values() { return map.values(); } - + } diff --git a/luni-kernel/src/main/java/java/lang/Thread.java b/luni-kernel/src/main/java/java/lang/Thread.java index b3afc73..d3795f8 100644 --- a/luni-kernel/src/main/java/java/lang/Thread.java +++ b/luni-kernel/src/main/java/java/lang/Thread.java @@ -1,7 +1,3 @@ -// BEGIN android-note -// Reworded description of Thread -// END android-note - /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -18,37 +14,65 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package java.lang; -// BEGIN android-added import dalvik.system.VMStack; -// END android-added +import java.security.AccessController; import java.util.Map; import java.util.HashMap; -// BEGIN android-changed -//import java.util.WeakHashMap; -// END android-changed - -import java.security.AccessController; import org.apache.harmony.security.fortress.SecurityUtils; /** - * A Thread is a unit of concurrent execution. It has its own - * call stack for methods being called and their parameters. Threads in the same - * VM interact and synchronize by the use of shared Objects and monitors - * associated with these objects. Synchronized methods and part of the API in - * Object also allow Threads to cooperate. - * + * A {@code Thread} is a concurrent unit of execution. It has its own call stack + * for methods being invoked, their arguments and local variables. Each virtual + * machine instance has at least one main {@code Thread} running when it is + * started; typically, there are several others for housekeeping. The + * application might decide to launch additional {@code Thread}s for specific + * purposes. + * <p> + * {@code Thread}s in the same VM interact and synchronize by the use of shared + * objects and monitors associated with these objects. Synchronized methods and + * part of the API in {@link Object} also allow {@code Thread}s to cooperate. + * <p> + * There are basically two main ways of having a {@code Thread} execute + * application code. One is providing a new class that extends {@code Thread} + * and overriding its {@link #run()} method. The other is providing a new + * {@code Thread} instance with a {@link Runnable} object during its creation. + * In both cases, the {@link #start()} method must be called to actually execute + * the new {@code Thread}. + * <p> + * Each {@code Thread} has an integer priority that basically determines the + * amount of CPU time the {@code Thread} gets. It can be set using the + * {@link #setPriority(int)} method. A {@code Thread} can also be made a daemon, + * which makes it run in the background. The latter also affects VM termination + * behavior: the VM does not terminate automatically as long as there are + * non-daemon threads running. + * * @see java.lang.Object * @see java.lang.ThreadGroup + * + * @since Android 1.0 */ public class Thread implements Runnable { - // BEGIN android-added - /** Park states */ private static class ParkState { /** park state indicating unparked */ @@ -59,22 +83,16 @@ public class Thread implements Runnable { /** park state indicating parked */ private static final int PARKED = 3; - }; - - // END android-added + } /** * A representation of a thread's state. A given thread may only be in one * state at a time. * - * @since 1.5 + * @since Android 1.0 */ public enum State { /** - * The thread is blocked and waiting for a lock. - */ - BLOCKED, - /** * The thread has been created, but has never been started. */ NEW, @@ -83,37 +101,41 @@ public class Thread implements Runnable { */ RUNNABLE, /** - * The thread has been terminated. + * The thread is blocked and waiting for a lock. */ - TERMINATED, + BLOCKED, + /** + * The thread is waiting. + */ + WAITING, /** * The thread is waiting for a specified amount of time. */ TIMED_WAITING, /** - * The thread is waiting. + * The thread has been terminated. */ - WAITING + TERMINATED } /** - * <p> * The maximum priority value allowed for a thread. - * </p> + * + * @since Android 1.0 */ public final static int MAX_PRIORITY = 10; /** - * <p> * The minimum priority value allowed for a thread. - * </p> + * + * @since Android 1.0 */ public final static int MIN_PRIORITY = 1; /** - * <p> * The normal (default) priority value assigned to threads. - * </p> + * + * @since Android 1.0 */ public final static int NORM_PRIORITY = 5; @@ -133,7 +155,6 @@ public class Thread implements Runnable { */ private long id; -// BEGIN android-chnged /** * Normal thread local values. */ @@ -143,7 +164,6 @@ public class Thread implements Runnable { * Inheritable thread local values. */ ThreadLocal.Values inheritableValues; -// END android-changed /** * Holds the interrupt action for this Thread, if any. @@ -176,46 +196,56 @@ public class Thread implements Runnable { */ boolean hasBeenStarted = false; - // BEGIN android-added /** the park state of the thread */ private int parkState = ParkState.UNPARKED; - // END android-added /** - * Constructs a new Thread with no runnable object and a newly generated - * name. The new Thread will belong to the same ThreadGroup as the Thread - * calling this constructor. + * Constructs a new {@code Thread} with no {@code Runnable} object and a + * newly generated name. The new {@code Thread} will belong to the same + * {@code ThreadGroup} as the {@code Thread} calling this constructor. * * @see java.lang.ThreadGroup + * @see java.lang.Runnable + * + * @since Android 1.0 */ public Thread() { create(null, null, null, 0); } /** - * Constructs a new Thread with a runnable object and a newly generated - * name. The new Thread will belong to the same ThreadGroup as the Thread - * calling this constructor. + * Constructs a new {@code Thread} with a {@code Runnable} object and a + * newly generated name. The new {@code Thread} will belong to the same + * {@code ThreadGroup} as the {@code Thread} calling this constructor. + * + * @param runnable + * a {@code Runnable} whose method <code>run</code> will be + * executed by the new {@code Thread} * - * @param runnable a java.lang.Runnable whose method <code>run</code> will - * be executed by the new Thread * @see java.lang.ThreadGroup * @see java.lang.Runnable + * + * @since Android 1.0 */ public Thread(Runnable runnable) { create(null, runnable, null, 0); } /** - * Constructs a new Thread with a runnable object and name provided. The new - * Thread will belong to the same ThreadGroup as the Thread calling this - * constructor. - * - * @param runnable a java.lang.Runnable whose method <code>run</code> will - * be executed by the new Thread - * @param threadName Name for the Thread being created + * Constructs a new {@code Thread} with a {@code Runnable} object and name + * provided. The new {@code Thread} will belong to the same {@code + * ThreadGroup} as the {@code Thread} calling this constructor. + * + * @param runnable + * a {@code Runnable} whose method <code>run</code> will be + * executed by the new {@code Thread} + * @param threadName + * the name for the {@code Thread} being created + * * @see java.lang.ThreadGroup * @see java.lang.Runnable + * + * @since Android 1.0 */ public Thread(Runnable runnable, String threadName) { if (threadName == null) { @@ -226,13 +256,17 @@ public class Thread implements Runnable { } /** - * Constructs a new Thread with no runnable object and the name provided. - * The new Thread will belong to the same ThreadGroup as the Thread calling - * this constructor. - * - * @param threadName Name for the Thread being created + * Constructs a new {@code Thread} with no {@code Runnable} object and the + * name provided. The new {@code Thread} will belong to the same {@code + * ThreadGroup} as the {@code Thread} calling this constructor. + * + * @param threadName + * the name for the {@code Thread} being created + * * @see java.lang.ThreadGroup * @see java.lang.Runnable + * + * @since Android 1.0 */ public Thread(String threadName) { if (threadName == null) { @@ -243,41 +277,54 @@ public class Thread implements Runnable { } /** - * Constructs a new Thread with a runnable object and a newly generated - * name. The new Thread will belong to the ThreadGroup passed as parameter. - * - * @param group ThreadGroup to which the new Thread will belong - * @param runnable a java.lang.Runnable whose method <code>run</code> will - * be executed by the new Thread - * @throws SecurityException if <code>group.checkAccess()</code> fails - * with a SecurityException - * @throws IllegalThreadStateException if <code>group.destroy()</code> has - * already been done + * Constructs a new {@code Thread} with a {@code Runnable} object and a + * newly generated name. The new {@code Thread} will belong to the {@code + * ThreadGroup} passed as parameter. + * + * @param group + * {@code ThreadGroup} to which the new {@code Thread} will + * belong + * @param runnable + * a {@code Runnable} whose method <code>run</code> will be + * executed by the new {@code Thread} + * @throws SecurityException + * if <code>group.checkAccess()</code> fails with a + * SecurityException + * @throws IllegalThreadStateException + * if <code>group.destroy()</code> has already been done * @see java.lang.ThreadGroup * @see java.lang.Runnable * @see java.lang.SecurityException * @see java.lang.SecurityManager + * + * @since Android 1.0 */ public Thread(ThreadGroup group, Runnable runnable) { create(group, runnable, null, 0); } /** - * Constructs a new Thread with a runnable object, the given name and - * belonging to the ThreadGroup passed as parameter. - * - * @param group ThreadGroup to which the new Thread will belong - * @param runnable a java.lang.Runnable whose method <code>run</code> will - * be executed by the new Thread - * @param threadName Name for the Thread being created - * @throws SecurityException if <code>group.checkAccess()</code> fails - * with a SecurityException - * @throws IllegalThreadStateException if <code>group.destroy()</code> has - * already been done + * Constructs a new {@code Thread} with a {@code Runnable} object, the given + * name and belonging to the {@code ThreadGroup} passed as parameter. + * + * @param group + * ThreadGroup to which the new {@code Thread} will belong + * @param runnable + * a {@code Runnable} whose method <code>run</code> will be + * executed by the new {@code Thread} + * @param threadName + * the name for the {@code Thread} being created + * @throws SecurityException + * if <code>group.checkAccess()</code> fails with a + * SecurityException + * @throws IllegalThreadStateException + * if <code>group.destroy()</code> has already been done * @see java.lang.ThreadGroup * @see java.lang.Runnable * @see java.lang.SecurityException * @see java.lang.SecurityManager + * + * @since Android 1.0 */ public Thread(ThreadGroup group, Runnable runnable, String threadName) { if (threadName == null) { @@ -288,18 +335,24 @@ public class Thread implements Runnable { } /** - * Constructs a new Thread with no runnable object, the given name and - * belonging to the ThreadGroup passed as parameter. - * - * @param group ThreadGroup to which the new Thread will belong - * @param threadName Name for the Thread being created - * @throws SecurityException if <code>group.checkAccess()</code> fails - * with a SecurityException - * @throws IllegalThreadStateException if <code>group.destroy()</code> has - * already been done + * Constructs a new {@code Thread} with no {@code Runnable} object, the + * given name and belonging to the {@code ThreadGroup} passed as parameter. + * + * @param group + * {@code ThreadGroup} to which the new {@code Thread} will belong + * @param threadName + * the name for the {@code Thread} being created + * @throws SecurityException + * if <code>group.checkAccess()</code> fails with a + * SecurityException + * @throws IllegalThreadStateException + * if <code>group.destroy()</code> has already been done * @see java.lang.ThreadGroup + * @see java.lang.Runnable * @see java.lang.SecurityException * @see java.lang.SecurityManager + * + * @since Android 1.0 */ public Thread(ThreadGroup group, String threadName) { if (threadName == null) { @@ -310,22 +363,32 @@ public class Thread implements Runnable { } /** - * Constructs a new Thread with a runnable object, the given name and - * belonging to the ThreadGroup passed as parameter. - * - * @param group ThreadGroup to which the new Thread will belong - * @param runnable a java.lang.Runnable whose method <code>run</code> will - * be executed by the new Thread - * @param threadName Name for the Thread being created - * @param stackSize Platform dependent stack size - * @throws SecurityException if <code>group.checkAccess()</code> fails - * with a SecurityException - * @throws IllegalThreadStateException if <code>group.destroy()</code> has - * already been done + * Constructs a new {@code Thread} with a {@code Runnable} object, the given + * name and belonging to the {@code ThreadGroup} passed as parameter. + * + * @param group + * {@code ThreadGroup} to which the new {@code Thread} will + * belong + * @param runnable + * a {@code Runnable} whose method <code>run</code> will be + * executed by the new {@code Thread} + * @param threadName + * the name for the {@code Thread} being created + * @param stackSize + * a stack size for the new {@code Thread}. This has a highly + * platform-dependent interpretation. It may even be ignored + * completely. + * @throws SecurityException + * if <code>group.checkAccess()</code> fails with a + * SecurityException + * @throws IllegalThreadStateException + * if <code>group.destroy()</code> has already been done * @see java.lang.ThreadGroup * @see java.lang.Runnable * @see java.lang.SecurityException * @see java.lang.SecurityManager + * + * @since Android 1.0 */ public Thread(ThreadGroup group, Runnable runnable, String threadName, long stackSize) { if (threadName == null) { @@ -418,7 +481,6 @@ public class Thread implements Runnable { } } -// BEGIN android-changed Thread currentThread = Thread.currentThread(); if (group == null) { group = currentThread.getThreadGroup(); @@ -451,7 +513,6 @@ public class Thread implements Runnable { inheritableValues = new ThreadLocal.Values(currentThread.inheritableValues); } -// END android-changed // store current AccessControlContext as inherited context for this thread SecurityUtils.putContext(this, AccessController.getContext()); @@ -461,24 +522,31 @@ public class Thread implements Runnable { } /** - * Returns the number of active threads in the running thread's ThreadGroup - * and its subgroups. - * - * @return Number of Threads + * Returns the number of active {@code Thread}s in the running {@code + * Thread}'s group and its subgroups. + * + * @return the number of {@code Thread}s + * + * @since Android 1.0 */ public static int activeCount() { return currentThread().getThreadGroup().activeCount(); } /** - * This method is used for operations that require approval from a - * SecurityManager. If there's none installed, this method is a no-op. If - * there's a SecurityManager installed , - * {@link SecurityManager#checkAccess(Thread)} is called for that - * SecurityManager. - * + * Is used for operations that require approval from a SecurityManager. If + * there's none installed, this method is a no-op. If there's a + * SecurityManager installed, {@link SecurityManager#checkAccess(Thread)} is + * called for that SecurityManager. + * + * @throws SecurityException + * if a SecurityManager is installed and it does not allow + * access to the Thread. + * * @see java.lang.SecurityException * @see java.lang.SecurityManager + * + * @since Android 1.0 */ public final void checkAccess() { // Forwards the message to the SecurityManager (if there's one) passing @@ -492,11 +560,13 @@ public class Thread implements Runnable { /** * Returns the number of stack frames in this thread. - * + * * @return Number of stack frames * @deprecated The results of this call were never well defined. To make - * things worse, it would depend if the Thread was suspended or - * not, and suspend was deprecated too. + * things worse, it would depend on whether the Thread was + * suspended or not, and suspend was deprecated too. + * + * @since Android 1.0 */ @Deprecated public int countStackFrames() { @@ -504,11 +574,11 @@ public class Thread implements Runnable { } /** - * Returns the instance of Thread that corresponds to the running Thread - * which calls this method. + * Returns the Thread of the caller, that is, the current Thread. * - * @return a java.lang.Thread corresponding to the code that called - * <code>currentThread()</code> + * @return the current Thread. + * + * @since Android 1.0 */ public static Thread currentThread() { return VMThread.currentThread(); @@ -518,6 +588,8 @@ public class Thread implements Runnable { * Destroys the receiver without any monitor cleanup. * * @deprecated Not implemented. + * + * @since Android 1.0 */ @Deprecated public void destroy() { @@ -525,8 +597,12 @@ public class Thread implements Runnable { } /** - * Prints a text representation of the stack for this Thread. - * + * Prints to the standard error stream a text representation of the current + * stack for this Thread. + * + * @see Throwable#printStackTrace() + * + * @since Android 1.0 */ public static void dumpStack() { new Throwable("stack dump").printStackTrace(); @@ -534,16 +610,20 @@ public class Thread implements Runnable { /** * Copies an array with all Threads which are in the same ThreadGroup as the - * receiver - and subgroups - into the array <code>threads</code> passed - * as parameter. If the array passed as parameter is too small no exception - * is thrown - the extra elements are simply not copied. - * - * @param threads array into which the Threads will be copied + * receiver - and subgroups - into the array <code>threads</code> passed as + * parameter. If the array passed as parameter is too small no exception is + * thrown - the extra elements are simply not copied. + * + * @param threads + * array into which the Threads will be copied * @return How many Threads were copied over - * @throws SecurityException if the installed SecurityManager fails - * {@link SecurityManager#checkAccess(Thread)} + * @throws SecurityException + * if the installed SecurityManager fails + * {@link SecurityManager#checkAccess(Thread)} * @see java.lang.SecurityException * @see java.lang.SecurityManager + * + * @since Android 1.0 */ public static int enumerate(Thread[] threads) { Thread thread = Thread.currentThread(); @@ -553,15 +633,17 @@ public class Thread implements Runnable { /** * <p> - * Returns the stack traces of all the currently live threads and puts them into - * the given map. + * Returns the stack traces of all the currently live threads and puts them + * into the given map. * </p> - * + * * @return A Map of current Threads to StackTraceElement arrays. - * @throws SecurityException if the current SecurityManager fails the - * {@link SecurityManager#checkPermission(java.security.Permission)} - * call. - * @since 1.5 + * @throws SecurityException + * if the current SecurityManager fails the + * {@link SecurityManager#checkPermission(java.security.Permission)} + * call. + * + * @since Android 1.0 */ public static Map<Thread, StackTraceElement[]> getAllStackTraces() { SecurityManager securityManager = System.getSecurityManager(); @@ -587,45 +669,40 @@ public class Thread implements Runnable { } /** - * Returns the context ClassLoader for the receiver. + * Returns the context ClassLoader for this Thread. * <p> * If the conditions * <ol> - * <li> there is a security manager - * <li> the caller's class loader is not null - * <li> the caller's class loader is not the same as or an - * ancestor of contextClassLoader + * <li>there is a security manager + * <li>the caller's class loader is not null + * <li>the caller's class loader is not the same as the requested + * context class loader and not an ancestor thereof * </ol> * are satisfied, a security check for * <code>RuntimePermission("getClassLoader")</code> is performed first. - * + * * @return ClassLoader The context ClassLoader * @see java.lang.ClassLoader * @see #getContextClassLoader() - * - * @throws SecurityException If aforementioned security check fails. + * + * @throws SecurityException + * if the aforementioned security check fails. + * + * @since Android 1.0 */ public ClassLoader getContextClassLoader() { // First, if the conditions // 1) there is a security manager // 2) the caller's class loader is not null - // 3) the caller's class loader is not the same as or an - // ancestor of contextClassLoader + // 3) the caller's class loader is not the same as the context + // class loader and not an ancestor thereof // are satisfied we should perform a security check. - SecurityManager securityManager = System.getSecurityManager(); - if (securityManager != null) { - ClassLoader callerClassLoader = - VMStack.getCallingClassLoader(); - if (callerClassLoader != null) { - ClassLoader classLoader = contextClassLoader; - while (classLoader != null) { - if (classLoader == callerClassLoader) { - return contextClassLoader; - } - classLoader = classLoader.getParent(); - } - securityManager.checkPermission(new RuntimePermission( - "getClassLoader")); + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + ClassLoader calling = VMStack.getCallingClassLoader(); + + if (calling != null && !calling.isAncestorOf(contextClassLoader)) { + sm.checkPermission(new RuntimePermission("getClassLoader")); } } @@ -633,67 +710,70 @@ public class Thread implements Runnable { } /** - * <p> * Returns the default exception handler that's executed when uncaught * exception terminates a thread. - * </p> * - * @return An {@link UncaughtExceptionHandler} or <code>null</code> if + * @return an {@link UncaughtExceptionHandler} or <code>null</code> if * none exists. - * @since 1.5 + * + * @since Android 1.0 */ public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler() { return defaultUncaughtHandler; } /** - * <p> * Returns the thread's identifier. The ID is a positive <code>long</code> - * generated on thread creation, is unique to the thread and doesn't change - * during the life of the thread; the ID may be reused after the thread has - * been terminated. - * </p> - * - * @return The thread's ID. - * @since 1.5 + * generated on thread creation, is unique to the thread, and doesn't change + * during the lifetime of the thread; the ID may be reused after the thread + * has been terminated. + * + * @return the thread's ID. + * + * @since Android 1.0 */ public long getId() { return id; } /** - * Returns the name of the receiver. + * Returns the name of the Thread. * - * @return the receiver's name (a java.lang.String) + * @return the Thread's name + * + * @since Android 1.0 */ public final String getName() { return name; } /** - * Returns the priority of the receiver. + * Returns the priority of the Thread. * - * @return the receiver's priority (an <code>int</code>) + * @return the Thread's priority * @see Thread#setPriority + * + * @since Android 1.0 */ public final int getPriority() { return priority; } /** - * <p> - * Returns the current stack trace of the thread. - * </p> + * Returns the a stack trace representing the current execution state of + * this Thread. * <p> * The <code>RuntimePermission("getStackTrace")</code> is checked before * returning a result. * </p> - * - * @return An array of StackTraceElements. - * @throws SecurityException if the current SecurityManager fails the - * {@link SecurityManager#checkPermission(java.security.Permission)} - * call. - * @since 1.5 + * + * @return an array of StackTraceElements. + * @throws SecurityException + * if the current SecurityManager fails the + * {@link SecurityManager#checkPermission(java.security.Permission)} + * call. + * + * @since Android 1.0 */ public StackTraceElement[] getStackTrace() { SecurityManager securityManager = System.getSecurityManager(); @@ -706,15 +786,15 @@ public class Thread implements Runnable { } /** - * <p> - * Returns the current state of the thread for monitoring purposes. - * </p> - * - * @return A State value. - * @since 1.5 + * Returns the current state of the Thread. This method is useful for + * monitoring purposes. + * + * @return a {@link State} value. + * + * @since Android 1.0 */ public State getState() { - // TODO Ticket 164: This is ugly and should be implemented better. + // TODO This is ugly and should be implemented better. VMThread vmt = this.vmThread; // Make sure we have a valid reference to an object. If native code @@ -732,12 +812,14 @@ public class Thread implements Runnable { } /** - * Returns the ThreadGroup to which the receiver belongs - * - * @return the receiver's ThreadGroup + * Returns the ThreadGroup to which this Thread belongs. + * + * @return the Thread's ThreadGroup + * + * @since Android 1.0 */ public final ThreadGroup getThreadGroup() { - // TODO Ticket 164: This should actually be done at native termination. + // TODO This should actually be done at native termination. if (getState() == Thread.State.TERMINATED) { return null; } else { @@ -746,14 +828,13 @@ public class Thread implements Runnable { } /** - * <p> * Returns the thread's uncaught exception handler. If not explicitly set, * then the ThreadGroup's handler is returned. If the thread is terminated, * then <code>null</code> is returned. - * </p> - * - * @return An UncaughtExceptionHandler instance or <code>null</code>. - * @since 1.5 + * + * @return an {@link UncaughtExceptionHandler} instance or {@code null}. + * + * @since Android 1.0 */ public UncaughtExceptionHandler getUncaughtExceptionHandler() { if (uncaughtHandler != null) @@ -763,14 +844,37 @@ public class Thread implements Runnable { } /** - * Posts an interrupt request to the receiver. - * - * @throws SecurityException if <code>checkAccess()</code> fails - * with a SecurityException + * Posts an interrupt request to this {@code Thread}. Unless the caller is + * the {@link #currentThread()}, the method {@code checkAccess()} is called + * for the installed {@code SecurityManager}, if any. This may result in a + * {@code SecurityException} being thrown. The further behavior depends on + * the state of this {@code Thread}: + * <ul> + * <li> + * {@code Thread}s blocked in one of {@code Object}'s {@code wait()} methods + * or one of {@code Thread}'s {@code join()} or {@code sleep()} methods will + * be woken up, their interrupt status will be cleared, and they receive an + * {@link InterruptedException}. + * <li> + * {@code Thread}s blocked in an I/O operation of an + * {@link java.nio.channels.InterruptibleChannel} will have their interrupt + * status set and receive an + * {@link java.nio.channels.ClosedByInterruptException}. Also, the channel + * will be closed. + * <li> + * {@code Thread}s blocked in a {@link java.nio.channels.Selector} will have + * their interrupt status set and return immediately. They don't receive an + * exception in this case. + * <ul> + * + * @throws SecurityException + * if <code>checkAccess()</code> fails with a SecurityException * @see java.lang.SecurityException * @see java.lang.SecurityManager * @see Thread#interrupted * @see Thread#isInterrupted + * + * @since Android 1.0 */ public void interrupt() { checkAccess(); @@ -787,14 +891,16 @@ public class Thread implements Runnable { /** * Returns a <code>boolean</code> indicating whether the current Thread ( - * <code>currentThread()</code>) has a pending interrupt request ( - * <code>true</code>) or not (<code>false</code>). It also has the - * side-effect of clearing the flag. - * - * @return a <code>boolean</code> + * <code>currentThread()</code>) has a pending interrupt request (<code> + * true</code>) or not (<code>false</code>). It also has the side-effect of + * clearing the flag. + * + * @return a <code>boolean</code> indicating the interrupt status * @see Thread#currentThread * @see Thread#interrupt * @see Thread#isInterrupted + * + * @since Android 1.0 */ public static boolean interrupted() { return VMThread.interrupted(); @@ -805,9 +911,11 @@ public class Thread implements Runnable { * still runs code (hasn't died yet). Returns <code>false</code> either if * the receiver hasn't been started yet or if it has already started and run * to completion and died. - * - * @return a <code>boolean</code> + * + * @return a <code>boolean</code> indicating the lifeness of the Thread * @see Thread#start + * + * @since Android 1.0 */ public final boolean isAlive() { Thread.State state = getState(); @@ -822,8 +930,10 @@ public class Thread implements Runnable { * When the last non-daemon Thread ends, the whole program ends no matter if * it had daemon Threads still running or not. * - * @return a <code>boolean</code> + * @return a <code>boolean</code> indicating whether the Thread is a daemon * @see Thread#setDaemon + * + * @since Android 1.0 */ public final boolean isDaemon() { return daemon; @@ -834,9 +944,11 @@ public class Thread implements Runnable { * pending interrupt request (<code>true</code>) or not ( * <code>false</code>) * - * @return a <code>boolean</code> + * @return a <code>boolean</code> indicating the interrupt status * @see Thread#interrupt * @see Thread#interrupted + * + * @since Android 1.0 */ public boolean isInterrupted() { VMThread vmt = this.vmThread; @@ -855,6 +967,8 @@ public class Thread implements Runnable { * the receiver while it was in the <code>join()</code> call * @see Object#notifyAll * @see java.lang.ThreadDeath + * + * @since Android 1.0 */ public final void join() throws InterruptedException { join(0, 0); @@ -870,6 +984,8 @@ public class Thread implements Runnable { * the receiver while it was in the <code>join()</code> call * @see Object#notifyAll * @see java.lang.ThreadDeath + * + * @since Android 1.0 */ public final void join(long millis) throws InterruptedException { join(millis, 0); @@ -886,6 +1002,8 @@ public class Thread implements Runnable { * the receiver while it was in the <code>join()</code> call * @see Object#notifyAll * @see java.lang.ThreadDeath + * + * @since Android 1.0 */ public final void join(long millis, int nanos) throws InterruptedException { if (millis < 0 || nanos < 0 || nanos > 999999) { @@ -905,14 +1023,17 @@ public class Thread implements Runnable { } /** - * This is a no-op if the receiver was never suspended, or suspended and - * already resumed. If the receiver is suspended, however, makes it resume - * to the point where it was when it was suspended. - * - * @throws SecurityException if <code>checkAccess()</code> fails with a - * SecurityException + * Resumes a suspended Thread. This is a no-op if the receiver was never + * suspended, or suspended and already resumed. If the receiver is + * suspended, however, makes it resume to the point where it was when it was + * suspended. + * + * @throws SecurityException + * if <code>checkAccess()</code> fails with a SecurityException * @see Thread#suspend() * @deprecated Used with deprecated method {@link Thread#suspend} + * + * @since Android 1.0 */ @Deprecated public final void resume() { @@ -929,6 +1050,8 @@ public class Thread implements Runnable { * holds. If no Runnable is set, does nothing. * * @see Thread#start + * + * @since Android 1.0 */ public void run() { if (target != null) { @@ -948,6 +1071,8 @@ public class Thread implements Runnable { * checkPermission call. * @see java.lang.ClassLoader * @see #getContextClassLoader() + * + * @since Android 1.0 */ public void setContextClassLoader(ClassLoader cl) { SecurityManager securityManager = System.getSecurityManager(); @@ -961,12 +1086,14 @@ public class Thread implements Runnable { /** * Set if the receiver is a daemon Thread or not. This can only be done * before the Thread starts running. - * - * @param isDaemon A boolean indicating if the Thread should be daemon or - * not - * @throws SecurityException if <code>checkAccess()</code> fails with a - * SecurityException + * + * @param isDaemon + * indicates whether the Thread should be daemon or not + * @throws SecurityException + * if <code>checkAccess()</code> fails with a SecurityException * @see Thread#isDaemon + * + * @since Android 1.0 */ public final void setDaemon(boolean isDaemon) { checkAccess(); @@ -982,17 +1109,21 @@ public class Thread implements Runnable { /** * <p> - * Sets the default uncaught exception handler. + * Sets the default uncaught exception handler. This handler is invoked in + * case any Thread dies due to an unhandled exception. * </p> * <p> * The <code>RuntimePermission("setDefaultUncaughtExceptionHandler")</code> * is checked prior to setting the handler. * </p> - * - * @param handler The handler to set or <code>null</code>. - * @throws SecurityException if the current SecurityManager fails the - * checkPermission call. - * @since 1.5 + * + * @param handler + * The handler to set or <code>null</code>. + * @throws SecurityException + * if the current SecurityManager fails the checkPermission + * call. + * + * @since Android 1.0 */ public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler handler) { SecurityManager securityManager = System.getSecurityManager(); @@ -1020,12 +1151,14 @@ public class Thread implements Runnable { } /** - * Sets the name of the receiver. + * Sets the name of the Thread. * - * @param threadName new name for the Thread + * @param threadName the new name for the Thread * @throws SecurityException if <code>checkAccess()</code> fails with a * SecurityException * @see Thread#getName + * + * @since Android 1.0 */ public final void setName(String threadName) { if (threadName == null) { @@ -1043,17 +1176,21 @@ public class Thread implements Runnable { } /** - * Sets the priority of the receiver. Note that the final priority set may - * not be the parameter that was passed - it will depend on the receiver's + * Sets the priority of the Thread. Note that the final priority set may not + * be the parameter that was passed - it will depend on the receiver's * ThreadGroup. The priority cannot be set to be higher than the receiver's * ThreadGroup's maxPriority(). - * - * @param priority new priority for the Thread - * @throws SecurityException if <code>checkAccess()</code> fails with a - * SecurityException - * @throws IllegalArgumentException if the new priority is greater than - * Thread.MAX_PRIORITY or less than Thread.MIN_PRIORITY + * + * @param priority + * new priority for the Thread + * @throws SecurityException + * if <code>checkAccess()</code> fails with a SecurityException + * @throws IllegalArgumentException + * if the new priority is greater than Thread.MAX_PRIORITY or + * less than Thread.MIN_PRIORITY * @see Thread#getPriority + * + * @since Android 1.0 */ public final void setPriority(int priority) { checkAccess(); @@ -1076,13 +1213,16 @@ public class Thread implements Runnable { /** * <p> - * Sets the default uncaught exception handler. + * Sets the uncaught exception handler. This handler is invoked in case this + * Thread dies due to an unhandled exception. * </p> - * - * @param handler The handler to set or <code>null</code>. - * @throws SecurityException if the current SecurityManager fails the - * checkAccess call. - * @since 1.5 + * + * @param handler + * The handler to set or <code>null</code>. + * @throws SecurityException + * if the current SecurityManager fails the checkAccess call. + * + * @since Android 1.0 */ public void setUncaughtExceptionHandler(UncaughtExceptionHandler handler) { checkAccess(); @@ -1091,32 +1231,41 @@ public class Thread implements Runnable { } /** - * Causes the thread which sent this message to sleep an interval of time - * (given in milliseconds). The precision is not guaranteed - the Thread may - * sleep more or less than requested. - * - * @param time The time to sleep in milliseconds. - * @throws InterruptedException if <code>interrupt()</code> was called for - * this Thread while it was sleeping + * Causes the thread which sent this message to sleep for the given interval + * of time (given in milliseconds). The precision is not guaranteed - the + * Thread may sleep more or less than requested. + * + * @param time + * The time to sleep in milliseconds. + * @throws InterruptedException + * if <code>interrupt()</code> was called for this Thread while + * it was sleeping * @see Thread#interrupt() + * + * @since Android 1.0 */ public static void sleep(long time) throws InterruptedException { Thread.sleep(time, 0); } /** - * Causes the thread which sent this message to sleep an interval of time - * (given in milliseconds). The precision is not guaranteed - the Thread may - * sleep more or less than requested. - * - * @param time The time to sleep in milliseconds. - * @param nanos Extra nanosecond precision - * @throws InterruptedException if <code>interrupt()</code> was called for - * this Thread while it was sleeping + * Causes the thread which sent this message to sleep for the given interval + * of time (given in milliseconds and nanoseconds). The precision is not + * guaranteed - the Thread may sleep more or less than requested. + * + * @param millis + * The time to sleep in milliseconds. + * @param nanos + * Extra nanosecond precision + * @throws InterruptedException + * if <code>interrupt()</code> was called for this Thread while + * it was sleeping * @see Thread#interrupt() + * + * @since Android 1.0 */ - public static void sleep(long time, int nanos) throws InterruptedException { - VMThread.sleep(time, nanos); + public static void sleep(long millis, int nanos) throws InterruptedException { + VMThread.sleep(millis, nanos); } /** @@ -1124,9 +1273,11 @@ public class Thread implements Runnable { * the receiver will be called by the receiver Thread itself (and not the * Thread calling <code>start()</code>). * - * @throws IllegalThreadStateException Unspecified in the Java language - * specification + * @throws IllegalThreadStateException if the Thread has been started before + * * @see Thread#run + * + * @since Android 1.0 */ public synchronized void start() { if (hasBeenStarted) { @@ -1145,7 +1296,10 @@ public class Thread implements Runnable { * * @throws SecurityException if <code>checkAccess()</code> fails with a * SecurityException - * @deprecated + * @deprecated because stopping a thread in this manner is unsafe and can + * leave your application and the VM in an unpredictable state. + * + * @since Android 1.0 */ @Deprecated public final void stop() { @@ -1163,7 +1317,10 @@ public class Thread implements Runnable { * SecurityException * @throws NullPointerException if <code>throwable()</code> is * <code>null</code> - * @deprecated + * @deprecated because stopping a thread in this manner is unsafe and can + * leave your application and the VM in an unpredictable state. + * + * @since Android 1.0 */ @Deprecated public final synchronized void stop(Throwable throwable) { @@ -1186,16 +1343,18 @@ public class Thread implements Runnable { } /** - * This is a no-op if the receiver is suspended. If the receiver - * <code>isAlive()</code> however, suspended it until - * <code>resume()</code> is sent to it. Suspend requests are not queued, - * which means that N requests are equivalent to just one - only one resume + * Suspends this Thread. This is a no-op if the receiver is suspended. If + * the receiver <code>isAlive()</code> however, suspended it until <code> + * resume()</code> is sent to it. Suspend requests are not queued, which + * means that N requests are equivalent to just one - only one resume * request is needed in this case. - * - * @throws SecurityException if <code>checkAccess()</code> fails with a - * SecurityException + * + * @throws SecurityException + * if <code>checkAccess()</code> fails with a SecurityException * @see Thread#resume() * @deprecated May cause deadlocks. + * + * @since Android 1.0 */ @Deprecated public final void suspend() { @@ -1209,9 +1368,11 @@ public class Thread implements Runnable { /** * Returns a string containing a concise, human-readable description of the - * receiver. - * + * Thread. It includes the Thread's name, priority, and group name. + * * @return a printable representation for the receiver. + * + * @since Android 1.0 */ @Override public String toString() { @@ -1219,22 +1380,24 @@ public class Thread implements Runnable { } /** - * Causes the thread which sent this message to yield execution to another - * Thread that is ready to run. The actual scheduling is - * implementation-dependent. - * + * Causes the calling Thread to yield execution time to another Thread that + * is ready to run. The actual scheduling is implementation-dependent. + * + * @since Android 1.0 */ public static void yield() { VMThread.yield(); } /** - * Returns whether the current thread has a monitor lock on the specified + * Indicates whether the current Thread has a monitor lock on the specified * object. * * @param object the object to test for the monitor lock - * @return true when the current thread has a monitor lock on the specified - * object + * @return true if the current thread has a monitor lock on the specified + * object; false otherwise + * + * @since Android 1.0 */ public static boolean holdsLock(Object object) { return currentThread().vmThread.holdsLock(object); @@ -1245,6 +1408,8 @@ public class Thread implements Runnable { * terminated by an uncaught exception. Upon such termination, the handler * is notified of the terminating thread and causal exception. If there is * no explicit handler set then the thread's group is the default handler. + * + * @since Android 1.0 */ public static interface UncaughtExceptionHandler { /** @@ -1254,12 +1419,12 @@ public class Thread implements Runnable { * * @param thread the thread that has an uncaught exception * @param ex the exception that was thrown + * + * @since Android 1.0 */ void uncaughtException(Thread thread, Throwable ex); } - // BEGIN android-added - /** * Implementation of <code>unpark()</code>. See {@link LangAccessImpl}. */ @@ -1391,6 +1556,4 @@ public class Thread implements Runnable { } } } - - // END android-added } diff --git a/luni-kernel/src/main/java/java/lang/ThreadGroup.java b/luni-kernel/src/main/java/java/lang/ThreadGroup.java index 4cfaa76..33fa31e 100644 --- a/luni-kernel/src/main/java/java/lang/ThreadGroup.java +++ b/luni-kernel/src/main/java/java/lang/ThreadGroup.java @@ -18,32 +18,39 @@ package java.lang; /** - * An implementation of this class is provided, but the documented constructors - * are used by the vm specific implementation to create the required "system" - * and "main" ThreadGroups. The documented methods are used by java.lang.Thread - * to add and remove Threads from their ThreadGroups. - * - * ThreadGroups are containers of Threads and ThreadGroups, therefore providing - * a tree-like structure to organize Threads. The root ThreadGroup name is - * "system" and it has no parent ThreadGroup. All other ThreadGroups have - * exactly one parent ThreadGroup. All Threads belong to exactly one - * ThreadGroup. + * A {@code ThreadGroup} is a means of organizing {@link Thread}s into a + * hierarchical structure. A {@code ThreadGroup} can contain zero or more + * {@code Thread}s and zero or more other {@code ThreadGroup}s. Each {@code + * Thread} and each {@code ThreadGroup} (except the root group) has a unique + * parent {@code ThreadGroup}. The result is a tree whose inner nodes are + * {@code ThreadGroup}s and whose leaf nodes are {@code Threads}. The unique + * root of the tree is a {@code ThreadGroup} that is created at VM startup and + * has the name "system". The benefit of using {@code ThreadGroup}s, in addition + * to the mere housekeeping aspect, is that all {@code Thread}s in a {@code + * ThreadGroup} can be manipulated together, that is, the {@code ThreadGroup} + * has methods that delegate to all its all {@code Thread}s. * * @see Thread * @see SecurityManager + * + * @since Android 1.0 */ public class ThreadGroup implements Thread.UncaughtExceptionHandler { - // Name of this ThreadGroup. - // VM needs this field name for debugging. + // Name of this ThreadGroup private String name; + // BEGIN android-note + // VM needs this field name for debugging. + // END android-note // Maximum priority for Threads inside this ThreadGroup private int maxPriority = Thread.MAX_PRIORITY; - // The ThreadGroup to which this ThreadGroup belongs. - // VM needs this field name for debugging. + // The ThreadGroup to which this ThreadGroup belongs ThreadGroup parent; + // BEGIN android-note + // VM needs this field name for debugging. + // END android-note int numThreads; @@ -70,21 +77,30 @@ public class ThreadGroup implements Thread.UncaughtExceptionHandler { // Whether this ThreadGroup has already been destroyed or not private boolean isDestroyed; - /* an older required this, but we don't actually use it */ - //private static ThreadGroup root = null; - + // BEGIN android-added /* the VM uses these directly; do not rename */ static ThreadGroup mSystem = new ThreadGroup(); static ThreadGroup mMain = new ThreadGroup(mSystem, "main"); + // END android-added + + // BEGIN android-removed + // /** + // * Used by the JVM to create the "system" ThreadGroup. Construct a + // * ThreadGroup instance, and assign the name "system". + // */ + // private ThreadGroup() { + // name = "system"; + // } + // END android-removed /** * Constructs a new ThreadGroup with the name provided. The new ThreadGroup * will be child of the ThreadGroup to which the - * <code>Thread.currentThread()</code> belongs. + * {@code Thread.currentThread()} belongs. * - * @param name Name for the ThreadGroup being created + * @param name the name for the ThreadGroup being created * - * @throws SecurityException if <code>checkAccess()</code> for the parent + * @throws SecurityException if {@code checkAccess()} for the parent * group fails with a SecurityException * * @see java.lang.Thread#currentThread @@ -96,16 +112,16 @@ public class ThreadGroup implements Thread.UncaughtExceptionHandler { /** * Constructs a new ThreadGroup with the name provided, as child of the - * ThreadGroup <code>parent</code> + * ThreadGroup {@code parent}. * - * @param parent Parent ThreadGroup - * @param name Name for the ThreadGroup being created + * @param parent the parent ThreadGroup + * @param name the name for the ThreadGroup being created * - * @throws NullPointerException if <code>parent</code> is - * <code>null</code> - * @throws SecurityException if <code>checkAccess()</code> for the parent + * @throws NullPointerException if {@code parent} is + * {@code null} + * @throws SecurityException if {@code checkAccess()} for the parent * group fails with a SecurityException - * @throws IllegalThreadStateException if <code>parent</code> has been + * @throws IllegalThreadStateException if {@code parent} has been * destroyed already */ public ThreadGroup(ThreadGroup parent, String name) { @@ -137,13 +153,23 @@ public class ThreadGroup implements Thread.UncaughtExceptionHandler { /** * Returns the number of Threads which are children of the receiver, - * directly or indirectly. + * directly or indirectly and are running. * - * @return Number of children Threads + * @return the number of children Threads */ public int activeCount() { - int count = numThreads; + // BEGIN android-changed + int count = 0; + // Lock the children thread list + synchronized (this.childrenThreadsLock) { + for (int i = 0; i < numThreads; i++) { + if(childrenThreads[i].isAlive()) { + count++; + } + } + } + // END android-changed // Lock this subpart of the tree as we walk synchronized (this.childrenGroupsLock) { for (int i = 0; i < numGroups; i++) { @@ -157,7 +183,7 @@ public class ThreadGroup implements Thread.UncaughtExceptionHandler { * Returns the number of ThreadGroups which are children of the receiver, * directly or indirectly. * - * @return Number of children ThreadGroups + * @return the number of children ThreadGroups */ public int activeGroupCount() { int count = 0; @@ -226,10 +252,12 @@ public class ThreadGroup implements Thread.UncaughtExceptionHandler { } /** - * The definition of this method depends on the deprecated method - * <code>suspend()</code>. The behavior of this call was never specified. + * Does nothing. The definition of this method depends on the deprecated + * method {@link #suspend()}. The exact behavior of this call was never + * specified. * * @param b Used to control low memory implicit suspension + * @return {@code true} (always) * * @deprecated Required deprecated method suspend(). */ @@ -240,29 +268,30 @@ public class ThreadGroup implements Thread.UncaughtExceptionHandler { } /** - * If there is a SecurityManager installed, call <code>checkAccess</code> - * in it passing the receiver as parameter, otherwise do nothing. + * Checks the accessibility of the ThreadGroup from the perspective of the + * caller. If there is a SecurityManager installed, calls + * {@code checkAccess} with the receiver as a parameter, otherwise does + * nothing. */ public final void checkAccess() { // Forwards the message to the SecurityManager (if there's one) passing // the receiver as parameter - -// TODO References to System crash Dalvik due to startup order. Change later. -// SecurityManager currentManager = System.getSecurityManager(); -// if (currentManager != null) { -// currentManager.checkAccess(this); -// } + SecurityManager currentManager = System.getSecurityManager(); + if (currentManager != null) { + currentManager.checkAccess(this); + } } /** * Destroys the receiver and recursively all its subgroups. It is only legal - * to destroy a ThreadGroup that has no Threads. Any daemon ThreadGroup is - * destroyed automatically when it becomes empty (no Threads and no - * ThreadGroups in it). + * to destroy a ThreadGroup that has no Threads in it. Any daemon + * ThreadGroup is destroyed automatically when it becomes empty (no Threads + * and no ThreadGroups in it). * * @throws IllegalThreadStateException if the receiver or any of its - * subgroups has been destroyed already - * @throws SecurityException if <code>this.checkAccess()</code> fails with + * subgroups has been destroyed already or if it still contains + * threads. + * @throws SecurityException if {@code this.checkAccess()} fails with * a SecurityException */ @@ -272,6 +301,18 @@ public class ThreadGroup implements Thread.UncaughtExceptionHandler { // Lock this subpart of the tree as we walk synchronized (this.childrenThreadsLock) { synchronized (this.childrenGroupsLock) { + // BEGIN android-added + if (this.isDestroyed) { + throw new IllegalThreadStateException( + "Thread group was already destroyed: " + + (this.name != null ? this.name : "n/a")); + } + if (this.numThreads > 0) { + throw new IllegalThreadStateException( + "Thread group still contains threads: " + + (this.name != null ? this.name : "n/a")); + } + // END android-added int toDestroy = numGroups; // Call recursively for subgroups for (int i = 0; i < toDestroy; i++) { @@ -314,32 +355,26 @@ public class ThreadGroup implements Thread.UncaughtExceptionHandler { } /** - * Copies an array with all Threads which are children of the receiver - * (directly or indirectly) into the array <code>threads</code> passed as - * parameters. If the array passed as parameter is too small no exception is - * thrown - the extra elements are simply not copied. - * - * @param threads Thread array into which the Threads will be copied - * @return How many Threads were copied over + * Iterates over all active threads in this group (and its sub-groups) and + * stores the threads in the given array. Returns when the array is full or + * no more threads remain, whichever happens first. * + * @param threads the array into which the Threads will be copied + * @return the number of Threads that were copied */ public int enumerate(Thread[] threads) { return enumerate(threads, true); } /** - * Copies an array with all Threads which are children of the receiver into - * the array <code>threads</code> passed as parameter. Children Threads of - * subgroups are recursively copied as well if parameter - * <code>recurse</code> is <code>true</code>. - * - * If the array passed as parameter is too small no exception is thrown - - * the extra elements are simply not copied. + * Iterates over all active threads in this group (and, optionally, its + * sub-groups) and stores the threads in the given array. Returns when the + * array is full or no more threads remain, whichever happens first. * - * @param threads array into which the Threads will be copied - * @param recurse Indicates whether Threads in subgroups should be - * recursively copied as well or not - * @return How many Threads were copied over + * @param threads the array into which the Threads will be copied + * @param recurse indicates whether Threads in subgroups should be + * recursively copied as well + * @return the number of Threads that were copied * */ public int enumerate(Thread[] threads, boolean recurse) { @@ -347,13 +382,12 @@ public class ThreadGroup implements Thread.UncaughtExceptionHandler { } /** - * Copies an array with all ThreadGroups which are children of the receiver - * (directly or indirectly) into the array <code>groups</code> passed as - * parameters. If the array passed as parameter is too small no exception is - * thrown - the extra elements are simply not copied. + * Iterates over all thread groups in this group (and its sub-groups) and + * and stores the groups in the given array. Returns when the array is full + * or no more groups remain, whichever happens first. * - * @param groups array into which the ThreadGroups will be copied - * @return How many ThreadGroups were copied over + * @param groups the array into which the ThreadGroups will be copied + * @return the number of ThreadGroups that were copied * */ public int enumerate(ThreadGroup[] groups) { @@ -361,18 +395,14 @@ public class ThreadGroup implements Thread.UncaughtExceptionHandler { } /** - * Copies an array with all ThreadGroups which are children of the receiver - * into the array <code>groups</code> passed as parameter. Children - * ThreadGroups of subgroups are recursively copied as well if parameter - * <code>recurse</code> is <code>true</code>. - * - * If the array passed as parameter is too small no exception is thrown - - * the extra elements are simply not copied. + * Iterates over all thread groups in this group (and, optionally, its + * sub-groups) and and stores the groups in the given array. Returns when + * the array is full or no more groups remain, whichever happens first. * - * @param groups array into which the ThreadGroups will be copied - * @param recurse Indicates whether ThreadGroups in subgroups should be + * @param groups the array into which the ThreadGroups will be copied + * @param recurse indicates whether ThreadGroups in subgroups should be * recursively copied as well or not - * @return How many ThreadGroups were copied over + * @return the number of ThreadGroups that were copied * */ public int enumerate(ThreadGroup[] groups, boolean recurse) { @@ -432,7 +462,7 @@ public class ThreadGroup implements Thread.UncaughtExceptionHandler { /** * Returns the maximum allowed priority for a Thread in the receiver. * - * @return the maximum priority (an <code>int</code>) + * @return the maximum priority * * @see #setMaxPriority */ @@ -443,15 +473,15 @@ public class ThreadGroup implements Thread.UncaughtExceptionHandler { /** * Returns the name of the receiver. * - * @return the receiver's name (a java.lang.String) + * @return the receiver's name */ public final String getName() { return name; } /** - * Returns the receiver's parent ThreadGroup. It can be null if the receiver - * is the the root ThreadGroup. + * Returns the receiver's parent ThreadGroup. It can be {@code null} if the + * receiver is the the root ThreadGroup. * * @return the parent ThreadGroup * @@ -467,7 +497,7 @@ public class ThreadGroup implements Thread.UncaughtExceptionHandler { * Interrupts every Thread in the receiver and recursively in all its * subgroups. * - * @throws SecurityException if <code>this.checkAccess()</code> fails with + * @throws SecurityException if {@code this.checkAccess()} fails with * a SecurityException * * @see Thread#interrupt @@ -489,9 +519,9 @@ public class ThreadGroup implements Thread.UncaughtExceptionHandler { } /** - * Returns true if the receiver is a daemon ThreadGroup, false otherwise. + * Checks whether the receiver is a daemon ThreadGroup. * - * @return if the receiver is a daemon ThreadGroup + * @return true if (and only if) the receiver is a daemon ThreadGroup * * @see #setDaemon * @see #destroy @@ -501,9 +531,9 @@ public class ThreadGroup implements Thread.UncaughtExceptionHandler { } /** - * Returns true if the receiver has been destroyed already, false otherwise. + * Checks whether the receiver has already been destroyed. * - * @return if the receiver has been destroyed already + * @return true if (and only if) the receiver has already been destroyed * * @see #destroy */ @@ -512,7 +542,7 @@ public class ThreadGroup implements Thread.UncaughtExceptionHandler { } /** - * Outputs to <code>System.out</code> a text representation of the + * Outputs to {@code System.out} a text representation of the * hierarchy of Threads and ThreadGroups in the receiver (and recursively). * Proper indentation is done to suggest the nesting of groups inside groups * and threads inside groups. @@ -524,7 +554,7 @@ public class ThreadGroup implements Thread.UncaughtExceptionHandler { } /* - * Outputs to <code>System.out</code>a text representation of the + * Outputs to {@code System.out}a text representation of the * hierarchy of Threads and ThreadGroups in the receiver (and recursively). * The indentation will be four spaces per level of nesting. * @@ -557,12 +587,12 @@ public class ThreadGroup implements Thread.UncaughtExceptionHandler { } /** - * Returns true if the receiver is a direct or indirect parent group of - * ThreadGroup <code>g</code>, false otherwise. + * Checks whether the receiver is a direct or indirect parent group of a + * given ThreadGroup. * - * @param g ThreadGroup to test + * @param g the potential child ThreadGroup * - * @return if the receiver is parent of the ThreadGroup passed as parameter + * @return true if (and only if) the receiver is parent of {@code g} * */ public final boolean parentOf(ThreadGroup g) { @@ -588,7 +618,9 @@ public class ThreadGroup implements Thread.UncaughtExceptionHandler { for (int i = 0; i < numThreads; i++) { if (childrenThreads[i].equals(thread)) { numThreads--; - System.arraycopy(childrenThreads, i + 1, childrenThreads, i, numThreads - i); + System + .arraycopy(childrenThreads, i + 1, childrenThreads, i, numThreads + - i); childrenThreads[numThreads] = null; break; } @@ -600,7 +632,7 @@ public class ThreadGroup implements Thread.UncaughtExceptionHandler { /** * Removes an immediate subgroup from the receiver. * - * @param g Threadgroup to remove from the receiver + * @param g ThreadGroup to remove from the receiver * * @see #add(Thread) * @see #add(ThreadGroup) @@ -623,7 +655,7 @@ public class ThreadGroup implements Thread.UncaughtExceptionHandler { * Resumes every Thread in the receiver and recursively in all its * subgroups. * - * @throws SecurityException if <code>this.checkAccess()</code> fails with + * @throws SecurityException if {@code this.checkAccess()} fails with * a SecurityException * * @see Thread#resume @@ -653,9 +685,10 @@ public class ThreadGroup implements Thread.UncaughtExceptionHandler { * Configures the receiver to be a daemon ThreadGroup or not. Daemon * ThreadGroups are automatically destroyed when they become empty. * - * @param isDaemon new value defining if receiver should be daemon or not + * @param isDaemon the new value defining if receiver should be daemon or + * not * - * @throws SecurityException if <code>checkAccess()</code> for the parent + * @throws SecurityException if {@code checkAccess()} for the parent * group fails with a SecurityException * * @see #isDaemon @@ -676,7 +709,7 @@ public class ThreadGroup implements Thread.UncaughtExceptionHandler { * * @param newMax the new maximum priority to be set * - * @throws SecurityException if <code>checkAccess()</code> fails with a + * @throws SecurityException if {@code checkAccess()} fails with a * SecurityException * @throws IllegalArgumentException if the new priority is greater than * Thread.MAX_PRIORITY or less than Thread.MIN_PRIORITY @@ -705,8 +738,8 @@ public class ThreadGroup implements Thread.UncaughtExceptionHandler { /** * Sets the parent ThreadGroup of the receiver, and adds the receiver to the - * parent's collection of immediate children (if <code>parent</code> is - * not <code>null</code>). + * parent's collection of immediate children (if {@code parent} is + * not {@code null}). * * @param parent The parent ThreadGroup, or null if the receiver is to be * the root ThreadGroup @@ -724,7 +757,7 @@ public class ThreadGroup implements Thread.UncaughtExceptionHandler { /** * Stops every Thread in the receiver and recursively in all its subgroups. * - * @throws SecurityException if <code>this.checkAccess()</code> fails with + * @throws SecurityException if {@code this.checkAccess()} fails with * a SecurityException * * @see Thread#stop() @@ -774,7 +807,7 @@ public class ThreadGroup implements Thread.UncaughtExceptionHandler { * Suspends every Thread in the receiver and recursively in all its * subgroups. * - * @throws SecurityException if <code>this.checkAccess()</code> fails with + * @throws SecurityException if {@code this.checkAccess()} fails with * a SecurityException * * @see Thread#suspend @@ -823,7 +856,7 @@ public class ThreadGroup implements Thread.UncaughtExceptionHandler { * Returns a string containing a concise, human-readable description of the * receiver. * - * @return a printable representation for the receiver. + * @return a printable representation of the ThreadGroup */ @Override public String toString() { @@ -832,20 +865,21 @@ public class ThreadGroup implements Thread.UncaughtExceptionHandler { } /** - * Any uncaught exception in any Thread has to be forwarded (by the VM) to - * the Thread's ThreadGroup by sending this message (uncaughtException). - * This allows users to define custom ThreadGroup classes and custom - * behavior for when a Thread has an uncaughtException or when it does - * (ThreadDeath). + * Handles uncaught exceptions. Any uncaught exception in any Thread + * is forwarded (by the VM) to the Thread's ThreadGroup by sending this + * message (uncaughtException). This allows users to define custom + * ThreadGroup classes and custom behavior for when a Thread has an + * uncaughtException or when it does (ThreadDeath). * - * @param t Thread with an uncaught exception - * @param e The uncaught exception itself + * @param t the Thread that terminated with an uncaught exception + * @param e the uncaught exception itself * * @see Thread#stop() * @see Thread#stop(Throwable) * @see ThreadDeath */ public void uncaughtException(Thread t, Throwable e) { + // BEGIN android-changed if (parent != null) { parent.uncaughtException(t, e); } else if (Thread.getDefaultUncaughtExceptionHandler() != null) { @@ -855,8 +889,10 @@ public class ThreadGroup implements Thread.UncaughtExceptionHandler { // No parent group, has to be 'system' Thread Group e.printStackTrace(System.err); } + // END android-changed } - + + // BEGIN android-added /** * Non-standard method for adding a thread to a group, required by Dalvik. * @@ -886,5 +922,5 @@ public class ThreadGroup implements Thread.UncaughtExceptionHandler { void removeThread(Thread thread) throws IllegalThreadStateException { remove(thread); } - + // END android-added } diff --git a/luni-kernel/src/main/java/java/lang/Throwable.java b/luni-kernel/src/main/java/java/lang/Throwable.java index 91de145..12b4e9b 100644 --- a/luni-kernel/src/main/java/java/lang/Throwable.java +++ b/luni-kernel/src/main/java/java/lang/Throwable.java @@ -23,21 +23,28 @@ import java.io.PrintStream; import java.io.PrintWriter; /** - * This class is the superclass of all classes which can be thrown by - * the virtual machine. The two direct subclasses represent - * recoverable exceptions (Exception) and unrecoverable errors - * (Error). This class provides common methods for accessing a string - * message which provides extra information about the circumstances in - * which the Throwable was created, and for filling in a stack trace - * (i.e., a record of the call stack at a particular point in time) - * which can be printed later. + * The superclass of all classes which can be thrown by the virtual machine. The + * two direct subclasses are recoverable exceptions ({@code Exception}) and + * unrecoverable errors ({@code Error}). This class provides common methods for + * accessing a string message which provides extra information about the + * circumstances in which the {@code Throwable} was created (basically an error + * message in most cases), and for saving a stack trace (that is, a record of + * the call stack at a particular point in time) which can be printed later. + * <p> + * A {@code Throwable} can also include a cause, which is a nested {@code + * Throwable} that represents the original problem that led to this {@code + * Throwable}. It is often used for wrapping various types of errors into a + * common {@code Throwable} without losing the detailed original error + * information. When printing the stack trace, the trace of the cause is + * included. * * @see Error * @see Exception * @see RuntimeException + * + * @since Android 1.0 */ public class Throwable implements java.io.Serializable { - private static final long serialVersionUID = -3042686055658047285L; /** @@ -49,12 +56,14 @@ public class Throwable implements java.io.Serializable { * The cause of this Throwable. Null when there is no cause. */ private Throwable cause = this; - + + // BEGIN android-added /** * An intermediate representation of the stack trace. This field may * be accessed by the VM; do not rename. */ private volatile Object stackState; + // END android-added /** * A fully-expanded representation of the stack trace. @@ -62,7 +71,9 @@ public class Throwable implements java.io.Serializable { private StackTraceElement[] stackTrace; /** - * Constructs a new instance of this class with its stack trace filled in. + * Constructs a new {@code Throwable} that includes the current stack trace. + * + * @since Android 1.0 */ public Throwable() { super(); @@ -70,10 +81,12 @@ public class Throwable implements java.io.Serializable { } /** - * Constructs a new instance of this class with its stack trace and message - * filled in. + * Constructs a new {@code Throwable} with the current stack trace and the + * specified detail message. * - * @param detailMessage String The detail message for the exception. + * @param detailMessage + * the detail message for this {@code Throwable}. + * @since Android 1.0 */ public Throwable(String detailMessage) { this(); @@ -81,11 +94,14 @@ public class Throwable implements java.io.Serializable { } /** - * Constructs a new instance of this class with its stack trace, - * message, and cause filled in. + * Constructs a new {@code Throwable} with the current stack trace, the + * specified detail message and the specified cause. * - * @param detailMessage String The detail message for the exception. - * @param throwable The cause of this Throwable + * @param detailMessage + * the detail message for this {@code Throwable}. + * @param throwable + * the cause of this {@code Throwable}. + * @since Android 1.0 */ public Throwable(String detailMessage, Throwable throwable) { this(); @@ -94,10 +110,12 @@ public class Throwable implements java.io.Serializable { } /** - * Constructs a new instance of this class with its stack trace and cause - * filled in. + * Constructs a new {@code Throwable} with the current stack trace and the + * specified cause. * - * @param throwable The cause of this Throwable + * @param throwable + * the cause of this {@code Throwable}. + * @since Android 1.0 */ public Throwable(Throwable throwable) { this(); @@ -105,14 +123,15 @@ public class Throwable implements java.io.Serializable { cause = throwable; } + // BEGIN android-changed /** - * Records in the receiver a stack trace from the point where this - * message was sent. The method is public so that code which - * catches a throwable and then <em>re-throws</em> it can adjust - * the stack trace to represent the location where the exception - * was re-thrown. + * Records the stack trace from the point where this method has been called + * to this {@code Throwable}. The method is public so that code which + * catches a {@code Throwable} and then re-throws it can adjust the stack + * trace to represent the location where the exception was re-thrown. * - * @return the receiver + * @return this {@code Throwable} instance. + * @since Android 1.0 */ public Throwable fillInStackTrace() { // Fill in the intermediate representation @@ -121,46 +140,65 @@ public class Throwable implements java.io.Serializable { stackTrace = null; return this; } + // END android-changed /** - * Returns the extra information message which was provided when - * the throwable was created. If no message was provided at - * creation time, then return null. + * Returns the extra information message which was provided when this + * {@code Throwable} was created. Returns {@code null} if no message was + * provided at creation time. * - * @return String The receiver's message. + * @return this {@code Throwable}'s detail message. + * @since Android 1.0 */ public String getMessage() { return detailMessage; } /** - * Returns the extra information message which was provided when - * the throwable was created. If no message was provided at - * creation time, then return null. Subclasses may override this - * method to return localized text for the message. + * Returns the extra information message which was provided when this + * {@code Throwable} was created. Returns {@code null} if no message was + * provided at creation time. Subclasses may override this method to return + * localized text for the message. The Android reference implementation + * returns the unlocalized detail message. * - * @return String The receiver's message. + * @return this {@code Throwable}'s localized detail message. + * @since Android 1.0 */ public String getLocalizedMessage() { return getMessage(); } /** - * Returns an array of StackTraceElement. Each StackTraceElement - * represents a entry on the stack. + * Returns the array of stack trace elements of this {@code Throwable}. Each + * {@code StackTraceElement} represents an entry in the call stack. The + * element at position 0 is the top of the stack, that is, the stack frame + * where this {@code Throwable} is thrown. * - * @return an array of StackTraceElement representing the stack + * @return a copy of the array of {@code StackTraceElement}s representing + * the call stack. Changes in the array obtained from this call will + * not change the call stack stored in this {@code Throwable}. + * @see #printStackTrace() + * @since Android 1.0 */ public StackTraceElement[] getStackTrace() { return getInternalStackTrace().clone(); } /** - * Sets the array of StackTraceElements. Each StackTraceElement - * represents a entry on the stack. A copy of this array will be - * returned by getStackTrace() and printed by printStackTrace(). + * Sets the array of stack trace elements. Each {@code StackTraceElement} + * represents an entry in the call stack. A copy of the specified array is + * stored in this {@code Throwable}. will be returned by {@code + * getStackTrace()} and printed by {@code printStackTrace()}. * - * @param trace The array of StackTraceElement + * @param trace + * the new array of {@code StackTraceElement}s. A copy of the + * array is stored in this {@code Throwable}, so subsequent + * changes to {@code trace} will not change the call stack stored + * in this {@code Throwable}. + * @throws NullPointerException + * if any element in {@code trace} is {@code null}. + * @see #printStackTrace() + * @since Android 1.0 */ public void setStackTrace(StackTraceElement[] trace) { StackTraceElement[] newTrace = trace.clone(); @@ -173,8 +211,10 @@ public class Throwable implements java.io.Serializable { } /** - * Outputs a printable representation of the receiver's stack - * trace on the System.err stream. + * Writes a printable representation of this {@code Throwable}'s stack trace + * to the {@code System.err} stream. + * + * @since Android 1.0 */ public void printStackTrace() { printStackTrace(System.err); @@ -212,17 +252,23 @@ public class Throwable implements java.io.Serializable { */ private StackTraceElement[] getInternalStackTrace() { if (stackTrace == null) { + // BEGIN android-changed stackTrace = nativeGetStackTrace(stackState); stackState = null; // Clean up intermediate representation + // END android-changed } return stackTrace; } /** - * Outputs a printable representation of the receiver's stack - * trace on the PrintStream specified by the argument. + * Writes a printable representation of this {@code Throwable}'s stack trace + * to the specified print stream. If the {@code Throwable} contains a + * {@link #getCause() cause}, the method will be invoked recursively for + * the nested {@code Throwable}. * - * @param err PrintStream The stream to write the stack trace on. + * @param err + * the stream to write the stack trace on. + * @since Android 1.0 */ public void printStackTrace(PrintStream err) { err.println(toString()); @@ -238,8 +284,7 @@ public class Throwable implements java.io.Serializable { while (throwable != null) { err.print("Caused by: "); err.println(throwable); - StackTraceElement[] currentStack = - throwable.getInternalStackTrace(); + StackTraceElement[] currentStack = throwable.getInternalStackTrace(); int duplicates = countDuplicates(currentStack, parentStack); for (int i = 0; i < currentStack.length - duplicates; i++) { err.println("\tat " + currentStack[i]); @@ -253,10 +298,14 @@ public class Throwable implements java.io.Serializable { } /** - * Outputs a printable representation of the receiver's stack - * trace on the PrintWriter specified by the argument. + * Writes a printable representation of this {@code Throwable}'s stack trace + * to the specified print writer. If the {@code Throwable} contains a + * {@link #getCause() cause}, the method will be invoked recursively for the + * nested {@code Throwable}. * - * @param err PrintWriter The writer to write the stack trace on. + * @param err + * the writer to write the stack trace on. + * @since Android 1.0 */ public void printStackTrace(PrintWriter err) { err.println(toString()); @@ -272,8 +321,7 @@ public class Throwable implements java.io.Serializable { while (throwable != null) { err.print("Caused by: "); err.println(throwable); - StackTraceElement[] currentStack = - throwable.getInternalStackTrace(); + StackTraceElement[] currentStack = throwable.getInternalStackTrace(); int duplicates = countDuplicates(currentStack, parentStack); for (int i = 0; i < currentStack.length - duplicates; i++) { err.println("\tat " + currentStack[i]); @@ -286,12 +334,6 @@ public class Throwable implements java.io.Serializable { } } - /** - * Returns a string containing a concise, human-readable description of the - * receiver. - * - * @return String a printable representation for the receiver. - */ @Override public String toString() { String msg = getLocalizedMessage(); @@ -299,22 +341,27 @@ public class Throwable implements java.io.Serializable { if (msg == null) { return name; } - return new StringBuffer(name.length() + 2 + msg.length()). - append(name).append(": ").append(msg).toString(); + return new StringBuffer(name.length() + 2 + msg.length()).append(name).append(": ") + .append(msg).toString(); } /** - * Initialize the cause of the receiver. The cause cannot be reassigned. - * - * @param throwable The cause of this Throwable - * - * @exception IllegalArgumentException when the cause is the receiver - * @exception IllegalStateException when the cause has already been - * initialized + * Initializes the cause of this {@code Throwable}. The cause can only be + * initialized once. * - * @return the receiver. + * @param throwable + * the cause of this {@code Throwable}. + * @return this {@code Throwable} instance. + * @throws IllegalArgumentException + * if {@code Throwable} is this object. + * @throws IllegalStateException + * if the cause has already been initialized. + * @since Android 1.0 */ public Throwable initCause(Throwable throwable) { + // BEGIN android-note + // removed synchronized modifier + // END android-note if (cause == this) { if (throwable != this) { cause = throwable; @@ -326,9 +373,11 @@ public class Throwable implements java.io.Serializable { } /** - * Returns the cause of this Throwable, or null if there is no cause. + * Returns the cause of this {@code Throwable}, or {@code null} if there is + * no cause. * - * @return Throwable The receiver's cause. + * @return Throwable this {@code Throwable}'s cause. + * @since Android 1.0 */ public Throwable getCause() { if (cause == this) { @@ -343,6 +392,7 @@ public class Throwable implements java.io.Serializable { s.defaultWriteObject(); } + // BEGIN android-added /* * Creates a compact, VM-specific collection of goodies, suitable for * storing in the "stackState" field, based on the current thread's @@ -355,5 +405,6 @@ public class Throwable implements java.io.Serializable { * in "stackState". */ native private static StackTraceElement[] nativeGetStackTrace(Object stackState); + // END android-added } diff --git a/luni-kernel/src/main/java/java/lang/ref/PhantomReference.java b/luni-kernel/src/main/java/java/lang/ref/PhantomReference.java index 7a7930f..c33ab6e 100644 --- a/luni-kernel/src/main/java/java/lang/ref/PhantomReference.java +++ b/luni-kernel/src/main/java/java/lang/ref/PhantomReference.java @@ -14,6 +14,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package java.lang.ref; @@ -47,7 +62,6 @@ public class PhantomReference<T> extends Reference<T> { */ public PhantomReference(T r, ReferenceQueue<? super T> q) { super(); - referent = r; queue = q; } @@ -64,5 +78,4 @@ public class PhantomReference<T> extends Reference<T> { public T get() { return null; } - } diff --git a/luni-kernel/src/main/java/java/lang/ref/Reference.java b/luni-kernel/src/main/java/java/lang/ref/Reference.java index 7840caa..ca7290b 100644 --- a/luni-kernel/src/main/java/java/lang/ref/Reference.java +++ b/luni-kernel/src/main/java/java/lang/ref/Reference.java @@ -14,6 +14,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package java.lang.ref; diff --git a/luni-kernel/src/main/java/java/lang/ref/SoftReference.java b/luni-kernel/src/main/java/java/lang/ref/SoftReference.java index 7236f20..19253f1 100644 --- a/luni-kernel/src/main/java/java/lang/ref/SoftReference.java +++ b/luni-kernel/src/main/java/java/lang/ref/SoftReference.java @@ -14,6 +14,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package java.lang.ref; @@ -83,7 +98,6 @@ public class SoftReference<T> extends Reference<T> { */ public SoftReference(T r) { super(); - referent = r; } @@ -100,7 +114,6 @@ public class SoftReference<T> extends Reference<T> { */ public SoftReference(T r, ReferenceQueue<? super T> q) { super(); - referent = r; queue = q; } @@ -119,5 +132,4 @@ public class SoftReference<T> extends Reference<T> { // return super.get(); // } // END android-removed - } diff --git a/luni-kernel/src/main/java/java/lang/ref/WeakReference.java b/luni-kernel/src/main/java/java/lang/ref/WeakReference.java index 5a8a19b..813cc89 100644 --- a/luni-kernel/src/main/java/java/lang/ref/WeakReference.java +++ b/luni-kernel/src/main/java/java/lang/ref/WeakReference.java @@ -14,6 +14,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package java.lang.ref; @@ -82,7 +97,6 @@ public class WeakReference<T> extends Reference<T> { */ public WeakReference(T r) { super(); - referent = r; } @@ -99,9 +113,7 @@ public class WeakReference<T> extends Reference<T> { */ public WeakReference(T r, ReferenceQueue<? super T> q) { super(); - referent = r; queue = q; } - } diff --git a/luni-kernel/src/main/java/java/lang/reflect/AccessibleObject.java b/luni-kernel/src/main/java/java/lang/reflect/AccessibleObject.java index 349d313..4381877 100644 --- a/luni-kernel/src/main/java/java/lang/reflect/AccessibleObject.java +++ b/luni-kernel/src/main/java/java/lang/reflect/AccessibleObject.java @@ -14,41 +14,55 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package java.lang.reflect; -// BEGIN android-added -import org.apache.harmony.kernel.vm.StringUtils; -import org.apache.harmony.kernel.vm.ReflectionAccess; -// END android-added - import java.lang.annotation.Annotation; import java.util.Hashtable; +import org.apache.harmony.kernel.vm.StringUtils; +import org.apache.harmony.kernel.vm.ReflectionAccess; + /** - * This class must be implemented by the VM vendor. This class is the superclass - * of all member reflect classes (Field, Constructor, Method). AccessibleObject - * provides the ability to toggle access checks for these objects. By default - * accessing a member (for example, setting a field or invoking a method) checks - * the validity of the access (for example, invoking a private method from - * outside the defining class is prohibited) and throws IllegalAccessException - * if the operation is not permitted. If the accessible flag is set to true, - * these checks are omitted. This allows privileged applications such as Java - * Object Serialization, inspectors, and debuggers to have complete access to + * {@code AccessibleObject} is the superclass of all member reflection classes + * (Field, Constructor, Method). AccessibleObject provides the ability to toggle + * a flag controlling access checks for these objects. By default, accessing a + * member (for example, setting a field or invoking a method) checks the + * validity of the access (for example, invoking a private method from outside + * the defining class is prohibited) and throws IllegalAccessException if the + * operation is not permitted. If the accessible flag is set to true, these + * checks are omitted. This allows privileged code, such as Java object + * serialization, object inspectors, and debuggers to have complete access to * objects. * * @see Field * @see Constructor * @see Method * @see ReflectPermission + * * @since 1.2 + * @since Android 1.0 */ public class AccessibleObject implements AnnotatedElement { // If true, object is accessible, bypassing normal security checks boolean flag = false; - // BEGIN android-added /** * one dimensional array */ @@ -63,7 +77,6 @@ public class AccessibleObject implements AnnotatedElement { * three dimensional array */ private static final String DIMENSION_3 = "[][][]"; - // END android-added // Holds a mapping from Java type names to native type codes. static Hashtable<String, String> trans; @@ -80,19 +93,26 @@ public class AccessibleObject implements AnnotatedElement { trans.put("void", "V"); trans.put("boolean", "Z"); } - + /** * Attempts to set the value of the accessible flag for all the objects in * the array provided. Only one security check is performed. Setting this - * flag to false will enable access checks, setting to true will disable - * them. If there is a security manager, checkPermission is called with a - * ReflectPermission("suppressAccessChecks"). + * flag to {@code false} will enable access checks, setting to {@code true} + * will disable them. If there is a security manager, checkPermission is + * called with a {@code ReflectPermission("suppressAccessChecks")}. * - * @param objects the accessible objects - * @param flag the new value for the accessible flag + * @param objects + * the accessible objects + * @param flag + * the new value for the accessible flag + * + * @throws SecurityException + * if the request is denied + * * @see #setAccessible(boolean) * @see ReflectPermission - * @throws SecurityException if the request is denied + * + * @since Android 1.0 */ public static void setAccessible(AccessibleObject[] objects, boolean flag) throws SecurityException { @@ -109,18 +129,24 @@ public class AccessibleObject implements AnnotatedElement { } /** - * AccessibleObject constructor. AccessibleObjects can only be created by - * the Virtual Machine. + * Constructs a new {@code AccessibleObject} instance. {@code + * AccessibleObject} instances can only be constructed by the virtual + * machine. + * + * @since Android 1.0 */ protected AccessibleObject() { super(); } /** - * Returns the value of the accessible flag. This is false if access checks - * are performed, true if they are skipped. + * Indicates whether this object is accessible without security checks being + * performed. Returns the accessible flag. * - * @return the value of the accessible flag + * @return {@code true} if this object is accessible without security + * checks, {@code false} otherwise + * + * @since Android 1.0 */ public boolean isAccessible() { return flag; @@ -128,13 +154,19 @@ public class AccessibleObject implements AnnotatedElement { /** * Attempts to set the value of the accessible flag. Setting this flag to - * false will enable access checks, setting to true will disable them. If - * there is a security manager, checkPermission is called with a - * ReflectPermission("suppressAccessChecks"). + * {@code false} will enable access checks, setting to {@code true} will + * disable them. If there is a security manager, checkPermission is called + * with a {@code ReflectPermission("suppressAccessChecks")}. * - * @param flag the new value for the accessible flag + * @param flag + * the new value for the accessible flag + * + * @throws SecurityException + * if the request is denied + * * @see ReflectPermission - * @throws SecurityException if the request is denied + * + * @since Android 1.0 */ public void setAccessible(boolean flag) throws SecurityException { SecurityManager smgr = System.getSecurityManager(); @@ -145,24 +177,16 @@ public class AccessibleObject implements AnnotatedElement { this.flag = flag; } - // BEGIN android-added /** * Sets the accessible flag on this instance without doing any checks. * - * @param flag the new value for the accessible flag + * @param flag + * the new value for the accessible flag */ /*package*/ void setAccessibleNoCheck(boolean flag) { this.flag = flag; } - // END android-added - /** - * Queries whether a given Annotation is present on the AccessibleObject. - * - * @param annotationType The type of Annotation to look for. - * - * @return true if and only if the given Annotation is present. - */ public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) { return getAnnotation(annotationType) != null; } @@ -178,13 +202,15 @@ public class AccessibleObject implements AnnotatedElement { /* slow, but works for all sub-classes */ public <T extends Annotation> T getAnnotation(Class<T> annotationType) { + if (annotationType == null) { + throw new NullPointerException(); + } Annotation[] annos = getAnnotations(); for (int i = annos.length-1; i >= 0; --i) { if (annos[i].annotationType() == annotationType) { return (T) annos[i]; } } - return null; } @@ -192,10 +218,11 @@ public class AccessibleObject implements AnnotatedElement { * Returns the signature for a class. This is the kind of signature used * internally by the JVM, with one-character codes representing the basic * types. It is not suitable for printing. + * + * @param clazz + * the class for which a signature is required * - * @param clazz The class for which a signature is required. - * - * @return The signature as a string. + * @return The signature as a string */ String getSignature(Class<?> clazz) { String result = ""; @@ -216,12 +243,13 @@ public class AccessibleObject implements AnnotatedElement { /** * Returns a printable String consisting of the canonical names of the * classes contained in an array. The form is that used in parameter and - * exception lists, that is, the class or type names are separated by - * commas. - * - * @param types The array of classes. + * exception lists, that is, the class or type names are separated by + * commas. + * + * @param types + * the array of classes * - * @return The String of names. + * @return The String of names */ String toString(Class<?>[] types) { StringBuilder result = new StringBuilder(); @@ -237,11 +265,9 @@ public class AccessibleObject implements AnnotatedElement { return result.toString(); } - // BEGIN android-changed - /** - * Gets the Signature attribute for this instance. Returns - * <code>null</code> if not found. + * Gets the Signature attribute for this instance. Returns {@code null} + * if not found. */ /*package*/ String getSignatureAttribute() { /* @@ -273,12 +299,9 @@ public class AccessibleObject implements AnnotatedElement { */ private static native Object[] getClassSignatureAnnotation(Class clazz); - // END android-changed - - // BEGIN android-added /** * Gets the unique instance of {@link ReflectionAccessImpl}. - * + * * @return non-null; the unique instance */ static /*package*/ ReflectionAccess getReflectionAccess() { @@ -289,9 +312,10 @@ public class AccessibleObject implements AnnotatedElement { /** * Appends the specified class name to the buffer. The class may represent * a simple type, a reference type or an array type. - * + * * @param sb buffer * @param obj the class which name should be appended to the buffer + * * @throws NullPointerException if any of the arguments is null */ void appendArrayType(StringBuilder sb, Class<?> obj) { @@ -328,9 +352,10 @@ public class AccessibleObject implements AnnotatedElement { * Appends names of the specified array classes to the buffer. The array * elements may represent a simple type, a reference type or an array type. * Output format: java.lang.Object[], java.io.File, void - * + * * @param sb buffer * @param objs array of classes to print the names + * * @throws NullPointerException if any of the arguments is null */ void appendArrayType(StringBuilder sb, Class[] objs) { @@ -347,9 +372,10 @@ public class AccessibleObject implements AnnotatedElement { * Appends names of the specified array classes to the buffer. The array * elements may represent a simple type, a reference type or an array type. * Output format: java.lang.Object[], java.io.File, void - * + * * @param sb buffer * @param objs array of classes to print the names + * * @throws NullPointerException if any of the arguments is null */ void appendArrayGenericType(StringBuilder sb, Type[] objs) { @@ -364,9 +390,10 @@ public class AccessibleObject implements AnnotatedElement { /** * Appends the generic type representation to the buffer. - * + * * @param sb buffer * @param obj the generic type which representation should be appended to the buffer + * * @throws NullPointerException if any of the arguments is null */ void appendGenericType(StringBuilder sb, Type obj) { @@ -421,9 +448,10 @@ public class AccessibleObject implements AnnotatedElement { * In case if the specified array element represents an array type its * internal will be appended to the buffer. * Output format: [Ljava.lang.Object;, java.io.File, void - * + * * @param sb buffer * @param objs array of classes to print the names + * * @throws NullPointerException if any of the arguments is null */ void appendSimpleType(StringBuilder sb, Class<?>[] objs) { @@ -435,5 +463,4 @@ public class AccessibleObject implements AnnotatedElement { } } } - // END android-added } diff --git a/luni-kernel/src/main/java/java/lang/reflect/Array.java b/luni-kernel/src/main/java/java/lang/reflect/Array.java index ca37d90..d633e69 100644 --- a/luni-kernel/src/main/java/java/lang/reflect/Array.java +++ b/luni-kernel/src/main/java/java/lang/reflect/Array.java @@ -14,38 +14,58 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package java.lang.reflect; /** - * This class provides methods to dynamically create and access arrays. + * This class provides static methods to create and access arrays dynamically. + * + * @since Android 1.0 */ public final class Array { /** - * Prevent this class from being instantiated + * Prevent this class from being instantiated. */ private Array(){ //do nothing } /** - * Return the element of the array at the specified index. This reproduces - * the effect of <code>array[index]</code> If the array component is a - * base type, the result is automatically wrapped. - * + * Returns the element of the array at the specified index. This reproduces + * the effect of {@code array[index]}. If the array component is a primitive + * type, the result is automatically wrapped. + * * @param array * the array * @param index * the index + * * @return the requested element, possibly wrapped - * @throws java.lang.NullPointerException - * if the array is null - * @throws java.lang.IllegalArgumentException - * if the array is not an array - * @throws java.lang.ArrayIndexOutOfBoundsException - * if the index is out of bounds -- negative or greater than - * or equal to the array length + * + * @throws NullPointerException + * if the array is null + * @throws IllegalArgumentException + * if {@code array} is not an array + * @throws ArrayIndexOutOfBoundsException + * if {@code index < 0 || index >= array.length} + * + * @since Android 1.0 */ public static Object get(Object array, int index) throws IllegalArgumentException, ArrayIndexOutOfBoundsException { @@ -83,23 +103,26 @@ public final class Array { } /** - * Return the element of the array at the specified index, converted to a - * boolean if possible. This reproduces the effect of - * <code>array[index]</code> + * Returns the element of the array at the specified index, converted to a + * {@code boolean}, if possible. This reproduces the effect of {@code + * array[index]} * * @param array * the array * @param index * the index + * * @return the requested element - * @throws java.lang.NullPointerException - * if the array is null - * @throws java.lang.IllegalArgumentException - * if the array is not an array or the element cannot be - * converted to the requested type by a widening conversion - * @throws java.lang.ArrayIndexOutOfBoundsException - * if the index is out of bounds -- negative or greater than - * or equal to the array length + * + * @throws NullPointerException + * if the {@code array} is {@code null} + * @throws IllegalArgumentException + * if {@code array} is not an array or the element at the + * index position can not be converted to the return type + * @throws ArrayIndexOutOfBoundsException + * if {@code index < 0 || index >= array.length} + * + * @since Android 1.0 */ public static boolean getBoolean(Object array, int index) throws IllegalArgumentException, ArrayIndexOutOfBoundsException { @@ -115,22 +138,26 @@ public final class Array { } /** - * Return the element of the array at the specified index, converted to a - * byte if possible. This reproduces the effect of <code>array[index]</code> + * Returns the element of the array at the specified index, converted to a + * {@code byte}, if possible. This reproduces the effect of {@code + * array[index]} * * @param array * the array * @param index * the index + * * @return the requested element - * @throws java.lang.NullPointerException - * if the array is null - * @throws java.lang.IllegalArgumentException - * if the array is not an array or the element cannot be - * converted to the requested type by a widening conversion - * @throws java.lang.ArrayIndexOutOfBoundsException - * if the index is out of bounds -- negative or greater than - * or equal to the array length + * + * @throws NullPointerException + * if the {@code array} is {@code null} + * @throws IllegalArgumentException + * if {@code array} is not an array or the element at the + * index position can not be converted to the return type + * @throws ArrayIndexOutOfBoundsException + * if {@code index < 0 || index >= array.length} + * + * @since Android 1.0 */ public static byte getByte(Object array, int index) throws IllegalArgumentException, ArrayIndexOutOfBoundsException { @@ -142,22 +169,26 @@ public final class Array { } /** - * Return the element of the array at the specified index, converted to a - * char if possible. This reproduces the effect of <code>array[index]</code> + * Returns the element of the array at the specified index, converted to a + * {@code char}, if possible. This reproduces the effect of {@code + * array[index]} * * @param array * the array * @param index * the index + * * @return the requested element - * @throws java.lang.NullPointerException - * if the array is null - * @throws java.lang.IllegalArgumentException - * if the array is not an array or the element cannot be - * converted to the requested type by a widening conversion - * @throws java.lang.ArrayIndexOutOfBoundsException - * if the index is out of bounds -- negative or greater than - * or equal to the array length + * + * @throws NullPointerException + * if the {@code array} is {@code null} + * @throws IllegalArgumentException + * if {@code array} is not an array or the element at the + * index position can not be converted to the return type + * @throws ArrayIndexOutOfBoundsException + * if {@code index < 0 || index >= array.length} + * + * @since Android 1.0 */ public static char getChar(Object array, int index) throws IllegalArgumentException, ArrayIndexOutOfBoundsException { @@ -173,23 +204,26 @@ public final class Array { } /** - * Return the element of the array at the specified index, converted to a - * double if possible. This reproduces the effect of - * <code>array[index]</code> + * Returns the element of the array at the specified index, converted to a + * {@code double}, if possible. This reproduces the effect of {@code + * array[index]} * * @param array * the array * @param index * the index + * * @return the requested element - * @throws java.lang.NullPointerException - * if the array is null - * @throws java.lang.IllegalArgumentException - * if the array is not an array or the element cannot be - * converted to the requested type by a widening conversion - * @throws java.lang.ArrayIndexOutOfBoundsException - * if the index is out of bounds -- negative or greater than - * or equal to the array length + * + * @throws NullPointerException + * if the {@code array} is {@code null} + * @throws IllegalArgumentException + * if {@code array} is not an array or the element at the + * index position can not be converted to the return type + * @throws ArrayIndexOutOfBoundsException + * if {@code index < 0 || index >= array.length} + * + * @since Android 1.0 */ public static double getDouble(Object array, int index) throws IllegalArgumentException, ArrayIndexOutOfBoundsException { @@ -201,23 +235,26 @@ public final class Array { } /** - * Return the element of the array at the specified index, converted to a - * float if possible. This reproduces the effect of - * <code>array[index]</code> + * Returns the element of the array at the specified index, converted to a + * {@code float}, if possible. This reproduces the effect of {@code + * array[index]} * * @param array * the array * @param index * the index + * * @return the requested element - * @throws java.lang.NullPointerException - * if the array is null - * @throws java.lang.IllegalArgumentException - * if the array is not an array or the element cannot be - * converted to the requested type by a widening conversion - * @throws java.lang.ArrayIndexOutOfBoundsException - * if the index is out of bounds -- negative or greater than - * or equal to the array length + * + * @throws NullPointerException + * if the {@code array} is {@code null} + * @throws IllegalArgumentException + * if {@code array} is not an array or the element at the + * index position can not be converted to the return type + * @throws ArrayIndexOutOfBoundsException + * if {@code index < 0 || index >= array.length} + * + * @since Android 1.0 */ public static float getFloat(Object array, int index) throws IllegalArgumentException, ArrayIndexOutOfBoundsException { @@ -229,22 +266,26 @@ public final class Array { } /** - * Return the element of the array at the specified index, converted to an - * int if possible. This reproduces the effect of <code>array[index]</code> + * Returns the element of the array at the specified index, converted to an + * {@code int}, if possible. This reproduces the effect of {@code + * array[index]} * * @param array * the array * @param index * the index + * * @return the requested element - * @throws java.lang.NullPointerException - * if the array is null - * @throws java.lang.IllegalArgumentException - * if the array is not an array or the element cannot be - * converted to the requested type by a widening conversion - * @throws java.lang.ArrayIndexOutOfBoundsException - * if the index is out of bounds -- negative or greater than - * or equal to the array length + * + * @throws NullPointerException + * if the {@code array} is {@code null} + * @throws IllegalArgumentException + * if {@code array} is not an array or the element at the + * index position can not be converted to the return type + * @throws ArrayIndexOutOfBoundsException + * if {@code index < 0 || index >= array.length} + * + * @since Android 1.0 */ public static int getInt(Object array, int index) throws IllegalArgumentException, ArrayIndexOutOfBoundsException { @@ -256,16 +297,20 @@ public final class Array { } /** - * Return the length of the array. This reproduces the effect of - * <code>array.length</code> + * Returns the length of the array. This reproduces the effect of {@code + * array.length} * * @param array * the array - * @return the length - * @throws java.lang.NullPointerException - * if the array is null - * @throws java.lang.IllegalArgumentException - * if the array is not an array + * + * @return the length of the array + * + * @throws NullPointerException + * if the {@code array} is {@code null} + * @throws IllegalArgumentException + * if {@code array} is not an array + * + * @since Android 1.0 */ public static int getLength(Object array) { if (array instanceof Object[]) @@ -300,24 +345,28 @@ public final class Array { throw new IllegalArgumentException("Not an array"); } - + /** - * Return the element of the array at the specified index, converted to a - * long if possible. This reproduces the effect of <code>array[index]</code> + * Returns the element of the array at the specified index, converted to a + * {@code long}, if possible. This reproduces the effect of {@code + * array[index]} * * @param array * the array * @param index * the index + * * @return the requested element - * @throws java.lang.NullPointerException - * if the array is null - * @throws java.lang.IllegalArgumentException - * if the array is not an array or the element cannot be - * converted to the requested type by a widening conversion - * @throws java.lang.ArrayIndexOutOfBoundsException - * if the index is out of bounds -- negative or greater than - * or equal to the array length + * + * @throws NullPointerException + * if the {@code array} is {@code null} + * @throws IllegalArgumentException + * if {@code array} is not an array or the element at the + * index position can not be converted to the return type + * @throws ArrayIndexOutOfBoundsException + * if {@code index < 0 || index >= array.length} + * + * @since Android 1.0 */ public static long getLong(Object array, int index) throws IllegalArgumentException, ArrayIndexOutOfBoundsException { @@ -329,23 +378,26 @@ public final class Array { } /** - * Return the element of the array at the specified index, converted to a - * short if possible. This reproduces the effect of - * <code>array[index]</code> + * Returns the element of the array at the specified index, converted to a + * {@code short}, if possible. This reproduces the effect of {@code + * array[index]} * * @param array * the array * @param index * the index + * * @return the requested element - * @throws java.lang.NullPointerException - * if the array is null - * @throws java.lang.IllegalArgumentException - * if the array is not an array or the element cannot be - * converted to the requested type by a widening conversion - * @throws java.lang.ArrayIndexOutOfBoundsException - * if the index is out of bounds -- negative or greater than - * or equal to the array length + * + * @throws NullPointerException + * if the {@code array} is {@code null} + * @throws IllegalArgumentException + * if {@code array} is not an array or the element at the + * index position can not be converted to the return type + * @throws ArrayIndexOutOfBoundsException + * if {@code index < 0 || index >= array.length} + * + * @since Android 1.0 */ public static short getShort(Object array, int index) throws IllegalArgumentException, ArrayIndexOutOfBoundsException { @@ -356,24 +408,27 @@ public final class Array { } /** - * Return a new multidimensional array of the specified component type and - * dimensions. This reproduces the effect of - * <code>new componentType[d0][d1]...[dn]</code> for a dimensions array of { - * d0, d1, ... , dn } + * Returns a new multidimensional array of the specified component type and + * dimensions. This reproduces the effect of {@code new + * componentType[d0][d1]...[dn]} for a dimensions array of { d0, d1, ... , + * dn }. * * @param componentType * the component type of the new array * @param dimensions * the dimensions of the new array + * * @return the new array - * @throws java.lang.NullPointerException - * if the component type is null - * @throws java.lang.NegativeArraySizeException - * if any of the dimensions are negative - * @throws java.lang.IllegalArgumentException - * if the array of dimensions is of size zero, or exceeds the - * limit of the number of dimension for an array (currently - * 255) + * + * @throws NullPointerException + * if the component type is {@code null} + * @throws NegativeArraySizeException + * if any of the dimensions are negative + * @throws IllegalArgumentException + * if the array of dimensions is of size zero, or exceeds the + * limit of the number of dimension for an array (currently 255) + * + * @since Android 1.0 */ public static Object newInstance(Class<?> componentType, int[] dimensions) throws NegativeArraySizeException, IllegalArgumentException { @@ -394,20 +449,24 @@ public final class Array { */ native private static Object createMultiArray(Class<?> componentType, int[] dimensions) throws NegativeArraySizeException; - + /** - * Return a new array of the specified component type and length. This - * reproduces the effect of <code>new componentType[size]</code> - * + * Returns a new array of the specified component type and length. This + * reproduces the effect of {@code new componentType[size]}. + * * @param componentType * the component type of the new array * @param size * the length of the new array + * * @return the new array - * @throws java.lang.NullPointerException - * if the component type is null - * @throws java.lang.NegativeArraySizeException - * if the size if negative + * + * @throws NullPointerException + * if the component type is null + * @throws NegativeArraySizeException + * if {@code size < 0} + * + * @since Android 1.0 */ public static Object newInstance(Class<?> componentType, int size) throws NegativeArraySizeException { @@ -451,9 +510,9 @@ public final class Array { int length) throws NegativeArraySizeException; /** - * Set the element of the array at the specified index to the value. This - * reproduces the effect of <code>array[index] = value</code> If the array - * component is a base type, the value is automatically unwrapped + * Sets the element of the array at the specified index to the value. This + * reproduces the effect of {@code array[index] = value}. If the array + * component is a primitive type, the value is automatically unwrapped. * * @param array * the array @@ -461,14 +520,16 @@ public final class Array { * the index * @param value * the new value - * @throws java.lang.NullPointerException - * if the array is null - * @throws java.lang.IllegalArgumentException - * if the array is not an array or the value cannot be - * converted to the array type by a widening conversion - * @throws java.lang.ArrayIndexOutOfBoundsException - * if the index is out of bounds -- negative or greater than - * or equal to the array length + * + * @throws NullPointerException + * if the {@code array} is {@code null} + * @throws IllegalArgumentException + * if {@code array} is not an array or the value cannot be + * converted to the array type by a widening conversion + * @throws ArrayIndexOutOfBoundsException + * if {@code index < 0 || index >= array.length} + * + * @since Android 1.0 */ public static void set(Object array, int index, Object value) throws IllegalArgumentException, ArrayIndexOutOfBoundsException { @@ -507,10 +568,11 @@ public final class Array { setDouble(array, index, ((Double) value).doubleValue()); } } - + /** - * Set the element of the array at the specified index to the boolean value. - * This reproduces the effect of <code>array[index] = value</code> + * Sets the element of the array at the specified index to the {@code + * boolean} value. This reproduces the effect of {@code array[index] = + * value}. * * @param array * the array @@ -518,14 +580,16 @@ public final class Array { * the index * @param value * the new value - * @throws java.lang.NullPointerException - * if the array is null - * @throws java.lang.IllegalArgumentException - * if the array is not an array or the value cannot be - * converted to the array type by a widening conversion - * @throws java.lang.ArrayIndexOutOfBoundsException - * if the index is out of bounds -- negative or greater than - * or equal to the array length + * + * @throws NullPointerException + * if the {@code array} is {@code null} + * @throws IllegalArgumentException + * if the {@code array} is not an array or the value cannot be + * converted to the array type by a widening conversion + * @throws ArrayIndexOutOfBoundsException + * if {@code index < 0 || index >= array.length} + * + * @since Android 1.0 */ public static void setBoolean(Object array, int index, boolean value) { if (array instanceof boolean[]) { @@ -536,8 +600,8 @@ public final class Array { } /** - * Set the element of the array at the specified index to the byte value. - * This reproduces the effect of <code>array[index] = value</code> + * Sets the element of the array at the specified index to the {@code byte} + * value. This reproduces the effect of {@code array[index] = value}. * * @param array * the array @@ -545,14 +609,16 @@ public final class Array { * the index * @param value * the new value - * @throws java.lang.NullPointerException - * if the array is null - * @throws java.lang.IllegalArgumentException - * if the array is not an array or the value cannot be - * converted to the array type by a widening conversion - * @throws java.lang.ArrayIndexOutOfBoundsException - * if the index is out of bounds -- negative or greater than - * or equal to the array length + * + * @throws NullPointerException + * if the {@code array} is {@code null} + * @throws IllegalArgumentException + * if the {@code array} is not an array or the value cannot be + * converted to the array type by a widening conversion + * @throws ArrayIndexOutOfBoundsException + * if {@code index < 0 || index >= array.length} + * + * @since Android 1.0 */ public static void setByte(Object array, int index, byte value) throws IllegalArgumentException, ArrayIndexOutOfBoundsException { @@ -564,8 +630,8 @@ public final class Array { } /** - * Set the element of the array at the specified index to the char value. - * This reproduces the effect of <code>array[index] = value</code> + * Set the element of the array at the specified index to the {@code char} + * value. This reproduces the effect of {@code array[index] = value}. * * @param array * the array @@ -573,14 +639,16 @@ public final class Array { * the index * @param value * the new value - * @throws java.lang.NullPointerException - * if the array is null - * @throws java.lang.IllegalArgumentException - * if the array is not an array or the value cannot be - * converted to the array type by a widening conversion - * @throws java.lang.ArrayIndexOutOfBoundsException - * if the index is out of bounds -- negative or greater than - * or equal to the array length + * + * @throws NullPointerException + * if the {@code array} is {@code null} + * @throws IllegalArgumentException + * if the {@code array} is not an array or the value cannot be + * converted to the array type by a widening conversion + * @throws ArrayIndexOutOfBoundsException + * if {@code index < 0 || index >= array.length} + * + * @since Android 1.0 */ public static void setChar(Object array, int index, char value) throws IllegalArgumentException, ArrayIndexOutOfBoundsException { @@ -596,8 +664,8 @@ public final class Array { } /** - * Set the element of the array at the specified index to the double value. - * This reproduces the effect of <code>array[index] = value</code> + * Set the element of the array at the specified index to the {@code double} + * value. This reproduces the effect of {@code array[index] = value}. * * @param array * the array @@ -605,14 +673,16 @@ public final class Array { * the index * @param value * the new value - * @throws java.lang.NullPointerException - * if the array is null - * @throws java.lang.IllegalArgumentException - * if the array is not an array or the value cannot be - * converted to the array type by a widening conversion - * @throws java.lang.ArrayIndexOutOfBoundsException - * if the index is out of bounds -- negative or greater than - * or equal to the array length + * + * @throws NullPointerException + * if the {@code array} is {@code null} + * @throws IllegalArgumentException + * if the {@code array} is not an array or the value cannot be + * converted to the array type by a widening conversion + * @throws ArrayIndexOutOfBoundsException + * if {@code index < 0 || index >= array.length} + * + * @since Android 1.0 */ public static void setDouble(Object array, int index, double value) throws IllegalArgumentException, ArrayIndexOutOfBoundsException { @@ -628,8 +698,8 @@ public final class Array { } /** - * Set the element of the array at the specified index to the float value. - * This reproduces the effect of <code>array[index] = value</code> + * Set the element of the array at the specified index to the {@code float} + * value. This reproduces the effect of {@code array[index] = value}. * * @param array * the array @@ -637,14 +707,16 @@ public final class Array { * the index * @param value * the new value - * @throws java.lang.NullPointerException - * if the array is null - * @throws java.lang.IllegalArgumentException - * if the array is not an array or the value cannot be - * converted to the array type by a widening conversion - * @throws java.lang.ArrayIndexOutOfBoundsException - * if the index is out of bounds -- negative or greater than - * or equal to the array length + * + * @throws NullPointerException + * if the {@code array} is {@code null} + * @throws IllegalArgumentException + * if the {@code array} is not an array or the value cannot be + * converted to the array type by a widening conversion + * @throws ArrayIndexOutOfBoundsException + * if {@code index < 0 || index >= array.length} + * + * @since Android 1.0 */ public static void setFloat(Object array, int index, float value) throws IllegalArgumentException, ArrayIndexOutOfBoundsException { @@ -656,8 +728,8 @@ public final class Array { } /** - * Set the element of the array at the specified index to the int value. - * This reproduces the effect of <code>array[index] = value</code> + * Set the element of the array at the specified index to the {@code int} + * value. This reproduces the effect of {@code array[index] = value}. * * @param array * the array @@ -665,14 +737,16 @@ public final class Array { * the index * @param value * the new value - * @throws java.lang.NullPointerException - * if the array is null - * @throws java.lang.IllegalArgumentException - * if the array is not an array or the value cannot be - * converted to the array type by a widening conversion - * @throws java.lang.ArrayIndexOutOfBoundsException - * if the index is out of bounds -- negative or greater than - * or equal to the array length + * + * @throws NullPointerException + * if the {@code array} is {@code null} + * @throws IllegalArgumentException + * if the {@code array} is not an array or the value cannot be + * converted to the array type by a widening conversion + * @throws ArrayIndexOutOfBoundsException + * if {@code index < 0 || index >= array.length} + * + * @since Android 1.0 */ public static void setInt(Object array, int index, int value) throws IllegalArgumentException, ArrayIndexOutOfBoundsException { @@ -684,8 +758,8 @@ public final class Array { } /** - * Set the element of the array at the specified index to the long value. - * This reproduces the effect of <code>array[index] = value</code> + * Set the element of the array at the specified index to the {@code long} + * value. This reproduces the effect of {@code array[index] = value}. * * @param array * the array @@ -693,14 +767,16 @@ public final class Array { * the index * @param value * the new value - * @throws java.lang.NullPointerException - * if the array is null - * @throws java.lang.IllegalArgumentException - * if the array is not an array or the value cannot be - * converted to the array type by a widening conversion - * @throws java.lang.ArrayIndexOutOfBoundsException - * if the index is out of bounds -- negative or greater than - * or equal to the array length + * + * @throws NullPointerException + * if the {@code array} is {@code null} + * @throws IllegalArgumentException + * if the {@code array} is not an array or the value cannot be + * converted to the array type by a widening conversion + * @throws ArrayIndexOutOfBoundsException + * if {@code index < 0 || index >= array.length} + * + * @since Android 1.0 */ public static void setLong(Object array, int index, long value) throws IllegalArgumentException, ArrayIndexOutOfBoundsException { @@ -712,8 +788,8 @@ public final class Array { } /** - * Set the element of the array at the specified index to the short value. - * This reproduces the effect of <code>array[index] = value</code> + * Set the element of the array at the specified index to the {@code short} + * value. This reproduces the effect of {@code array[index] = value}. * * @param array * the array @@ -721,14 +797,16 @@ public final class Array { * the index * @param value * the new value - * @throws java.lang.NullPointerException - * if the array is null - * @throws java.lang.IllegalArgumentException - * if the array is not an array or the value cannot be - * converted to the array type by a widening conversion - * @throws java.lang.ArrayIndexOutOfBoundsException - * if the index is out of bounds -- negative or greater than - * or equal to the array length + * + * @throws NullPointerException + * if the {@code array} is {@code null} + * @throws IllegalArgumentException + * if the {@code array} is not an array or the value cannot be + * converted to the array type by a widening conversion + * @throws ArrayIndexOutOfBoundsException + * if {@code index < 0 || index >= array.length} + * + * @since Android 1.0 */ public static void setShort(Object array, int index, short value) throws IllegalArgumentException, ArrayIndexOutOfBoundsException { diff --git a/luni-kernel/src/main/java/java/lang/reflect/Constructor.java b/luni-kernel/src/main/java/java/lang/reflect/Constructor.java index cf8be6a..b02dcae 100644 --- a/luni-kernel/src/main/java/java/lang/reflect/Constructor.java +++ b/luni-kernel/src/main/java/java/lang/reflect/Constructor.java @@ -14,22 +14,38 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package java.lang.reflect; -// BEGIN android-added +import java.lang.annotation.Annotation; + import org.apache.harmony.kernel.vm.StringUtils; import org.apache.harmony.luni.lang.reflect.GenericSignatureParser; import org.apache.harmony.luni.lang.reflect.ListOfTypes; import org.apache.harmony.luni.lang.reflect.Types; -//END android-added - -import java.lang.annotation.Annotation; /** - * This class models a constructor. Information about the constructor can be + * This class represents a constructor. Information about the constructor can be * accessed, and the constructor can be invoked dynamically. * + * @param <T> the class that declares this constructor + * + * @since Android 1.0 */ public final class Constructor<T> extends AccessibleObject implements GenericDeclaration, Member { @@ -40,7 +56,6 @@ public final class Constructor<T> extends AccessibleObject implements GenericDec Class<?>[] exceptionTypes; - // BEGIN android-added ListOfTypes genericExceptionTypes; ListOfTypes genericParameterTypes; TypeVariable<Constructor<T>>[] formalTypeParameters; @@ -57,12 +72,11 @@ public final class Constructor<T> extends AccessibleObject implements GenericDec genericTypesAreInitialized = true; } } - // END android-added int slot; /** - * Prevent this class from being instantiated + * Prevent this class from being instantiated. */ private Constructor(){ //do nothing @@ -71,23 +85,23 @@ public final class Constructor<T> extends AccessibleObject implements GenericDec /** * Creates an instance of the class. Only called from native code, thus * private. - * - * @param declaringClass The class this constructor object belongs to. - * @param ptypes The parameter types of the constructor. - * @param extypes The exception types of the constructor. - * @param slot The slot of the constructor inside the VM class structure. + * + * @param declaringClass + * the class this constructor object belongs to + * @param ptypes + * the parameter types of the constructor + * @param extypes + * the exception types of the constructor + * @param slot + * the slot of the constructor inside the VM class structure */ - private Constructor (Class<T> declaringClass, Class<?>[] ptypes, Class<?>[] extypes, int slot) - { + private Constructor (Class<T> declaringClass, Class<?>[] ptypes, Class<?>[] extypes, int slot){ this.declaringClass = declaringClass; this.parameterTypes = ptypes; this.exceptionTypes = extypes; // may be null this.slot = slot; } - // BEGIN android-changed - - /** {@inheritDoc} */ @Override /*package*/ String getSignatureAttribute() { Object[] annotation = getSignatureAnnotation(declaringClass, slot); @@ -105,31 +119,21 @@ public final class Constructor<T> extends AccessibleObject implements GenericDec native private Object[] getSignatureAnnotation(Class declaringClass, int slot); - // END android-changed - - /** - * Returns an array of generic type variables used in this constructor. - * - * @return The array of type parameters. - */ public TypeVariable<Constructor<T>>[] getTypeParameters() { - // BEGIN android-changed initGenericTypes(); return formalTypeParameters.clone(); - // END android-changed } /** - * <p> - * Returns the String representation of the constructor's declaration, + * Returns the string representation of the constructor's declaration, * including the type parameters. - * </p> + * + * @return the string representation of the constructor's declaration * - * @return An instance of String. * @since 1.5 + * @since Android 1.0 */ public String toGenericString() { - // BEGIN android-changed StringBuilder sb = new StringBuilder(80); initGenericTypes(); // append modifiers if any @@ -163,52 +167,51 @@ public final class Constructor<T> extends AccessibleObject implements GenericDec appendArrayGenericType(sb, genericEceptionTypeArray); } return sb.toString(); - // END android-changed } /** - * <p> - * Gets the parameter types as an array of {@link Type} instances, in - * declaration order. If the constructor has no parameters, then an empty - * array is returned. - * </p> - * - * @return An array of {@link Type} instances. - * @throws GenericSignatureFormatError if the generic method signature is - * invalid. - * @throws TypeNotPresentException if the component type points to a missing - * type. - * @throws MalformedParameterizedTypeException if the component type points - * to a type that can't be instantiated for some reason. + * Returns the generic parameter types as an array of {@code Type} + * instances, in declaration order. If this constructor has no generic + * parameters, an empty array is returned. + * + * @return the parameter types + * + * @throws GenericSignatureFormatError + * if the generic constructor signature is invalid + * @throws TypeNotPresentException + * if any parameter type points to a missing type + * @throws MalformedParameterizedTypeException + * if any parameter type points to a type that cannot be + * instantiated for some reason + * * @since 1.5 + * @since Android 1.0 */ public Type[] getGenericParameterTypes() { - // BEGIN android-changed initGenericTypes(); return Types.getClonedTypeArray(genericParameterTypes); - // END android-changed } /** - * <p> - * Gets the exception types as an array of {@link Type} instances. If the - * constructor has no declared exceptions, then an empty array is returned. - * </p> - * - * @return An array of {@link Type} instances. - * @throws GenericSignatureFormatError if the generic method signature is - * invalid. - * @throws TypeNotPresentException if the component type points to a missing - * type. - * @throws MalformedParameterizedTypeException if the component type points - * to a type that can't be instantiated for some reason. + * Returns the exception types as an array of {@code Type} instances. If + * this constructor has no declared exceptions, an empty array will be + * returned. + * + * @return an array of generic exception types + * + * @throws GenericSignatureFormatError + * if the generic constructor signature is invalid + * @throws TypeNotPresentException + * if any exception type points to a missing type + * @throws MalformedParameterizedTypeException + * if any exception type points to a type that cannot be + * instantiated for some reason * @since 1.5 + * @since Android 1.0 */ public Type[] getGenericExceptionTypes() { - // BEGIN android-changed initGenericTypes(); return Types.getClonedTypeArray(genericExceptionTypes); - // END android-changed } @Override @@ -219,38 +222,36 @@ public final class Constructor<T> extends AccessibleObject implements GenericDec int slot); /** - * <p> - * Gets an array of arrays that represent the annotations of the formal + * Returns an array of arrays that represent the annotations of the formal * parameters of this constructor. If there are no parameters on this * constructor, then an empty array is returned. If there are no annotations - * set, then and array of empty arrays is returned. - * </p> + * set, then an array of empty arrays is returned. + * + * @return an array of arrays of {@code Annotation} instances * - * @return An array of arrays of {@link Annotation} instances. * @since 1.5 + * @since Android 1.0 */ public Annotation[][] getParameterAnnotations() { -// BEGIN android-changed Annotation[][] parameterAnnotations = getParameterAnnotations(declaringClass, slot); if (parameterAnnotations.length == 0) { return Method.noAnnotations(parameterTypes.length); } -// END android-changed return parameterAnnotations; } native private Annotation[][] getParameterAnnotations(Class declaringClass, int slot); /** - * <p> - * Indicates whether or not this constructor takes a variable number - * argument. - * </p> + * Indicates whether or not this constructor takes a variable number of + * arguments. + * + * @return {@code true} if a vararg is declare, otherwise + * {@code false} * - * @return A value of <code>true</code> if a vararg is declare, otherwise - * <code>false</code>. * @since 1.5 + * @since Android 1.0 */ public boolean isVarArgs() { int mods = getConstructorModifiers(declaringClass, slot); @@ -258,14 +259,13 @@ public final class Constructor<T> extends AccessibleObject implements GenericDec } /** - * <p> - * Indicates whether or not this constructor is synthetic. - * </p> + * Indicates whether or not this constructor is synthetic (artificially + * introduced by the compiler). * - * @return A value of <code>true</code> if it is synthetic, or - * <code>false</code> otherwise. - * - * @since 1.5 + * @return {@code true} if this constructor is synthetic, {@code false} + * otherwise + * + * @since Android 1.0 */ public boolean isSynthetic() { int mods = getConstructorModifiers(declaringClass, slot); @@ -273,14 +273,20 @@ public final class Constructor<T> extends AccessibleObject implements GenericDec } /** - * Compares the specified object to this Constructor and answer if they are - * equal. The object must be an instance of Constructor with the same - * defining class and parameter types. + * Indicates whether or not the specified {@code object} is equal to this + * constructor. To be equal, the specified object must be an instance + * of {@code Constructor} with the same declaring class and parameter types + * as this constructor. + * + * @param object + * the object to compare + * + * @return {@code true} if the specified object is equal to this + * constructor, {@code false} otherwise * - * @param object the object to compare - * @return true if the specified object is equal to this Constructor, false - * otherwise * @see #hashCode + * + * @since Android 1.0 */ @Override public boolean equals(Object object) { @@ -288,22 +294,24 @@ public final class Constructor<T> extends AccessibleObject implements GenericDec } /** - * Return the {@link Class} associated with the class that defined this - * constructor. - * + * Returns the class that declares this constructor. + * * @return the declaring class + * + * @since Android 1.0 */ public Class<T> getDeclaringClass() { return declaringClass; } /** - * Return an array of the {@link Class} objects associated with the - * exceptions declared to be thrown by this constructor. If the constructor - * was not declared to throw any exceptions, the array returned will be - * empty. + * Returns the exception types as an array of {@code Class} instances. If + * this constructor has no declared exceptions, an empty array will be + * returned. * * @return the declared exception classes + * + * @since Android 1.0 */ public Class<?>[] getExceptionTypes() { if (exceptionTypes == null) @@ -312,11 +320,14 @@ public final class Constructor<T> extends AccessibleObject implements GenericDec } /** - * Return the modifiers for the modeled constructor. The Modifier class + * Returns the modifiers for this constructor. The {@link Modifier} class * should be used to decode the result. * - * @return the modifiers - * @see java.lang.reflect.Modifier + * @return the modifiers for this constructor + * + * @see Modifier + * + * @since Android 1.0 */ public int getModifiers() { return getConstructorModifiers(declaringClass, slot); @@ -325,21 +336,24 @@ public final class Constructor<T> extends AccessibleObject implements GenericDec private native int getConstructorModifiers(Class<T> declaringClass, int slot); /** - * Return the name of the modeled constructor. This is the name of the - * declaring class. + * Returns the name of this constructor. + * + * @return the name of this constructor * - * @return the name + * @since Android 1.0 */ public String getName() { return declaringClass.getName(); } /** - * Return an array of the {@link Class} objects associated with the + * Returns an array of the {@code Class} objects associated with the * parameter types of this constructor. If the constructor was declared with - * no parameters, the array returned will be empty. - * + * no parameters, an empty array will be returned. + * * @return the parameter types + * + * @since Android 1.0 */ public Class<?>[] getParameterTypes() { return parameterTypes; @@ -349,8 +363,8 @@ public final class Constructor<T> extends AccessibleObject implements GenericDec * Returns the constructor's signature in non-printable form. This is called * (only) from IO native code and needed for deriving the serialVersionUID * of the class - * - * @return The constructor's signature. + * + * @return the constructor's signature */ @SuppressWarnings("unused") private String getSignature() { @@ -366,12 +380,15 @@ public final class Constructor<T> extends AccessibleObject implements GenericDec } /** - * Returns an integer hash code for the receiver. Objects which are equal - * answer the same value for this method. The hash code for a Constructor is - * the hash code of the declaring class' name. + * Returns an integer hash code for this constructor. Constructors which are + * equal return the same value for this method. The hash code for a + * Constructor is the hash code of the name of the declaring class. + * + * @return the hash code * - * @return the receiver's hash * @see #equals + * + * @since Android 1.0 */ @Override public int hashCode() { @@ -379,45 +396,52 @@ public final class Constructor<T> extends AccessibleObject implements GenericDec } /** - * Return a new instance of the declaring class, initialized by dynamically - * invoking the modeled constructor. This reproduces the effect of - * <code>new declaringClass(arg1, arg2, ... , argN)</code> This method - * performs the following: + * Returns a new instance of the declaring class, initialized by dynamically + * invoking the constructor represented by this {@code Constructor} object. + * This reproduces the effect of {@code new declaringClass(arg1, arg2, ... , + * argN)} This method performs the following: * <ul> * <li>A new instance of the declaring class is created. If the declaring * class cannot be instantiated (i.e. abstract class, an interface, an array - * type, or a base type) then an InstantiationException is thrown.</li> + * type, or a primitive type) then an InstantiationException is thrown.</li> * <li>If this Constructor object is enforcing access control (see - * AccessibleObject) and the modeled constructor is not accessible from the + * {@link AccessibleObject}) and this constructor is not accessible from the * current context, an IllegalAccessException is thrown.</li> - * <li>If the number of arguments passed and the number of parameters do - * not match, an IllegalArgumentException is thrown.</li> + * <li>If the number of arguments passed and the number of parameters do not + * match, an IllegalArgumentException is thrown.</li> * <li>For each argument passed: * <ul> - * <li>If the corresponding parameter type is a base type, the argument is - * unwrapped. If the unwrapping fails, an IllegalArgumentException is + * <li>If the corresponding parameter type is a primitive type, the argument + * is unwrapped. If the unwrapping fails, an IllegalArgumentException is * thrown.</li> * <li>If the resulting argument cannot be converted to the parameter type * via a widening conversion, an IllegalArgumentException is thrown.</li> * </ul> - * <li>The modeled constructor is then invoked. If an exception is thrown - * during the invocation, it is caught and wrapped in an - * InvocationTargetException. This exception is then thrown. If the - * invocation completes normally, the newly initialized object is returned. + * <li>The constructor represented by this {@code Constructor} object is + * then invoked. If an exception is thrown during the invocation, it is + * caught and wrapped in an InvocationTargetException. This exception is + * then thrown. If the invocation completes normally, the newly initialized + * object is returned. * </ul> * - * @param args the arguments to the constructor + * @param args + * the arguments to the constructor + * * @return the new, initialized, object - * @exception java.lang.InstantiationException if the class cannot be - * instantiated - * @exception java.lang.IllegalAccessException if the modeled constructor - * is not accessible - * @exception java.lang.IllegalArgumentException if an incorrect number of - * arguments are passed, or an argument could not be converted by - * a widening conversion - * @exception java.lang.reflect.InvocationTargetException if an exception - * was thrown by the invoked constructor - * @see java.lang.reflect.AccessibleObject + * + * @exception InstantiationException + * if the class cannot be instantiated + * @exception IllegalAccessException + * if this constructor is not accessible + * @exception IllegalArgumentException + * if an incorrect number of arguments are passed, or an + * argument could not be converted by a widening conversion + * @exception InvocationTargetException + * if an exception was thrown by the invoked constructor + * + * @see AccessibleObject + * + * @since Android 1.0 */ public T newInstance(Object... args) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { @@ -428,21 +452,32 @@ public final class Constructor<T> extends AccessibleObject implements GenericDec Class<?>[] parameterTypes, int slot, boolean noAccessCheck) throws InstantiationException, IllegalAccessException, InvocationTargetException; - + /** - * Returns a string containing a concise, human-readable description of the - * receiver. The format of the string is modifiers (if any) declaring class - * name '(' parameter types, separated by ',' ')' If the constructor throws - * exceptions, ' throws ' exception types, separated by ',' For example: - * <code>public String(byte[],String) throws UnsupportedEncodingException</code> + * Returns a string containing a concise, human-readable description of this + * constructor. The format of the string is: + * + * <ol> + * <li>modifiers (if any) + * <li>declaring class name + * <li>'(' + * <li>parameter types, separated by ',' (if any) + * <li>')' + * <li>'throws' plus exception types, separated by ',' (if any) + * </ol> + * + * For example: + * {@code public String(byte[],String) throws UnsupportedEncodingException} + * + * @return a printable representation for this constructor * - * @return a printable representation for the receiver + * @since Android 1.0 */ @Override public String toString() { StringBuilder result = new StringBuilder(Modifier.toString(getModifiers())); - if (result.length() != 0) // android-changed + if (result.length() != 0) result.append(' '); result.append(declaringClass.getName()); result.append("("); diff --git a/luni-kernel/src/main/java/java/lang/reflect/Field.java b/luni-kernel/src/main/java/java/lang/reflect/Field.java index 98fb2de..27cf34a 100644 --- a/luni-kernel/src/main/java/java/lang/reflect/Field.java +++ b/luni-kernel/src/main/java/java/lang/reflect/Field.java @@ -14,53 +14,78 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package java.lang.reflect; -// BEGIN android-added +import java.lang.annotation.Annotation; + import org.apache.harmony.luni.lang.reflect.GenericSignatureParser; import org.apache.harmony.luni.lang.reflect.Types; import org.apache.harmony.kernel.vm.StringUtils; -// END android-added - -import java.lang.annotation.Annotation; - /** - * This class must be implemented by the VM vendor. This class models a field. - * Information about the field can be accessed, and the field's value can be - * accessed dynamically. + * This class represents a field. Information about the field can be accessed, + * and the field's value can be accessed dynamically. * + * @since Android 1.0 */ public final class Field extends AccessibleObject implements Member { - + private Class<?> declaringClass; - + private Class<?> type; - - // BEGIN android-added + private Type genericType; + private volatile boolean genericTypesAreInitialized = false; - // END android-added - + private String name; - + private int slot; - + private static final int TYPE_BOOLEAN = 1; + private static final int TYPE_BYTE = 2; + private static final int TYPE_CHAR = 3; + private static final int TYPE_SHORT = 4; + private static final int TYPE_INTEGER = 5; + private static final int TYPE_FLOAT = 6; + private static final int TYPE_LONG = 7; + private static final int TYPE_DOUBLE = 8; - + /** - * Prevent this class from being instantiated + * Construct a clone of the given instance. + * + * @param orig non-null; the original instance to clone */ - private Field(){ - //do nothing + /*package*/ Field(Field orig) { + this(orig.declaringClass, orig.type, orig.name, orig.slot); + + // Copy the accessible flag. + if (orig.flag) { + this.flag = true; + } } private Field(Class<?> declaringClass, Class<?> type, String name, int slot) { @@ -70,7 +95,6 @@ public final class Field extends AccessibleObject implements Member { this.slot = slot; } - // BEGIN android-added private synchronized void initGenericType() { if (!genericTypesAreInitialized) { String signatureAttribute = getSignatureAttribute(); @@ -83,12 +107,10 @@ public final class Field extends AccessibleObject implements Member { genericTypesAreInitialized = true; } } - // END android-added - - // BEGIN android-changed /** {@inheritDoc} */ - @Override /*package*/ String getSignatureAttribute() { + @Override + /* package */String getSignatureAttribute() { Object[] annotation = getSignatureAnnotation(declaringClass, slot); if (annotation == null) { @@ -97,23 +119,18 @@ public final class Field extends AccessibleObject implements Member { return StringUtils.combineStrings(annotation); } - + /** - * Get the Signature annotation for this field. Returns null if not found. + * Get the Signature annotation for this field. Returns null if not found. */ - native private Object[] getSignatureAnnotation(Class declaringClass, - int slot); - - // END android-changed + native private Object[] getSignatureAnnotation(Class declaringClass, int slot); /** - * <p> * Indicates whether or not this field is synthetic. - * </p> * - * @return A value of <code>true</code> if this field is synthetic, - * otherwise <code>false</code>. + * @return {@code true} if this field is synthetic, {@code false} otherwise * @since 1.5 + * @since Android 1.0 */ public boolean isSynthetic() { int flags = getFieldModifiers(declaringClass, slot); @@ -121,16 +138,14 @@ public final class Field extends AccessibleObject implements Member { } /** - * <p> - * Returns the String representation of the field's declaration, including - * the type parameters. - * </p> + * Returns the string representation of this field, including the field's + * generic type. * - * @return An instance of String. + * @return the string representation of this field * @since 1.5 + * @since Android 1.0 */ public String toGenericString() { - // BEGIN android-changed StringBuilder sb = new StringBuilder(80); // append modifiers if any int modifier = getModifiers(); @@ -143,17 +158,15 @@ public final class Field extends AccessibleObject implements Member { // append full field name sb.append(getDeclaringClass().getName()).append('.').append(getName()); return sb.toString(); - // END android-changed } /** - * <p> * Indicates whether or not this field is an enumeration constant. - * </p> * - * @return A value of <code>true</code> if this field is an enumeration - * constant, otherwise <code>false</code>. + * @return {@code true} if this field is an enumeration constant, {@code + * false} otherwise * @since 1.5 + * @since Android 1.0 */ public boolean isEnumConstant() { int flags = getFieldModifiers(declaringClass, slot); @@ -161,42 +174,42 @@ public final class Field extends AccessibleObject implements Member { } /** - * <p> - * Gets the declared type of this field. - * </p> + * Returns the generic type of this field. * - * @return An instance of {@link Type}. - * @throws GenericSignatureFormatError if the generic method signature is - * invalid. - * @throws TypeNotPresentException if the component type points to a missing - * type. - * @throws MalformedParameterizedTypeException if the component type points - * to a type that can't be instantiated for some reason. + * @return the generic type + * @throws GenericSignatureFormatError + * if the generic field signature is invalid + * @throws TypeNotPresentException + * if the generic type points to a missing type + * @throws MalformedParameterizedTypeException + * if the generic type points to a type that cannot be + * instantiated for some reason * @since 1.5 + * @since Android 1.0 */ public Type getGenericType() { - // BEGIN android-changed initGenericType(); return Types.getType(genericType); - // END android-changed } - + @Override public Annotation[] getDeclaredAnnotations() { return getDeclaredAnnotations(declaringClass, slot); } - native private Annotation[] getDeclaredAnnotations(Class declaringClass, - int slot); + + native private Annotation[] getDeclaredAnnotations(Class declaringClass, int slot); /** - * Compares the specified object to this Field and answer if they are equal. - * The object must be an instance of Field with the same defining class and - * name. + * Indicates whether or not the specified {@code object} is equal to this + * field. To be equal, the specified object must be an instance of + * {@code Field} with the same declaring class, type and name as this field. * - * @param object the object to compare - * @return true if the specified object is equal to this Field, false - * otherwise + * @param object + * the object to compare + * @return {@code true} if the specified object is equal to this method, + * {@code false} otherwise * @see #hashCode + * @since Android 1.0 */ @Override public boolean equals(Object object) { @@ -204,248 +217,251 @@ public final class Field extends AccessibleObject implements Member { } /** - * Return the value of the field in the specified object. This reproduces - * the effect of <code>object.fieldName</code> + * Returns the value of the field in the specified object. This reproduces + * the effect of {@code object.fieldName} * <p> - * If the modeled field is static, the object argument is ignored. + * If the type of this field is a primitive type, the field value is + * automatically wrapped. + * <p> + * If this field is static, the object argument is ignored. * Otherwise, if the object is null, a NullPointerException is thrown. If * the object is not an instance of the declaring class of the method, an * IllegalArgumentException is thrown. * <p> * If this Field object is enforcing access control (see AccessibleObject) - * and the modeled field is not accessible from the current context, an + * and this field is not accessible from the current context, an * IllegalAccessException is thrown. * <p> - * The value of the field is returned. If the type of this field is a base - * type, the field value is automatically wrapped. * * @param object * the object to access * @return the field value, possibly wrapped * @throws NullPointerException - * if the object is null and the field is non-static + * if the object is {@code null} and the field is non-static * @throws IllegalArgumentException * if the object is not compatible with the declaring class * @throws IllegalAccessException - * if modeled field is not accessible + * if this field is not accessible + * @since Android 1.0 */ - public Object get(Object object) throws IllegalAccessException, - IllegalArgumentException { + public Object get(Object object) throws IllegalAccessException, IllegalArgumentException { return getField(object, declaringClass, type, slot, flag); } /** - * Return the value of the field in the specified object as a boolean. This - * reproduces the effect of <code>object.fieldName</code> + * Returns the value of the field in the specified object as a {@code + * boolean}. This reproduces the effect of {@code object.fieldName} * <p> - * If the modeled field is static, the object argument is ignored. - * Otherwise, if the object is null, a NullPointerException is thrown. If - * the object is not an instance of the declaring class of the method, an - * IllegalArgumentException is thrown. + * If this field is static, the object argument is ignored. + * Otherwise, if the object is {@code null}, a NullPointerException is + * thrown. If the object is not an instance of the declaring class of the + * method, an IllegalArgumentException is thrown. * <p> * If this Field object is enforcing access control (see AccessibleObject) - * and the modeled field is not accessible from the current context, an + * and this field is not accessible from the current context, an * IllegalAccessException is thrown. * * @param object * the object to access * @return the field value * @throws NullPointerException - * if the object is null and the field is non-static + * if the object is {@code null} and the field is non-static * @throws IllegalArgumentException * if the object is not compatible with the declaring class * @throws IllegalAccessException - * if modeled field is not accessible + * if this field is not accessible + * @since Android 1.0 */ - public boolean getBoolean(Object object) - throws IllegalAccessException, IllegalArgumentException { + public boolean getBoolean(Object object) throws IllegalAccessException, + IllegalArgumentException { return getZField(object, declaringClass, type, slot, flag, TYPE_BOOLEAN); } /** - * Return the value of the field in the specified object as a byte. This - * reproduces the effect of <code>object.fieldName</code> + * Returns the value of the field in the specified object as a {@code byte}. + * This reproduces the effect of {@code object.fieldName} * <p> - * If the modeled field is static, the object argument is ignored. - * Otherwise, if the object is null, a NullPointerException is thrown. If - * the object is not an instance of the declaring class of the method, an - * IllegalArgumentException is thrown. + * If this field is static, the object argument is ignored. + * Otherwise, if the object is {@code null}, a NullPointerException is + * thrown. If the object is not an instance of the declaring class of the + * method, an IllegalArgumentException is thrown. * <p> * If this Field object is enforcing access control (see AccessibleObject) - * and the modeled field is not accessible from the current context, an + * and this field is not accessible from the current context, an * IllegalAccessException is thrown. * * @param object * the object to access * @return the field value * @throws NullPointerException - * if the object is null and the field is non-static + * if the object is {@code null} and the field is non-static * @throws IllegalArgumentException * if the object is not compatible with the declaring class * @throws IllegalAccessException - * if modeled field is not accessible + * if this field is not accessible + * @since Android 1.0 */ - public byte getByte(Object object) throws IllegalAccessException, - IllegalArgumentException { + public byte getByte(Object object) throws IllegalAccessException, IllegalArgumentException { return getBField(object, declaringClass, type, slot, flag, TYPE_BYTE); } /** - * Return the value of the field in the specified object as a char. This - * reproduces the effect of <code>object.fieldName</code> + * Returns the value of the field in the specified object as a {@code char}. + * This reproduces the effect of {@code object.fieldName} * <p> - * If the modeled field is static, the object argument is ignored. - * Otherwise, if the object is null, a NullPointerException is thrown. If - * the object is not an instance of the declaring class of the method, an - * IllegalArgumentException is thrown. + * If this field is static, the object argument is ignored. + * Otherwise, if the object is {@code null}, a NullPointerException is + * thrown. If the object is not an instance of the declaring class of the + * method, an IllegalArgumentException is thrown. * <p> * If this Field object is enforcing access control (see AccessibleObject) - * and the modeled field is not accessible from the current context, an + * and this field is not accessible from the current context, an * IllegalAccessException is thrown. * * @param object * the object to access * @return the field value * @throws NullPointerException - * if the object is null and the field is non-static + * if the object is {@code null} and the field is non-static * @throws IllegalArgumentException * if the object is not compatible with the declaring class * @throws IllegalAccessException - * if modeled field is not accessible + * if this field is not accessible + * @since Android 1.0 */ - public char getChar(Object object) throws IllegalAccessException, - IllegalArgumentException { + public char getChar(Object object) throws IllegalAccessException, IllegalArgumentException { return getCField(object, declaringClass, type, slot, flag, TYPE_CHAR); } /** - * Return the {@link Class} associated with the class that defined this - * field. - * + * Returns the class that declares this field. + * * @return the declaring class + * @since Android 1.0 */ public Class<?> getDeclaringClass() { return declaringClass; } /** - * Return the value of the field in the specified object as a double. This - * reproduces the effect of <code>object.fieldName</code> + * Returns the value of the field in the specified object as a {@code + * double}. This reproduces the effect of {@code object.fieldName} * <p> - * If the modeled field is static, the object argument is ignored. - * Otherwise, if the object is null, a NullPointerException is thrown. If - * the object is not an instance of the declaring class of the method, an - * IllegalArgumentException is thrown. + * If this field is static, the object argument is ignored. + * Otherwise, if the object is {@code null}, a NullPointerException is + * thrown. If the object is not an instance of the declaring class of the + * method, an IllegalArgumentException is thrown. * <p> * If this Field object is enforcing access control (see AccessibleObject) - * and the modeled field is not accessible from the current context, an + * and this field is not accessible from the current context, an * IllegalAccessException is thrown. * * @param object * the object to access * @return the field value * @throws NullPointerException - * if the object is null and the field is non-static + * if the object is {@code null} and the field is non-static * @throws IllegalArgumentException * if the object is not compatible with the declaring class * @throws IllegalAccessException - * if modeled field is not accessible + * if this field is not accessible + * @since Android 1.0 */ - public double getDouble(Object object) - throws IllegalAccessException, IllegalArgumentException { + public double getDouble(Object object) throws IllegalAccessException, IllegalArgumentException { return getDField(object, declaringClass, type, slot, flag, TYPE_DOUBLE); } /** - * Return the value of the field in the specified object as a float. This - * reproduces the effect of <code>object.fieldName</code> + * Returns the value of the field in the specified object as a {@code float} + * . This reproduces the effect of {@code object.fieldName} * <p> - * If the modeled field is static, the object argument is ignored. - * Otherwise, if the object is null, a NullPointerException is thrown. If - * the object is not an instance of the declaring class of the method, an - * IllegalArgumentException is thrown. + * If this field is static, the object argument is ignored. + * Otherwise, if the object is {@code null}, a NullPointerException is + * thrown. If the object is not an instance of the declaring class of the + * method, an IllegalArgumentException is thrown. * <p> * If this Field object is enforcing access control (see AccessibleObject) - * and the modeled field is not accessible from the current context, an + * and this field is not accessible from the current context, an * IllegalAccessException is thrown. * * @param object * the object to access * @return the field value * @throws NullPointerException - * if the object is null and the field is non-static + * if the object is {@code null} and the field is non-static * @throws IllegalArgumentException * if the object is not compatible with the declaring class * @throws IllegalAccessException - * if modeled field is not accessible + * if this field is not accessible + * @since Android 1.0 */ - public float getFloat(Object object) throws IllegalAccessException, - IllegalArgumentException { + public float getFloat(Object object) throws IllegalAccessException, IllegalArgumentException { return getFField(object, declaringClass, type, slot, flag, TYPE_FLOAT); } /** - * Return the value of the field in the specified object as an int. This - * reproduces the effect of <code>object.fieldName</code> + * Returns the value of the field in the specified object as an {@code int}. + * This reproduces the effect of {@code object.fieldName} * <p> - * If the modeled field is static, the object argument is ignored. - * Otherwise, if the object is null, a NullPointerException is thrown. If - * the object is not an instance of the declaring class of the method, an - * IllegalArgumentException is thrown. + * If this field is static, the object argument is ignored. + * Otherwise, if the object is {@code null}, a NullPointerException is + * thrown. If the object is not an instance of the declaring class of the + * method, an IllegalArgumentException is thrown. * <p> * If this Field object is enforcing access control (see AccessibleObject) - * and the modeled field is not accessible from the current context, an + * and this field is not accessible from the current context, an * IllegalAccessException is thrown. * * @param object * the object to access * @return the field value * @throws NullPointerException - * if the object is null and the field is non-static + * if the object is {@code null} and the field is non-static * @throws IllegalArgumentException * if the object is not compatible with the declaring class * @throws IllegalAccessException - * if modeled field is not accessible + * if this field is not accessible + * @since Android 1.0 */ - public int getInt(Object object) throws IllegalAccessException, - IllegalArgumentException { + public int getInt(Object object) throws IllegalAccessException, IllegalArgumentException { return getIField(object, declaringClass, type, slot, flag, TYPE_INTEGER); } /** - * Return the value of the field in the specified object as a long. This - * reproduces the effect of <code>object.fieldName</code> + * Returns the value of the field in the specified object as a {@code long}. + * This reproduces the effect of {@code object.fieldName} * <p> - * If the modeled field is static, the object argument is ignored. - * Otherwise, if the object is null, a NullPointerException is thrown. If - * the object is not an instance of the declaring class of the method, an - * IllegalArgumentException is thrown. + * If this field is static, the object argument is ignored. + * Otherwise, if the object is {@code null}, a NullPointerException is + * thrown. If the object is not an instance of the declaring class of the + * method, an IllegalArgumentException is thrown. * <p> * If this Field object is enforcing access control (see AccessibleObject) - * and the modeled field is not accessible from the current context, an + * and this field is not accessible from the current context, an * IllegalAccessException is thrown. * * @param object * the object to access * @return the field value * @throws NullPointerException - * if the object is null and the field is non-static + * if the object is {@code null} and the field is non-static * @throws IllegalArgumentException * if the object is not compatible with the declaring class * @throws IllegalAccessException - * if modeled field is not accessible + * if this field is not accessible + * @since Android 1.0 */ - public long getLong(Object object) throws IllegalAccessException, - IllegalArgumentException { + public long getLong(Object object) throws IllegalAccessException, IllegalArgumentException { return getJField(object, declaringClass, type, slot, flag, TYPE_LONG); } /** - * Return the modifiers for the modeled field. The Modifier class should be - * used to decode the result. - * - * @return the modifiers - * @see java.lang.reflect.Modifier + * Returns the modifiers for this field. The {@link Modifier} class should + * be used to decode the result. + * + * @return the modifiers for this field + * @see Modifier + * @since Android 1.0 */ public int getModifiers() { return getFieldModifiers(declaringClass, slot); @@ -454,40 +470,40 @@ public final class Field extends AccessibleObject implements Member { private native int getFieldModifiers(Class<?> declaringClass, int slot); /** - * Return the name of the modeled field. - * - * @return the name + * Returns the name of this field. + * + * @return the name of this field + * @since Android 1.0 */ public String getName() { return name; } /** - * Return the value of the field in the specified object as a short. This - * reproduces the effect of <code>object.fieldName</code> + * Returns the value of the field in the specified object as a {@code short} + * . This reproduces the effect of {@code object.fieldName} * <p> - * If the modeled field is static, the object argument is ignored. - * Otherwise, if the object is null, a NullPointerException is thrown. If - * the object is not an instance of the declaring class of the method, an - * IllegalArgumentException is thrown. + * If this field is static, the object argument is ignored. + * Otherwise, if the object is {@code null}, a NullPointerException is + * thrown. If the object is not an instance of the declaring class of the + * method, an IllegalArgumentException is thrown. * <p> * If this Field object is enforcing access control (see AccessibleObject) - * and the modeled field is not accessible from the current context, an + * and this field is not accessible from the current context, an * IllegalAccessException is thrown. - * <p> * * @param object * the object to access * @return the field value * @throws NullPointerException - * if the object is null and the field is non-static + * if the object is {@code null} and the field is non-static * @throws IllegalArgumentException * if the object is not compatible with the declaring class * @throws IllegalAccessException - * if modeled field is not accessible + * if this field is not accessible + * @since Android 1.0 */ - public short getShort(Object object) throws IllegalAccessException, - IllegalArgumentException { + public short getShort(Object object) throws IllegalAccessException, IllegalArgumentException { return getSField(object, declaringClass, type, slot, flag, TYPE_SHORT); } @@ -496,7 +512,8 @@ public final class Field extends AccessibleObject implements Member { * (only) from IO native code and needed for deriving the serialVersionUID * of the class * - * @return The constructor's signature. + * @return the constructor's signature. + * @since Android 1.0 */ @SuppressWarnings("unused") private String getSignature() { @@ -506,71 +523,79 @@ public final class Field extends AccessibleObject implements Member { /** * Return the {@link Class} associated with the type of this field. * - * @return the type + * @return the type of this field + * @since Android 1.0 */ public Class<?> getType() { return type; } /** - * Returns an integer hash code for the receiver. Objects which are equal - * answer the same value for this method. + * Returns an integer hash code for this field. Objects which are equal + * return the same value for this method. * <p> - * The hash code for a Field is the hash code of the field's name. + * The hash code for a Field is the exclusive-or combination of the hash + * code of the field's name and the hash code of the name of its declaring + * class. * - * @return the receiver's hash + * @return the hash code for this field * @see #equals + * @since Android 1.0 */ @Override public int hashCode() { - return name.hashCode(); + // BEGIN android-changed + return name.hashCode() ^ getDeclaringClass().getName().hashCode(); + // END android-changed } /** - * Set the value of the field in the specified object to the boolean value. - * This reproduces the effect of <code>object.fieldName = value</code> + * Sets the value of the field in the specified object to the value. This + * reproduces the effect of {@code object.fieldName = value} * <p> - * If the modeled field is static, the object argument is ignored. - * Otherwise, if the object is null, a NullPointerException is thrown. If - * the object is not an instance of the declaring class of the method, an - * IllegalArgumentException is thrown. + * If this field is static, the object argument is ignored. + * Otherwise, if the object is {@code null}, a NullPointerException is + * thrown. If the object is not an instance of the declaring class of the + * method, an IllegalArgumentException is thrown. * <p> * If this Field object is enforcing access control (see AccessibleObject) - * and the modeled field is not accessible from the current context, an + * and this field is not accessible from the current context, an * IllegalAccessException is thrown. * <p> - * If the field type is a base type, the value is automatically unwrapped. - * If the unwrap fails, an IllegalArgumentException is thrown. If the value - * cannot be converted to the field type via a widening conversion, an - * IllegalArgumentException is thrown. + * If the field type is a primitive type, the value is automatically + * unwrapped. If the unwrap fails, an IllegalArgumentException is thrown. If + * the value cannot be converted to the field type via a widening + * conversion, an IllegalArgumentException is thrown. * * @param object * the object to access * @param value * the new value * @throws NullPointerException - * if the object is null and the field is non-static + * if the object is {@code null} and the field is non-static * @throws IllegalArgumentException * if the object is not compatible with the declaring class * @throws IllegalAccessException - * if modeled field is not accessible + * if this field is not accessible + * @since Android 1.0 */ - public void set(Object object, Object value) - throws IllegalAccessException, IllegalArgumentException { + public void set(Object object, Object value) throws IllegalAccessException, + IllegalArgumentException { setField(object, declaringClass, type, slot, flag, value); } - + /** - * Set the value of the field in the specified object to the boolean value. - * This reproduces the effect of <code>object.fieldName = value</code> + * Sets the value of the field in the specified object to the {@code + * boolean} value. This reproduces the effect of {@code object.fieldName = + * value} * <p> - * If the modeled field is static, the object argument is ignored. - * Otherwise, if the object is null, a NullPointerException is thrown. If - * the object is not an instance of the declaring class of the method, an - * IllegalArgumentException is thrown. + * If this field is static, the object argument is ignored. + * Otherwise, if the object is {@code null}, a NullPointerException is + * thrown. If the object is not an instance of the declaring class of the + * method, an IllegalArgumentException is thrown. * <p> * If this Field object is enforcing access control (see AccessibleObject) - * and the modeled field is not accessible from the current context, an + * and this field is not accessible from the current context, an * IllegalAccessException is thrown. * <p> * If the value cannot be converted to the field type via a widening @@ -581,28 +606,29 @@ public final class Field extends AccessibleObject implements Member { * @param value * the new value * @throws NullPointerException - * if the object is null and the field is non-static + * if the object is {@code null} and the field is non-static * @throws IllegalArgumentException * if the object is not compatible with the declaring class * @throws IllegalAccessException - * if modeled field is not accessible + * if this field is not accessible + * @since Android 1.0 */ - public void setBoolean(Object object, boolean value) - throws IllegalAccessException, IllegalArgumentException { + public void setBoolean(Object object, boolean value) throws IllegalAccessException, + IllegalArgumentException { setZField(object, declaringClass, type, slot, flag, TYPE_BOOLEAN, value); } /** - * Set the value of the field in the specified object to the byte value. - * This reproduces the effect of <code>object.fieldName = value</code> + * Sets the value of the field in the specified object to the {@code byte} + * value. This reproduces the effect of {@code object.fieldName = value} * <p> - * If the modeled field is static, the object argument is ignored. - * Otherwise, if the object is null, a NullPointerException is thrown. If - * the object is not an instance of the declaring class of the method, an - * IllegalArgumentException is thrown. + * If this field is static, the object argument is ignored. + * Otherwise, if the object is {@code null}, a NullPointerException is + * thrown. If the object is not an instance of the declaring class of the + * method, an IllegalArgumentException is thrown. * <p> * If this Field object is enforcing access control (see AccessibleObject) - * and the modeled field is not accessible from the current context, an + * and this field is not accessible from the current context, an * IllegalAccessException is thrown. * <p> * If the value cannot be converted to the field type via a widening @@ -613,28 +639,29 @@ public final class Field extends AccessibleObject implements Member { * @param value * the new value * @throws NullPointerException - * if the object is null and the field is non-static + * if the object is {@code null} and the field is non-static * @throws IllegalArgumentException * if the object is not compatible with the declaring class * @throws IllegalAccessException - * if modeled field is not accessible + * if this field is not accessible + * @since Android 1.0 */ - public void setByte(Object object, byte value) - throws IllegalAccessException, IllegalArgumentException { + public void setByte(Object object, byte value) throws IllegalAccessException, + IllegalArgumentException { setBField(object, declaringClass, type, slot, flag, TYPE_BYTE, value); } /** - * Set the value of the field in the specified object to the char value. - * This reproduces the effect of <code>object.fieldName = value</code> + * Sets the value of the field in the specified object to the {@code char} + * value. This reproduces the effect of {@code object.fieldName = value} * <p> - * If the modeled field is static, the object argument is ignored. - * Otherwise, if the object is null, a NullPointerException is thrown. If - * the object is not an instance of the declaring class of the method, an - * IllegalArgumentException is thrown. + * If this field is static, the object argument is ignored. + * Otherwise, if the object is {@code null}, a NullPointerException is + * thrown. If the object is not an instance of the declaring class of the + * method, an IllegalArgumentException is thrown. * <p> * If this Field object is enforcing access control (see AccessibleObject) - * and the modeled field is not accessible from the current context, an + * and this field is not accessible from the current context, an * IllegalAccessException is thrown. * <p> * If the value cannot be converted to the field type via a widening @@ -645,28 +672,29 @@ public final class Field extends AccessibleObject implements Member { * @param value * the new value * @throws NullPointerException - * if the object is null and the field is non-static + * if the object is {@code null} and the field is non-static * @throws IllegalArgumentException * if the object is not compatible with the declaring class * @throws IllegalAccessException - * if modeled field is not accessible + * if this field is not accessible + * @since Android 1.0 */ - public void setChar(Object object, char value) - throws IllegalAccessException, IllegalArgumentException { + public void setChar(Object object, char value) throws IllegalAccessException, + IllegalArgumentException { setCField(object, declaringClass, type, slot, flag, TYPE_CHAR, value); } /** - * Set the value of the field in the specified object to the double value. - * This reproduces the effect of <code>object.fieldName = value</code> + * Sets the value of the field in the specified object to the {@code double} + * value. This reproduces the effect of {@code object.fieldName = value} * <p> - * If the modeled field is static, the object argument is ignored. - * Otherwise, if the object is null, a NullPointerException is thrown. If - * the object is not an instance of the declaring class of the method, an - * IllegalArgumentException is thrown. + * If this field is static, the object argument is ignored. + * Otherwise, if the object is {@code null}, a NullPointerException is + * thrown. If the object is not an instance of the declaring class of the + * method, an IllegalArgumentException is thrown. * <p> * If this Field object is enforcing access control (see AccessibleObject) - * and the modeled field is not accessible from the current context, an + * and this field is not accessible from the current context, an * IllegalAccessException is thrown. * <p> * If the value cannot be converted to the field type via a widening @@ -677,28 +705,29 @@ public final class Field extends AccessibleObject implements Member { * @param value * the new value * @throws NullPointerException - * if the object is null and the field is non-static + * if the object is {@code null} and the field is non-static * @throws IllegalArgumentException * if the object is not compatible with the declaring class * @throws IllegalAccessException - * if modeled field is not accessible + * if this field is not accessible + * @since Android 1.0 */ - public void setDouble(Object object, double value) - throws IllegalAccessException, IllegalArgumentException { + public void setDouble(Object object, double value) throws IllegalAccessException, + IllegalArgumentException { setDField(object, declaringClass, type, slot, flag, TYPE_DOUBLE, value); } /** - * Set the value of the field in the specified object to the float value. - * This reproduces the effect of <code>object.fieldName = value</code> + * Sets the value of the field in the specified object to the {@code float} + * value. This reproduces the effect of {@code object.fieldName = value} * <p> - * If the modeled field is static, the object argument is ignored. - * Otherwise, if the object is null, a NullPointerException is thrown. If - * the object is not an instance of the declaring class of the method, an - * IllegalArgumentException is thrown. + * If this field is static, the object argument is ignored. + * Otherwise, if the object is {@code null}, a NullPointerException is + * thrown. If the object is not an instance of the declaring class of the + * method, an IllegalArgumentException is thrown. * <p> * If this Field object is enforcing access control (see AccessibleObject) - * and the modeled field is not accessible from the current context, an + * and this field is not accessible from the current context, an * IllegalAccessException is thrown. * <p> * If the value cannot be converted to the field type via a widening @@ -709,28 +738,29 @@ public final class Field extends AccessibleObject implements Member { * @param value * the new value * @throws NullPointerException - * if the object is null and the field is non-static + * if the object is {@code null} and the field is non-static * @throws IllegalArgumentException * if the object is not compatible with the declaring class * @throws IllegalAccessException - * if modeled field is not accessible + * if this field is not accessible + * @since Android 1.0 */ - public void setFloat(Object object, float value) - throws IllegalAccessException, IllegalArgumentException { + public void setFloat(Object object, float value) throws IllegalAccessException, + IllegalArgumentException { setFField(object, declaringClass, type, slot, flag, TYPE_FLOAT, value); } /** - * Set the value of the field in the specified object to the int value. This - * reproduces the effect of <code>object.fieldName = value</code> + * Set the value of the field in the specified object to the {@code int} + * value. This reproduces the effect of {@code object.fieldName = value} * <p> - * If the modeled field is static, the object argument is ignored. - * Otherwise, if the object is null, a NullPointerException is thrown. If - * the object is not an instance of the declaring class of the method, an - * IllegalArgumentException is thrown. + * If this field is static, the object argument is ignored. + * Otherwise, if the object is {@code null}, a NullPointerException is + * thrown. If the object is not an instance of the declaring class of the + * method, an IllegalArgumentException is thrown. * <p> * If this Field object is enforcing access control (see AccessibleObject) - * and the modeled field is not accessible from the current context, an + * and this field is not accessible from the current context, an * IllegalAccessException is thrown. * <p> * If the value cannot be converted to the field type via a widening @@ -741,28 +771,29 @@ public final class Field extends AccessibleObject implements Member { * @param value * the new value * @throws NullPointerException - * if the object is null and the field is non-static + * if the object is {@code null} and the field is non-static * @throws IllegalArgumentException * if the object is not compatible with the declaring class * @throws IllegalAccessException - * if modeled field is not accessible + * if this field is not accessible + * @since Android 1.0 */ - public void setInt(Object object, int value) - throws IllegalAccessException, IllegalArgumentException { + public void setInt(Object object, int value) throws IllegalAccessException, + IllegalArgumentException { setIField(object, declaringClass, type, slot, flag, TYPE_INTEGER, value); } /** - * Set the value of the field in the specified object to the long value. - * This reproduces the effect of <code>object.fieldName = value</code> + * Sets the value of the field in the specified object to the {@code long} + * value. This reproduces the effect of {@code object.fieldName = value} * <p> - * If the modeled field is static, the object argument is ignored. - * Otherwise, if the object is null, a NullPointerException is thrown. If - * the object is not an instance of the declaring class of the method, an - * IllegalArgumentException is thrown. + * If this field is static, the object argument is ignored. + * Otherwise, if the object is {@code null}, a NullPointerException is + * thrown. If the object is not an instance of the declaring class of the + * method, an IllegalArgumentException is thrown. * <p> * If this Field object is enforcing access control (see AccessibleObject) - * and the modeled field is not accessible from the current context, an + * and this field is not accessible from the current context, an * IllegalAccessException is thrown. * <p> * If the value cannot be converted to the field type via a widening @@ -773,28 +804,29 @@ public final class Field extends AccessibleObject implements Member { * @param value * the new value * @throws NullPointerException - * if the object is null and the field is non-static + * if the object is {@code null} and the field is non-static * @throws IllegalArgumentException * if the object is not compatible with the declaring class * @throws IllegalAccessException - * if modeled field is not accessible + * if this field is not accessible + * @since Android 1.0 */ - public void setLong(Object object, long value) - throws IllegalAccessException, IllegalArgumentException { + public void setLong(Object object, long value) throws IllegalAccessException, + IllegalArgumentException { setJField(object, declaringClass, type, slot, flag, TYPE_LONG, value); } /** - * Set the value of the field in the specified object to the short value. - * This reproduces the effect of <code>object.fieldName = value</code> + * Sets the value of the field in the specified object to the {@code short} + * value. This reproduces the effect of {@code object.fieldName = value} * <p> - * If the modeled field is static, the object argument is ignored. - * Otherwise, if the object is null, a NullPointerException is thrown. If - * the object is not an instance of the declaring class of the method, an - * IllegalArgumentException is thrown. + * If this field is static, the object argument is ignored. + * Otherwise, if the object is {@code null}, a NullPointerException is + * thrown. If the object is not an instance of the declaring class of the + * method, an IllegalArgumentException is thrown. * <p> * If this Field object is enforcing access control (see AccessibleObject) - * and the modeled field is not accessible from the current context, an + * and this field is not accessible from the current context, an * IllegalAccessException is thrown. * <p> * If the value cannot be converted to the field type via a widening @@ -805,119 +837,104 @@ public final class Field extends AccessibleObject implements Member { * @param value * the new value * @throws NullPointerException - * if the object is null and the field is non-static + * if the object is {@code null} and the field is non-static * @throws IllegalArgumentException * if the object is not compatible with the declaring class * @throws IllegalAccessException - * if modeled field is not accessible + * if this field is not accessible + * @since Android 1.0 */ - public void setShort(Object object, short value) - throws IllegalAccessException, IllegalArgumentException { + public void setShort(Object object, short value) throws IllegalAccessException, + IllegalArgumentException { setSField(object, declaringClass, type, slot, flag, TYPE_SHORT, value); } /** - * Returns a string containing a concise, human-readable description of the - * receiver. + * Returns a string containing a concise, human-readable description of this + * field. * <p> * The format of the string is: - * <ul> - * <li>modifiers (if any) - * <li>return type - * <li>declaring class name - * <li>'.' - * <li>field name - * </ul> - * <p> - * For example: - * <code>public static java.io.InputStream java.lang.System.in</code> + * <ol> + * <li>modifiers (if any) + * <li>type + * <li>declaring class name + * <li>'.' + * <li>field name + * </ol> + * <p> + * For example: {@code public static java.io.InputStream + * java.lang.System.in} * - * @return a printable representation for the receiver + * @return a printable representation for this field + * @since Android 1.0 */ @Override public String toString() { StringBuffer result = new StringBuffer(Modifier.toString(getModifiers())); - if (result.length() != 0) // android-changed + if (result.length() != 0) result.append(' '); result.append(type.getName()); result.append(' '); result.append(declaringClass.getName()); result.append('.'); result.append(name); - + return result.toString(); } - - private native Object getField(Object o, Class<?> declaringClass, Class<?> type, - int slot, boolean noAccessCheck) throws IllegalAccessException; - private native double getDField(Object o, Class<?> declaringClass, Class<?> type, - int slot, boolean noAccessCheck, int type_no) - throws IllegalAccessException; + private native Object getField(Object o, Class<?> declaringClass, Class<?> type, int slot, + boolean noAccessCheck) throws IllegalAccessException; - private native int getIField(Object o, Class<?> declaringClass, Class<?> type, - int slot, boolean noAccessCheck, int type_no) - throws IllegalAccessException; + private native double getDField(Object o, Class<?> declaringClass, Class<?> type, int slot, + boolean noAccessCheck, int type_no) throws IllegalAccessException; - private native long getJField(Object o, Class<?> declaringClass, Class<?> type, - int slot, boolean noAccessCheck, int type_no) - throws IllegalAccessException; + private native int getIField(Object o, Class<?> declaringClass, Class<?> type, int slot, + boolean noAccessCheck, int type_no) throws IllegalAccessException; - private native boolean getZField(Object o, Class<?> declaringClass, - Class<?> type, int slot, boolean noAccessCheck, int type_no) - throws IllegalAccessException; + private native long getJField(Object o, Class<?> declaringClass, Class<?> type, int slot, + boolean noAccessCheck, int type_no) throws IllegalAccessException; - private native float getFField(Object o, Class<?> declaringClass, Class<?> type, - int slot, boolean noAccessCheck, int type_no) - throws IllegalAccessException; + private native boolean getZField(Object o, Class<?> declaringClass, Class<?> type, int slot, + boolean noAccessCheck, int type_no) throws IllegalAccessException; - private native char getCField(Object o, Class<?> declaringClass, Class<?> type, - int slot, boolean noAccessCheck, int type_no) - throws IllegalAccessException; + private native float getFField(Object o, Class<?> declaringClass, Class<?> type, int slot, + boolean noAccessCheck, int type_no) throws IllegalAccessException; - private native short getSField(Object o, Class<?> declaringClass, Class<?> type, - int slot, boolean noAccessCheck, int type_no) - throws IllegalAccessException; + private native char getCField(Object o, Class<?> declaringClass, Class<?> type, int slot, + boolean noAccessCheck, int type_no) throws IllegalAccessException; - private native byte getBField(Object o, Class<?> declaringClass, Class<?> type, - int slot, boolean noAccessCheck, int type_no) - throws IllegalAccessException; + private native short getSField(Object o, Class<?> declaringClass, Class<?> type, int slot, + boolean noAccessCheck, int type_no) throws IllegalAccessException; - private native void setField(Object o, Class<?> declaringClass, Class<?> type, - int slot, boolean noAccessCheck, Object value) - throws IllegalAccessException; + private native byte getBField(Object o, Class<?> declaringClass, Class<?> type, int slot, + boolean noAccessCheck, int type_no) throws IllegalAccessException; - private native void setDField(Object o, Class<?> declaringClass, Class<?> type, - int slot, boolean noAccessCheck, int type_no, double v) - throws IllegalAccessException; + private native void setField(Object o, Class<?> declaringClass, Class<?> type, int slot, + boolean noAccessCheck, Object value) throws IllegalAccessException; - private native void setIField(Object o, Class<?> declaringClass, Class<?> type, - int slot, boolean noAccessCheck, int type_no, int i) - throws IllegalAccessException; + private native void setDField(Object o, Class<?> declaringClass, Class<?> type, int slot, + boolean noAccessCheck, int type_no, double v) throws IllegalAccessException; - private native void setJField(Object o, Class<?> declaringClass, Class<?> type, - int slot, boolean noAccessCheck, int type_no, long j) - throws IllegalAccessException; + private native void setIField(Object o, Class<?> declaringClass, Class<?> type, int slot, + boolean noAccessCheck, int type_no, int i) throws IllegalAccessException; - private native void setZField(Object o, Class<?> declaringClass, Class<?> type, - int slot, boolean noAccessCheck, int type_no, boolean z) - throws IllegalAccessException; + private native void setJField(Object o, Class<?> declaringClass, Class<?> type, int slot, + boolean noAccessCheck, int type_no, long j) throws IllegalAccessException; - private native void setFField(Object o, Class<?> declaringClass, Class<?> type, - int slot, boolean noAccessCheck, int type_no, float f) - throws IllegalAccessException; + private native void setZField(Object o, Class<?> declaringClass, Class<?> type, int slot, + boolean noAccessCheck, int type_no, boolean z) throws IllegalAccessException; - private native void setCField(Object o, Class<?> declaringClass, Class<?> type, - int slot, boolean noAccessCheck, int type_no, char c) - throws IllegalAccessException; + private native void setFField(Object o, Class<?> declaringClass, Class<?> type, int slot, + boolean noAccessCheck, int type_no, float f) throws IllegalAccessException; - private native void setSField(Object o, Class<?> declaringClass, Class<?> type, - int slot, boolean noAccessCheck, int type_no, short s) - throws IllegalAccessException; + private native void setCField(Object o, Class<?> declaringClass, Class<?> type, int slot, + boolean noAccessCheck, int type_no, char c) throws IllegalAccessException; + + private native void setSField(Object o, Class<?> declaringClass, Class<?> type, int slot, + boolean noAccessCheck, int type_no, short s) throws IllegalAccessException; + + private native void setBField(Object o, Class<?> declaringClass, Class<?> type, int slot, + boolean noAccessCheck, int type_no, byte b) throws IllegalAccessException; - private native void setBField(Object o, Class<?> declaringClass, Class<?> type, - int slot, boolean noAccessCheck, int type_no, byte b) - throws IllegalAccessException; - } diff --git a/luni-kernel/src/main/java/java/lang/reflect/Method.java b/luni-kernel/src/main/java/java/lang/reflect/Method.java index 3facca5..7fc0322 100644 --- a/luni-kernel/src/main/java/java/lang/reflect/Method.java +++ b/luni-kernel/src/main/java/java/lang/reflect/Method.java @@ -14,22 +14,36 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package java.lang.reflect; -// BEGIN android-added +import java.lang.annotation.Annotation; + import org.apache.harmony.kernel.vm.StringUtils; import org.apache.harmony.luni.lang.reflect.GenericSignatureParser; import org.apache.harmony.luni.lang.reflect.ListOfTypes; import org.apache.harmony.luni.lang.reflect.Types; -// END android-added - -import java.lang.annotation.Annotation; - /** - * This class models a method. Information about the method can be accessed, and - * the method can be invoked dynamically. + * This class represents a method. Information about the method can be accessed, + * and the method can be invoked dynamically. + * + * @since Android 1.0 */ public final class Method extends AccessibleObject implements GenericDeclaration, Member { @@ -45,7 +59,6 @@ public final class Method extends AccessibleObject implements GenericDeclaration private Class<?> returnType; - // BEGIN android-added private ListOfTypes genericExceptionTypes; private ListOfTypes genericParameterTypes; private Type genericReturnType; @@ -64,21 +77,10 @@ public final class Method extends AccessibleObject implements GenericDeclaration genericTypesAreInitialized = true; } } - // END android-added - - // BEGIN android-removed - /** - * Prevent this class from being instantiated - */ - //private Method(){ - //do nothing - //} - // END android-removed - // BEGIN android-added /** * Construct a clone of the given instance. - * + * * @param orig non-null; the original instance to clone */ /*package*/ Method(Method orig) { @@ -90,7 +92,6 @@ public final class Method extends AccessibleObject implements GenericDeclaration this.flag = true; } } - // END android-added private Method(Class<?> declaring, Class<?>[] paramTypes, Class<?>[] exceptTypes, Class<?> returnType, String name, int slot) { @@ -103,14 +104,10 @@ public final class Method extends AccessibleObject implements GenericDeclaration } public TypeVariable<Method>[] getTypeParameters() { - // BEGIN android-changed initGenericTypes(); return formalTypeParameters.clone(); - // END android-changed } - // BEGIN android-changed - /** {@inheritDoc} */ @Override /*package*/ String getSignatureAttribute() { Object[] annotation = getSignatureAnnotation(declaringClass, slot); @@ -123,25 +120,21 @@ public final class Method extends AccessibleObject implements GenericDeclaration } /** - * Gets the Signature annotation for this method. Returns null if + * Returns the Signature annotation for this method. Returns {@code null} if * not found. */ native private Object[] getSignatureAnnotation(Class declaringClass, int slot); - // END android-changed - /** - * <p> - * Returns the String representation of the method's declaration, including + * Returns the string representation of the method's declaration, including * the type parameters. - * </p> + * + * @return the string representation of this method * - * @return An instance of String. - * @since 1.5 + * @since Android 1.0 */ public String toGenericString() { - // BEGIN android-changed StringBuilder sb = new StringBuilder(80); initGenericTypes(); @@ -174,7 +167,7 @@ public final class Method extends AccessibleObject implements GenericDeclaration appendArrayGenericType(sb, Types.getClonedTypeArray(genericParameterTypes)); sb.append(')'); - // append exeptions if any + // append exceptions if any Type[] genericExceptionTypeArray = Types.getClonedTypeArray( genericExceptionTypes); if (genericExceptionTypeArray.length > 0) { @@ -182,73 +175,69 @@ public final class Method extends AccessibleObject implements GenericDeclaration appendArrayGenericType(sb, genericExceptionTypeArray); } return sb.toString(); - // END android-changed } /** - * <p> - * Gets the parameter types as an array of {@link Type} instances, in - * declaration order. If the method has no parameters, then an empty array - * is returned. - * </p> - * - * @return An array of {@link Type} instances. - * @throws GenericSignatureFormatError if the generic method signature is - * invalid. - * @throws TypeNotPresentException if the component type points to a missing - * type. - * @throws MalformedParameterizedTypeException if the component type points - * to a type that can't be instantiated for some reason. - * @since 1.5 + * Returns the parameter types as an array of {@code Type} instances, in + * declaration order. If this method has no parameters, an empty array is + * returned. + * + * @return the parameter types + * + * @throws GenericSignatureFormatError + * if the generic method signature is invalid + * @throws TypeNotPresentException + * if any parameter type points to a missing type + * @throws MalformedParameterizedTypeException + * if any parameter type points to a type that cannot be + * instantiated for some reason + * + * @since Android 1.0 */ public Type[] getGenericParameterTypes() { - // BEGIN android-changed initGenericTypes(); return Types.getClonedTypeArray(genericParameterTypes); - // END android-changed } /** - * <p> - * Gets the exception types as an array of {@link Type} instances. If the - * method has no declared exceptions, then an empty array is returned. - * </p> - * - * @return An array of {@link Type} instances. - * @throws GenericSignatureFormatError if the generic method signature is - * invalid. - * @throws TypeNotPresentException if the component type points to a missing - * type. - * @throws MalformedParameterizedTypeException if the component type points - * to a type that can't be instantiated for some reason. - * @since 1.5 + * Returns the exception types as an array of {@code Type} instances. If + * this method has no declared exceptions, an empty array will be returned. + * + * @return an array of generic exception types + * + * @throws GenericSignatureFormatError + * if the generic method signature is invalid + * @throws TypeNotPresentException + * if any exception type points to a missing type + * @throws MalformedParameterizedTypeException + * if any exception type points to a type that cannot be + * instantiated for some reason + * + * @since Android 1.0 */ public Type[] getGenericExceptionTypes() { - // BEGIN android-changed initGenericTypes(); return Types.getClonedTypeArray(genericExceptionTypes); - // END android-changed } /** - * <p> - * Gets the return type as a {@link Type} instance. - * </p> - * - * @return A {@link Type} instance. - * @throws GenericSignatureFormatError if the generic method signature is - * invalid. - * @throws TypeNotPresentException if the component type points to a missing - * type. - * @throws MalformedParameterizedTypeException if the component type points - * to a type that can't be instantiated for some reason. - * @since 1.5 + * Returns the return type of this method as a {@code Type} instance. + * + * @return the return type of this method + * + * @throws GenericSignatureFormatError + * if the generic method signature is invalid + * @throws TypeNotPresentException + * if the return type points to a missing type + * @throws MalformedParameterizedTypeException + * if the return type points to a type that cannot be + * instantiated for some reason + * + * @since Android 1.0 */ public Type getGenericReturnType() { - // BEGIN android-changed initGenericTypes(); return Types.getType(genericReturnType); - // END android-changed } @Override @@ -258,7 +247,6 @@ public final class Method extends AccessibleObject implements GenericDeclaration native private Annotation[] getDeclaredAnnotations(Class declaringClass, int slot); -// BEGIN android-added private static final Annotation[] NO_ANNOTATIONS = new Annotation[0]; /** @@ -271,27 +259,23 @@ public final class Method extends AccessibleObject implements GenericDeclaration } return annotations; } -// END android-added /** - * <p> - * Gets an array of arrays that represent the annotations of the formal + * Returns an array of arrays that represent the annotations of the formal * parameters of this method. If there are no parameters on this method, * then an empty array is returned. If there are no annotations set, then * and array of empty arrays is returned. - * </p> + * + * @return an array of arrays of {@code Annotation} instances * - * @return An array of arrays of {@link Annotation} instances. - * @since 1.5 + * @since Android 1.0 */ public Annotation[][] getParameterAnnotations() { -// BEGIN android-changed Annotation[][] parameterAnnotations = getParameterAnnotations(declaringClass, slot); if (parameterAnnotations.length == 0) { return noAnnotations(parameterTypes.length); } -// END android-changed return parameterAnnotations; } @@ -299,13 +283,11 @@ public final class Method extends AccessibleObject implements GenericDeclaration int slot); /** - * <p> * Indicates whether or not this method takes a variable number argument. - * </p> + * + * @return {@code true} if a vararg is declared, {@code false} otherwise * - * @return A value of <code>true</code> if a vararg is declare, otherwise - * <code>false</code>. - * @since 1.5 + * @since Android 1.0 */ public boolean isVarArgs() { int modifiers = getMethodModifiers(declaringClass, slot); @@ -313,13 +295,11 @@ public final class Method extends AccessibleObject implements GenericDeclaration } /** - * <p> * Indicates whether or not this method is a bridge. - * </p> + * + * @return {@code true} if this method is a bridge, {@code false} otherwise * - * @return A value of <code>true</code> if this method's a bridge, - * otherwise <code>false</code>. - * @since 1.5 + * @since Android 1.0 */ public boolean isBridge() { int modifiers = getMethodModifiers(declaringClass, slot); @@ -327,26 +307,28 @@ public final class Method extends AccessibleObject implements GenericDeclaration } /** - * <p> * Indicates whether or not this method is synthetic. - * </p> + * + * @return {@code true} if this method is synthetic, {@code false} otherwise * - * @return A value of <code>true</code> if this method is synthetic, - * otherwise <code>false</code>. - * @since 1.5 + * @since Android 1.0 */ public boolean isSynthetic() { int modifiers = getMethodModifiers(declaringClass, slot); return (modifiers & Modifier.SYNTHETIC) != 0; } - + /** - * <p>Gets the default value for the annotation member represented by - * this method.</p> - * @return The default value or <code>null</code> if none. - * @throws TypeNotPresentException if the annotation is of type {@link Class} - * and no definition can be found. - * @since 1.5 + * Returns the default value for the annotation member represented by this + * method. + * + * @return the default value, or {@code null} if none + * + * @throws TypeNotPresentException + * if this annotation member is of type {@code Class} and no + * definition can be found + * + * @since Android 1.0 */ public Object getDefaultValue() { return getDefaultValue(declaringClass, slot); @@ -354,15 +336,20 @@ public final class Method extends AccessibleObject implements GenericDeclaration native private Object getDefaultValue(Class declaringClass, int slot); /** - * Compares the specified object to this Method and determines if they are - * equal. The object must be an instance of Method with the same defining - * class and parameter types. + * Indicates whether or not the specified {@code object} is equal to this + * method. To be equal, the specified object must be an instance + * of {@code Method} with the same declaring class and parameter types + * as this method. * * @param object * the object to compare - * @return true if the specified object is equal to this Method, false - * otherwise + * + * @return {@code true} if the specified object is equal to this + * method, {@code false} otherwise + * * @see #hashCode + * + * @since Android 1.0 */ @Override public boolean equals(Object object) { @@ -370,21 +357,23 @@ public final class Method extends AccessibleObject implements GenericDeclaration } /** - * Return the {@link Class} associated with the class that defined this - * method. - * + * Returns the class that declares this method. + * * @return the declaring class + * + * @since Android 1.0 */ public Class<?> getDeclaringClass() { return declaringClass; } /** - * Return an array of the {@link Class} objects associated with the - * exceptions declared to be thrown by this method. If the method was not - * declared to throw any exceptions, the array returned will be empty. + * Returns the exception types as an array of {@code Class} instances. If + * this method has no declared exceptions, an empty array is returned. * * @return the declared exception classes + * + * @since Android 1.0 */ public Class<?>[] getExceptionTypes() { if (exceptionTypes == null) { @@ -395,55 +384,68 @@ public final class Method extends AccessibleObject implements GenericDeclaration } /** - * Return the modifiers for the modeled method. The Modifier class - * should be used to decode the result. + * Returns the modifiers for this method. The {@link Modifier} class should + * be used to decode the result. + * + * @return the modifiers for this method + * + * @see Modifier * - * @return the modifiers - * @see java.lang.reflect.Modifier + * @since Android 1.0 */ public int getModifiers() { return getMethodModifiers(declaringClass, slot); } private native int getMethodModifiers(Class<?> decl_class, int slot); - + /** - * Return the name of the modeled method. + * Returns the name of the method represented by this {@code Method} + * instance. * - * @return the name + * @return the name of this method + * + * @since Android 1.0 */ public String getName() { return name; } /** - * Return an array of the {@link Class} objects associated with the - * parameter types of this method. If the method was declared with no - * parameters, the array returned will be empty. + * Returns an array of {@code Class} objects associated with the parameter + * types of this method. If the method was declared with no parameters, an + * empty array will be returned. * * @return the parameter types + * + * @since Android 1.0 */ public Class<?>[] getParameterTypes() { return parameterTypes; } /** - * Return the {@link Class} associated with the return type of this + * Returns the {@code Class} associated with the return type of this * method. * * @return the return type + * + * @since Android 1.0 */ public Class<?> getReturnType() { return returnType; } /** - * Returns an integer hash code for the receiver. Objects which are equal - * return the same value for this method. The hash code for a Method is the - * hash code of the method's name. + * Returns an integer hash code for this method. Objects which are equal + * return the same value for this method. The hash code for this Method is + * the hash code of the name of this method. + * + * @return hash code for this method * - * @return the receiver's hash * @see #equals + * + * @since Android 1.0 */ @Override public int hashCode() { @@ -451,59 +453,60 @@ public final class Method extends AccessibleObject implements GenericDeclaration } /** - * Return the result of dynamically invoking the modeled method. This - * reproduces the effect of - * <code>receiver.methodName(arg1, arg2, ... , argN)</code> This method - * performs the following: + * Returns the result of dynamically invoking this method. This reproduces + * the effect of {@code receiver.methodName(arg1, arg2, ... , argN)} This + * method performs the following: * <ul> - * <li>If the modeled method is static, the receiver argument is ignored. + * <li>If this method is static, the receiver argument is ignored.</li> + * <li>Otherwise, if the receiver is null, a NullPointerException is thrown. * </li> - * <li>Otherwise, if the receiver is null, a NullPointerException is - * thrown.</li> - * If the receiver is not an instance of the declaring class of the method, - * an IllegalArgumentException is thrown. + * <li>If the receiver is not an instance of the declaring class of the + * method, an IllegalArgumentException is thrown.</li> * <li>If this Method object is enforcing access control (see - * AccessibleObject) and the modeled method is not accessible from the - * current context, an IllegalAccessException is thrown.</li> - * <li>If the number of arguments passed and the number of parameters do - * not match, an IllegalArgumentException is thrown.</li> + * AccessibleObject) and this method is not accessible from the current + * context, an IllegalAccessException is thrown.</li> + * <li>If the number of arguments passed and the number of parameters do not + * match, an IllegalArgumentException is thrown.</li> * <li>For each argument passed: * <ul> - * <li>If the corresponding parameter type is a base type, the argument is - * unwrapped. If the unwrapping fails, an IllegalArgumentException is + * <li>If the corresponding parameter type is a primitive type, the argument + * is unwrapped. If the unwrapping fails, an IllegalArgumentException is * thrown.</li> * <li>If the resulting argument cannot be converted to the parameter type * via a widening conversion, an IllegalArgumentException is thrown.</li> * </ul> - * <li>If the modeled method is static, it is invoked directly. If it is - * non-static, the modeled method and the receiver are then used to perform - * a standard dynamic method lookup. The resulting method is then invoked. - * </li> + * <li>If this method is static, it is invoked directly. If it is + * non-static, this method and the receiver are then used to perform a + * standard dynamic method lookup. The resulting method is then invoked.</li> * <li>If an exception is thrown during the invocation it is caught and - * wrapped in an InvocationTargetException. This exception is then thrown. - * </li> - * <li>If the invocation completes normally, the return value is itself - * returned. If the method is declared to return a base type, the return - * value is first wrapped. If the return type is void, null is returned. - * </li> + * wrapped in an InvocationTargetException. This exception is then thrown.</li> + * <li>If the invocation completes normally, the return value itself is + * returned. If the method is declared to return a primitive type, the + * return value is first wrapped. If the return type is void, null is + * returned.</li> * </ul> * * @param receiver - * The object on which to call the modeled method + * the object on which to call this method * @param args * the arguments to the method + * * @return the new, initialized, object - * @throws java.lang.NullPointerException - * if the receiver is null for a non-static method - * @throws java.lang.IllegalAccessException - * if the modeled method is not accessible - * @throws java.lang.IllegalArgumentException - * if an incorrect number of arguments are passed, the - * receiver is incompatible with the declaring class, or an - * argument could not be converted by a widening conversion - * @throws java.lang.reflect.InvocationTargetException - * if an exception was thrown by the invoked method - * @see java.lang.reflect.AccessibleObject + * + * @throws NullPointerException + * if the receiver is null for a non-static method + * @throws IllegalAccessException + * if this method is not accessible + * @throws IllegalArgumentException + * if an incorrect number of arguments are passed, the receiver + * is incompatible with the declaring class, or an argument + * could not be converted by a widening conversion + * @throws InvocationTargetException + * if an exception was thrown by the invoked method + * + * @see AccessibleObject + * + * @since Android 1.0 */ public Object invoke(Object receiver, Object... args) throws IllegalAccessException, IllegalArgumentException, @@ -519,22 +522,35 @@ public final class Method extends AccessibleObject implements GenericDeclaration throws IllegalAccessException, IllegalArgumentException, InvocationTargetException; - + /** - * Returns a string containing a concise, human-readable description of the - * receiver. The format of the string is modifiers (if any) return type - * declaring class name '.' method name '(' parameter types, separated by - * ',' ')' If the method throws exceptions, ' throws ' exception types, - * separated by ',' For example: - * <code>public native Object java.lang.Method.invoke(Object,Object) throws IllegalAccessException,IllegalArgumentException,InvocationTargetException</code> - * - * @return a printable representation for the receiver + * Returns a string containing a concise, human-readable description of this + * method. The format of the string is: + * + * <ol> + * <li>modifiers (if any) + * <li>return type or 'void' + * <li>declaring class name + * <li>'(' + * <li>parameter types, separated by ',' (if any) + * <li>')' + * <li>'throws' plus exception types, separated by ',' (if any) + * </ol> + * + * For example: {@code public native Object + * java.lang.Method.invoke(Object,Object) throws + * IllegalAccessException,IllegalArgumentException + * ,InvocationTargetException} + * + * @return a printable representation for this method + * + * @since Android 1.0 */ @Override public String toString() { StringBuilder result = new StringBuilder(Modifier.toString(getModifiers())); - if (result.length() != 0) // android-changed + if (result.length() != 0) result.append(' '); result.append(returnType.getName()); result.append(' '); @@ -556,7 +572,7 @@ public final class Method extends AccessibleObject implements GenericDeclaration * Returns the constructor's signature in non-printable form. This is called * (only) from IO native code and needed for deriving the serialVersionUID * of the class - * + * * @return The constructor's signature. */ @SuppressWarnings("unused") diff --git a/luni-kernel/src/main/java/java/lang/reflect/ReflectionAccessImpl.java b/luni-kernel/src/main/java/java/lang/reflect/ReflectionAccessImpl.java index 6e5bc05..15cd798 100644 --- a/luni-kernel/src/main/java/java/lang/reflect/ReflectionAccessImpl.java +++ b/luni-kernel/src/main/java/java/lang/reflect/ReflectionAccessImpl.java @@ -19,34 +19,35 @@ package java.lang.reflect; import org.apache.harmony.kernel.vm.ReflectionAccess; /** - * Implementation of bridge from <code>java.lang</code> to - * <code>java.lang.reflect</code>. + * Implementation of bridge from {@code java.lang} to + * {@code java.lang.reflect}. */ /*package*/ final class ReflectionAccessImpl implements ReflectionAccess { /** non-null; unique instance of this class */ /*package*/ static final ReflectionAccessImpl THE_ONE = new ReflectionAccessImpl(); - /** + /** * This class is not publicly instantiable. Use {@link #THE_ONE}. */ private ReflectionAccessImpl() { // This space intentionally left blank. } - /** {@inheritDoc} */ public Method clone(Method method) { return new Method(method); } - /** {@inheritDoc} */ + public Field clone(Field field) { + return new Field(field); + } + public Method accessibleClone(Method method) { Method result = new Method(method); result.setAccessibleNoCheck(true); return result; } - /** {@inheritDoc} */ public void setAccessibleNoCheck(AccessibleObject ao, boolean accessible) { ao.setAccessibleNoCheck(accessible); } diff --git a/luni-kernel/src/main/java/org/apache/harmony/kernel/vm/ReflectionAccess.java b/luni-kernel/src/main/java/org/apache/harmony/kernel/vm/ReflectionAccess.java index b16df3e..1487ba1 100644 --- a/luni-kernel/src/main/java/org/apache/harmony/kernel/vm/ReflectionAccess.java +++ b/luni-kernel/src/main/java/org/apache/harmony/kernel/vm/ReflectionAccess.java @@ -17,6 +17,7 @@ package org.apache.harmony.kernel.vm; import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Field; import java.lang.reflect.Method; /** @@ -35,6 +36,14 @@ public interface ReflectionAccess { public Method clone(Method method); /** + * Gets a clone of the given field. + * + * @param field non-null; the field to clone + * @return non-null; the clone + */ + public Field clone(Field field); + + /** * Gets a clone of the given method, where the clone has * its "accessible" flag set to <code>true</code> * diff --git a/luni-kernel/src/main/java/org/apache/harmony/lang/annotation/AnnotationFactory.java b/luni-kernel/src/main/java/org/apache/harmony/lang/annotation/AnnotationFactory.java index 06b1727..a898f54 100644 --- a/luni-kernel/src/main/java/org/apache/harmony/lang/annotation/AnnotationFactory.java +++ b/luni-kernel/src/main/java/org/apache/harmony/lang/annotation/AnnotationFactory.java @@ -102,7 +102,7 @@ public final class AnnotationFactory implements InvocationHandler, Serializable new Class[]{annotationType}, antn); } - private final Class<? extends Annotation> klazz; + private final Class<? extends Annotation> klazz; private AnnotationMember[] elements; /** @@ -114,7 +114,7 @@ public final class AnnotationFactory implements InvocationHandler, Serializable * @param values actual element values */ private AnnotationFactory(Class<? extends Annotation> klzz, AnnotationMember[] values) { - klazz = klzz; + klazz = klzz; AnnotationMember[] defs = getElementsDescription(klazz); if (values == null) { elements = defs; @@ -131,7 +131,7 @@ public final class AnnotationFactory implements InvocationHandler, Serializable elements[i] = defs[i]; } } - } + } /** * Reads the object, obtains actual member definitions for the annotation type, @@ -171,7 +171,7 @@ public final class AnnotationFactory implements InvocationHandler, Serializable } elements = merged.toArray(new AnnotationMember[merged.size()]); } - + /** * Returns true if the specified object represents the same annotation instance. * That is, if it implements the same annotation type and @@ -182,19 +182,19 @@ public final class AnnotationFactory implements InvocationHandler, Serializable * false otherwise. * @see android.lang.annotation.AnnotationMember#equals(Object) */ - public boolean equals(Object obj) { - if (obj == this) { - return true; + public boolean equals(Object obj) { + if (obj == this) { + return true; } if (!klazz.isInstance(obj)) { return false; } Object handler = null; - if (Proxy.isProxyClass(obj.getClass()) + if (Proxy.isProxyClass(obj.getClass()) && (handler = Proxy.getInvocationHandler(obj)) instanceof AnnotationFactory ) { AnnotationFactory other = (AnnotationFactory) handler; - if (elements.length != other.elements.length) { - return false; + if (elements.length != other.elements.length) { + return false; } next: for (AnnotationMember el1 : elements){ for (AnnotationMember el2 : other.elements) { @@ -245,36 +245,36 @@ public final class AnnotationFactory implements InvocationHandler, Serializable } return true; } - } + } /** * Returns a hash code composed as a sum of hash codes of member elements, * including elements with default values. * @see android.lang.annotation.AnnotationMember#hashCode() */ - public int hashCode() { - int hash = 0; + public int hashCode() { + int hash = 0; for (AnnotationMember element : elements) { hash += element.hashCode(); } return hash; - } + } /** * Provides detailed description of this annotation instance, * including all member name-values pairs. * @return string representation of this annotation */ - public String toString() { - String res = "@" + klazz.getName() + "("; - for(int i = 0; i < elements.length; i++) { + public String toString() { + String res = "@" + klazz.getName() + "("; + for(int i = 0; i < elements.length; i++) { if ( i != 0 ) { res += ", "; } res += elements[i].toString();; } return res + ")"; - } + } /** * Processes a method invocation request to this annotation instance. @@ -314,8 +314,8 @@ public final class AnnotationFactory implements InvocationHandler, Serializable } return value; } - } else if (params.length == 1 && params[0] == Object.class && "equals".equals(name)){ - return Boolean.valueOf(equals(args[0])); + } else if (params.length == 1 && params[0] == Object.class && "equals".equals(name)){ + return Boolean.valueOf(equals(args[0])); } throw new IllegalArgumentException( "Invalid method for annotation type: " + method); diff --git a/luni-kernel/src/main/native/java_lang_System.c b/luni-kernel/src/main/native/java_lang_System.c index 53d1898..1c06a40 100644 --- a/luni-kernel/src/main/native/java_lang_System.c +++ b/luni-kernel/src/main/native/java_lang_System.c @@ -1,11 +1,20 @@ -// -// java_lang_System.c -// Android -// -// Copyright 2006 The Android Open Source Project -// +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #include "JNIHelp.h" -//#include "utils/Log.h" #include <stdlib.h> #include <string.h> @@ -53,10 +62,7 @@ static jstring java_getEnvByIndex(JNIEnv* env, jclass clazz, jint index) { jstring valueStr = NULL; - /* TODO: Commented out because it makes the Mac simulator unhappy. - * char* entry = environ[index]; - */ - char* entry = NULL; + char* entry = environ[index]; if (entry != NULL) { valueStr = (*env)->NewStringUTF(env, entry); } diff --git a/luni-kernel/src/test/java/tests/api/org/apache/harmony/kernel/dalvik/ThreadsTest.java b/luni-kernel/src/test/java/tests/api/org/apache/harmony/kernel/dalvik/ThreadsTest.java index 46782e0..a3e2bd3 100644 --- a/luni-kernel/src/test/java/tests/api/org/apache/harmony/kernel/dalvik/ThreadsTest.java +++ b/luni-kernel/src/test/java/tests/api/org/apache/harmony/kernel/dalvik/ThreadsTest.java @@ -16,6 +16,8 @@ package tests.api.org.apache.harmony.kernel.dalvik; +import dalvik.annotation.TestTargetClass; + import junit.framework.Assert; import junit.framework.TestCase; @@ -26,6 +28,7 @@ import java.lang.reflect.Field; /** * Tests for the <code>park()</code> functionality of {@link Unsafe}. */ +@TestTargetClass(Unsafe.class) public class ThreadsTest extends TestCase { private static Unsafe UNSAFE = null; |