diff options
author | jfrijters <jfrijters> | 2014-07-07 11:40:35 +0400 |
---|---|---|
committer | jfrijters <jfrijters> | 2014-07-07 11:40:35 +0400 |
commit | 5ed36cd631b3d8de24c9ca6dee81476959620eaa (patch) | |
tree | 004d6a89108ccd48a0186acd03bcfd5b3a555e92 | |
parent | f1fdf20be306e59b28d645e003d6d83f15f2d02d (diff) |
Simplified the anonymous class name mangling.
-rw-r--r-- | openjdk/java/lang/Class.java | 1585 | ||||
-rw-r--r-- | runtime/DynamicClassLoader.cs | 126 | ||||
-rw-r--r-- | runtime/TypeWrapper.cs | 7 | ||||
-rw-r--r-- | runtime/openjdk/java.lang.cs | 8 |
4 files changed, 1034 insertions, 692 deletions
diff --git a/openjdk/java/lang/Class.java b/openjdk/java/lang/Class.java index bbc1d241..07fd7bd5 100644 --- a/openjdk/java/lang/Class.java +++ b/openjdk/java/lang/Class.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,17 +25,20 @@ package java.lang; +import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Array; import java.lang.reflect.GenericArrayType; +import java.lang.reflect.GenericDeclaration; import java.lang.reflect.Member; import java.lang.reflect.Field; +import java.lang.reflect.Executable; import java.lang.reflect.Method; import java.lang.reflect.Constructor; -import java.lang.reflect.GenericDeclaration; import java.lang.reflect.Modifier; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.AnnotatedType; import java.lang.ref.SoftReference; import java.io.InputStream; import java.io.ObjectStreamField; @@ -45,19 +48,17 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; -import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.List; -import java.util.LinkedList; -import java.util.LinkedHashSet; import java.util.Set; import java.util.Map; import java.util.HashMap; +import java.util.Objects; import sun.misc.Unsafe; import sun.reflect.CallerSensitive; import sun.reflect.ConstantPool; import sun.reflect.Reflection; import sun.reflect.ReflectionFactory; -import sun.reflect.SignatureIterator; import sun.reflect.generics.factory.CoreReflectionFactory; import sun.reflect.generics.factory.GenericsFactory; import sun.reflect.generics.repository.ClassRepository; @@ -151,7 +152,7 @@ final class ClassSerializationProxy implements IObjectReference * <p> The following example uses a {@code Class} object to print the * class name of an object: * - * <p> <blockquote><pre> + * <blockquote><pre> * void printClassName(Object obj) { * System.out.println("The class of " + obj + * " is " + obj.getClass().getName()); @@ -163,7 +164,7 @@ final class ClassSerializationProxy implements IObjectReference * <cite>The Java™ Language Specification</cite>. * For example: * - * <p> <blockquote> + * <blockquote> * {@code System.out.println("The name of class Foo is: "+Foo.class.getName());} * </blockquote> * @@ -177,11 +178,10 @@ final class ClassSerializationProxy implements IObjectReference * @since JDK1.0 */ @cli.System.SerializableAttribute.Annotation -public final - class Class<T> implements java.io.Serializable, - java.lang.reflect.GenericDeclaration, - java.lang.reflect.Type, - java.lang.reflect.AnnotatedElement { +public final class Class<T> implements java.io.Serializable, + GenericDeclaration, + Type, + AnnotatedElement { private static final int ANNOTATION= 0x00002000; private static final int ENUM = 0x00004000; private static final int SYNTHETIC = 0x00001000; @@ -252,6 +252,75 @@ public final + getName(); } + /** + * Returns a string describing this {@code Class}, including + * information about modifiers and type parameters. + * + * The string is formatted as a list of type modifiers, if any, + * followed by the kind of type (empty string for primitive types + * and {@code class}, {@code enum}, {@code interface}, or + * <code>@</code>{@code interface}, as appropriate), followed + * by the type's name, followed by an angle-bracketed + * comma-separated list of the type's type parameters, if any. + * + * A space is used to separate modifiers from one another and to + * separate any modifiers from the kind of type. The modifiers + * occur in canonical order. If there are no type parameters, the + * type parameter list is elided. + * + * <p>Note that since information about the runtime representation + * of a type is being generated, modifiers not present on the + * originating source code or illegal on the originating source + * code may be present. + * + * @return a string describing this {@code Class}, including + * information about modifiers and type parameters + * + * @since 1.8 + */ + public String toGenericString() { + if (isPrimitive()) { + return toString(); + } else { + StringBuilder sb = new StringBuilder(); + + // Class modifiers are a superset of interface modifiers + int modifiers = getModifiers() & Modifier.classModifiers(); + if (modifiers != 0) { + sb.append(Modifier.toString(modifiers)); + sb.append(' '); + } + + if (isAnnotation()) { + sb.append('@'); + } + if (isInterface()) { // Note: all annotation types are interfaces + sb.append("interface"); + } else { + if (isEnum()) + sb.append("enum"); + else + sb.append("class"); + } + sb.append(' '); + sb.append(getName()); + + TypeVariable<?>[] typeparms = getTypeParameters(); + if (typeparms.length > 0) { + boolean first = true; + sb.append('<'); + for(TypeVariable<?> typeparm: typeparms) { + if (!first) + sb.append(','); + sb.append(typeparm.getTypeName()); + first = false; + } + sb.append('>'); + } + + return sb.toString(); + } + } /** * Returns the {@code Class} object associated with the class or @@ -338,7 +407,8 @@ public final * ensure it's ok to access the bootstrap class loader. * * @param name fully qualified name of the desired class - * @param initialize whether the class must be initialized + * @param initialize if {@code true} the class will be initialized. + * See Section 12.4 of <em>The Java Language Specification</em>. * @param loader class loader from which the class must be loaded * @return class object representing the desired class * @@ -357,11 +427,11 @@ public final ClassLoader loader) throws ClassNotFoundException { - if (loader == null) { + if (sun.misc.VM.isSystemDomainLoader(loader)) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { ClassLoader ccl = ClassLoader.getClassLoader(Reflection.getCallerClass()); - if (ccl != null) { + if (!sun.misc.VM.isSystemDomainLoader(ccl)) { sm.checkPermission( SecurityConstants.GET_CLASSLOADER_PERMISSION); } @@ -391,36 +461,24 @@ public final * any exception thrown by the constructor in a (checked) {@link * java.lang.reflect.InvocationTargetException}. * - * @return a newly allocated instance of the class represented by this - * object. - * @exception IllegalAccessException if the class or its nullary - * constructor is not accessible. - * @exception InstantiationException - * if this {@code Class} represents an abstract class, - * an interface, an array class, a primitive type, or void; - * or if the class has no nullary constructor; - * or if the instantiation fails for some other reason. - * @exception ExceptionInInitializerError if the initialization - * provoked by this method fails. - * @exception SecurityException - * If a security manager, <i>s</i>, is present and any of the - * following conditions is met: - * - * <ul> - * - * <li> invocation of - * {@link SecurityManager#checkMemberAccess - * s.checkMemberAccess(this, Member.PUBLIC)} denies - * creation of new instances of this class - * - * <li> the caller's class loader is not the same as or an - * ancestor of the class loader for the current class and - * invocation of {@link SecurityManager#checkPackageAccess - * s.checkPackageAccess()} denies access to the package - * of this class - * - * </ul> - * + * @return a newly allocated instance of the class represented by this + * object. + * @throws IllegalAccessException if the class or its nullary + * constructor is not accessible. + * @throws InstantiationException + * if this {@code Class} represents an abstract class, + * an interface, an array class, a primitive type, or void; + * or if the class has no nullary constructor; + * or if the instantiation fails for some other reason. + * @throws ExceptionInInitializerError if the initialization + * provoked by this method fails. + * @throws SecurityException + * If a security manager, <i>s</i>, is present and + * the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of this class. */ @CallerSensitive public T newInstance() @@ -456,7 +514,8 @@ public final }); cachedConstructor = c; } catch (NoSuchMethodException e) { - throw new InstantiationException(getName()); + throw (InstantiationException) + new InstantiationException(getName()).initCause(e); } } Constructor<T> tmpConstructor = cachedConstructor; @@ -610,6 +669,7 @@ public final * returns {@code false} otherwise. * @return {@code true} if and only if this class is a synthetic class as * defined by the Java Language Specification. + * @jls 13.1 The Form of a Binary * @since 1.5 */ public boolean isSynthetic() { @@ -735,9 +795,11 @@ public final * <cite>The Java™ Virtual Machine Specification</cite> * @since 1.5 */ + @SuppressWarnings("unchecked") public TypeVariable<Class<T>>[] getTypeParameters() { - if (getGenericSignature() != null) - return (TypeVariable<Class<T>>[])getGenericInfo().getTypeParameters(); + ClassRepository info = getGenericInfo(); + if (info != null) + return (TypeVariable<Class<T>>[])info.getTypeParameters(); else return (TypeVariable<Class<T>>[])new TypeVariable<?>[0]; } @@ -787,15 +849,19 @@ public final * @since 1.5 */ public Type getGenericSuperclass() { - if (getGenericSignature() != null) { - // Historical irregularity: - // Generic signature marks interfaces with superclass = Object - // but this API returns null for interfaces - if (isInterface()) - return null; - return getGenericInfo().getSuperclass(); - } else + ClassRepository info = getGenericInfo(); + if (info == null) { return getSuperclass(); + } + + // Historical irregularity: + // Generic signature marks interfaces with superclass = Object + // but this API returns null for interfaces + if (isInterface()) { + return null; + } + + return info.getSuperclass(); } /** @@ -856,9 +922,29 @@ public final * <p> If this object represents a primitive type or void, the method * returns an array of length 0. * + * <p> If this {@code Class} object represents an array type, the + * interfaces {@code Cloneable} and {@code java.io.Serializable} are + * returned in that order. + * * @return an array of interfaces implemented by this class. */ - public native Class<?>[] getInterfaces(); + public Class<?>[] getInterfaces() { + ReflectionData<T> rd = reflectionData(); + if (rd == null) { + // no cloning required + return getInterfaces0(); + } else { + Class<?>[] interfaces = rd.interfaces; + if (interfaces == null) { + interfaces = getInterfaces0(); + rd.interfaces = interfaces; + } + // defensively copy before handing over to user code + return interfaces.clone(); + } + } + + private native Class<?>[] getInterfaces0(); /** * Returns the {@code Type}s representing the interfaces @@ -910,10 +996,8 @@ public final * @since 1.5 */ public Type[] getGenericInterfaces() { - if (getGenericSignature() != null) - return getGenericInfo().getSuperInterfaces(); - else - return getInterfaces(); + ClassRepository info = getGenericInfo(); + return (info == null) ? getInterfaces() : info.getSuperInterfaces(); } @@ -990,10 +1074,31 @@ public final * * @return the immediately enclosing method of the underlying class, if * that class is a local or anonymous class; otherwise {@code null}. + * + * @throws SecurityException + * If a security manager, <i>s</i>, is present and any of the + * following conditions is met: + * + * <ul> + * + * <li> the caller's class loader is not the same as the + * class loader of the enclosing class and invocation of + * {@link SecurityManager#checkPermission + * s.checkPermission} method with + * {@code RuntimePermission("accessDeclaredMembers")} + * denies access to the methods within the enclosing class + * + * <li> the caller's class loader is not the same as or an + * ancestor of the class loader for the enclosing class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of the enclosing class + * + * </ul> * @since 1.5 */ @CallerSensitive - public Method getEnclosingMethod() { + public Method getEnclosingMethod() throws SecurityException { EnclosingMethodInfo enclosingInfo = getEnclosingMethodInfo(); if (enclosingInfo == null) @@ -1016,11 +1121,6 @@ public final // Perform access check Class<?> enclosingCandidate = enclosingInfo.getEnclosingClass(); - // be very careful not to change the stack depth of this - // checkMemberAccess call for security reasons - // see java.lang.SecurityManager.checkMemberAccess - // - // Note that we need to do this on the enclosing class enclosingCandidate.checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); /* @@ -1088,7 +1188,7 @@ public final descriptor = (String) enclosingInfo[2]; assert((name != null && descriptor != null) || name == descriptor); } catch (ClassCastException cce) { - throw new InternalError("Invalid type in enclosing method information"); + throw new InternalError("Invalid type in enclosing method information", cce); } } @@ -1128,10 +1228,30 @@ public final * * @return the immediately enclosing constructor of the underlying class, if * that class is a local or anonymous class; otherwise {@code null}. + * @throws SecurityException + * If a security manager, <i>s</i>, is present and any of the + * following conditions is met: + * + * <ul> + * + * <li> the caller's class loader is not the same as the + * class loader of the enclosing class and invocation of + * {@link SecurityManager#checkPermission + * s.checkPermission} method with + * {@code RuntimePermission("accessDeclaredMembers")} + * denies access to the constructors within the enclosing class + * + * <li> the caller's class loader is not the same as or an + * ancestor of the class loader for the enclosing class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of the enclosing class + * + * </ul> * @since 1.5 */ @CallerSensitive - public Constructor<?> getEnclosingConstructor() { + public Constructor<?> getEnclosingConstructor() throws SecurityException { EnclosingMethodInfo enclosingInfo = getEnclosingMethodInfo(); if (enclosingInfo == null) @@ -1153,11 +1273,6 @@ public final // Perform access check Class<?> enclosingCandidate = enclosingInfo.getEnclosingClass(); - // be very careful not to change the stack depth of this - // checkMemberAccess call for security reasons - // see java.lang.SecurityManager.checkMemberAccess - // - // Note that we need to do this on the enclosing class enclosingCandidate.checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); /* @@ -1194,9 +1309,25 @@ public final * type, or void,then this method returns null. * * @return the declaring class for this class + * @throws SecurityException + * If a security manager, <i>s</i>, is present and the caller's + * class loader is not the same as or an ancestor of the class + * loader for the declaring class and invocation of {@link + * SecurityManager#checkPackageAccess s.checkPackageAccess()} + * denies access to the package of the declaring class * @since JDK1.1 */ - public native Class<?> getDeclaringClass(); + @CallerSensitive + public Class<?> getDeclaringClass() throws SecurityException { + final Class<?> candidate = getDeclaringClass0(); + + if (candidate != null) + candidate.checkPackageAccess( + ClassLoader.getClassLoader(Reflection.getCallerClass()), true); + return candidate; + } + + private native Class<?> getDeclaringClass0(); /** @@ -1204,10 +1335,16 @@ public final * class. If the underlying class is a top level class this * method returns {@code null}. * @return the immediately enclosing class of the underlying class + * @exception SecurityException + * If a security manager, <i>s</i>, is present and the caller's + * class loader is not the same as or an ancestor of the class + * loader for the enclosing class and invocation of {@link + * SecurityManager#checkPackageAccess s.checkPackageAccess()} + * denies access to the package of the enclosing class * @since 1.5 */ @CallerSensitive - public Class<?> getEnclosingClass() { + public Class<?> getEnclosingClass() throws SecurityException { // There are five kinds of classes (or interfaces): // a) Top level classes // b) Nested classes (static member classes) @@ -1286,6 +1423,32 @@ public final } /** + * Return an informative string for the name of this type. + * + * @return an informative string for the name of this type + * @since 1.8 + */ + public String getTypeName() { + if (isArray()) { + try { + Class<?> cl = this; + int dimensions = 0; + while (cl.isArray()) { + dimensions++; + cl = cl.getComponentType(); + } + StringBuilder sb = new StringBuilder(); + sb.append(cl.getName()); + for (int i = 0; i < dimensions; i++) { + sb.append("[]"); + } + return sb.toString(); + } catch (Throwable e) { /*FALLTHRU*/ } + } + return getName(); + } + + /** * Character.isDigit answers {@code true} to some non-ascii * digits. This one does not. */ @@ -1371,7 +1534,7 @@ public final try { return getName().substring(enclosingClass.getName().length()); } catch (IndexOutOfBoundsException ex) { - throw new InternalError("Malformed class name"); + throw new InternalError("Malformed class name", ex); } } @@ -1398,33 +1561,19 @@ public final * class, or void. * * @return the array of {@code Class} objects representing the public - * members of this class - * @exception SecurityException - * If a security manager, <i>s</i>, is present and any of the - * following conditions is met: - * - * <ul> - * - * <li> invocation of - * {@link SecurityManager#checkMemberAccess - * s.checkMemberAccess(this, Member.PUBLIC)} method - * denies access to the classes within this class - * - * <li> the caller's class loader is not the same as or an - * ancestor of the class loader for the current class and - * invocation of {@link SecurityManager#checkPackageAccess - * s.checkPackageAccess()} denies access to the package - * of this class - * - * </ul> + * members of this class + * @throws SecurityException + * If a security manager, <i>s</i>, is present and + * the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of this class. * * @since JDK1.1 */ @CallerSensitive public Class<?>[] getClasses() { - // be very careful not to change the stack depth of this - // checkMemberAccess call for security reasons - // see java.lang.SecurityManager.checkMemberAccess checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false); // Privileged so this implementation can look at DECLARED classes, @@ -1435,7 +1584,7 @@ public final return java.security.AccessController.doPrivileged( new java.security.PrivilegedAction<Class<?>[]>() { - public Class[] run() { + public Class<?>[] run() { List<Class<?>> list = new ArrayList<>(); Class<?> currentClass = Class.this; while (currentClass != null) { @@ -1447,7 +1596,7 @@ public final } currentClass = currentClass.getSuperclass(); } - return list.toArray(new Class[0]); + return list.toArray(new Class<?>[0]); } }); } @@ -1456,103 +1605,99 @@ public final /** * Returns an array containing {@code Field} objects reflecting all * the accessible public fields of the class or interface represented by - * this {@code Class} object. The elements in the array returned are - * not sorted and are not in any particular order. This method returns an - * array of length 0 if the class or interface has no accessible public - * fields, or if it represents an array class, a primitive type, or void. - * - * <p> Specifically, if this {@code Class} object represents a class, - * this method returns the public fields of this class and of all its - * superclasses. If this {@code Class} object represents an - * interface, this method returns the fields of this interface and of all - * its superinterfaces. + * this {@code Class} object. * - * <p> The implicit length field for array class is not reflected by this - * method. User code should use the methods of class {@code Array} to - * manipulate arrays. - * - * <p> See <em>The Java Language Specification</em>, sections 8.2 and 8.3. + * <p> If this {@code Class} object represents a class or interface with no + * no accessible public fields, then this method returns an array of length + * 0. * - * @return the array of {@code Field} objects representing the - * public fields - * @exception SecurityException - * If a security manager, <i>s</i>, is present and any of the - * following conditions is met: + * <p> If this {@code Class} object represents a class, then this method + * returns the public fields of the class and of all its superclasses. * - * <ul> + * <p> If this {@code Class} object represents an interface, then this + * method returns the fields of the interface and of all its + * superinterfaces. * - * <li> invocation of - * {@link SecurityManager#checkMemberAccess - * s.checkMemberAccess(this, Member.PUBLIC)} denies - * access to the fields within this class + * <p> If this {@code Class} object represents an array type, a primitive + * type, or void, then this method returns an array of length 0. * - * <li> the caller's class loader is not the same as or an - * ancestor of the class loader for the current class and - * invocation of {@link SecurityManager#checkPackageAccess - * s.checkPackageAccess()} denies access to the package - * of this class + * <p> The elements in the returned array are not sorted and are not in any + * particular order. * - * </ul> + * @return the array of {@code Field} objects representing the + * public fields + * @throws SecurityException + * If a security manager, <i>s</i>, is present and + * the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of this class. * * @since JDK1.1 + * @jls 8.2 Class Members + * @jls 8.3 Field Declarations */ @CallerSensitive public Field[] getFields() throws SecurityException { - // be very careful not to change the stack depth of this - // checkMemberAccess call for security reasons - // see java.lang.SecurityManager.checkMemberAccess checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); return copyFields(privateGetPublicFields(null)); } /** - * Returns an array containing {@code Method} objects reflecting all - * the public <em>member</em> methods of the class or interface represented - * by this {@code Class} object, including those declared by the class - * or interface and those inherited from superclasses and - * superinterfaces. Array classes return all the (public) member methods - * inherited from the {@code Object} class. The elements in the array - * returned are not sorted and are not in any particular order. This - * method returns an array of length 0 if this {@code Class} object - * represents a class or interface that has no public member methods, or if - * this {@code Class} object represents a primitive type or void. + * Returns an array containing {@code Method} objects reflecting all the + * public methods of the class or interface represented by this {@code + * Class} object, including those declared by the class or interface and + * those inherited from superclasses and superinterfaces. * - * <p> The class initialization method {@code <clinit>} is not - * included in the returned array. If the class declares multiple public - * member methods with the same parameter types, they are all included in - * the returned array. + * <p> If this {@code Class} object represents a type that has multiple + * public methods with the same name and parameter types, but different + * return types, then the returned array has a {@code Method} object for + * each such method. * - * <p> See <em>The Java Language Specification</em>, sections 8.2 and 8.4. + * <p> If this {@code Class} object represents a type with a class + * initialization method {@code <clinit>}, then the returned array does + * <em>not</em> have a corresponding {@code Method} object. * - * @return the array of {@code Method} objects representing the - * public methods of this class - * @exception SecurityException - * If a security manager, <i>s</i>, is present and any of the - * following conditions is met: + * <p> If this {@code Class} object represents an array type, then the + * returned array has a {@code Method} object for each of the public + * methods inherited by the array type from {@code Object}. It does not + * contain a {@code Method} object for {@code clone()}. * - * <ul> + * <p> If this {@code Class} object represents an interface then the + * returned array does not contain any implicitly declared methods from + * {@code Object}. Therefore, if no methods are explicitly declared in + * this interface or any of its superinterfaces then the returned array + * has length 0. (Note that a {@code Class} object which represents a class + * always has public methods, inherited from {@code Object}.) * - * <li> invocation of - * {@link SecurityManager#checkMemberAccess - * s.checkMemberAccess(this, Member.PUBLIC)} denies - * access to the methods within this class + * <p> If this {@code Class} object represents a primitive type or void, + * then the returned array has length 0. * - * <li> the caller's class loader is not the same as or an - * ancestor of the class loader for the current class and - * invocation of {@link SecurityManager#checkPackageAccess - * s.checkPackageAccess()} denies access to the package - * of this class + * <p> Static methods declared in superinterfaces of the class or interface + * represented by this {@code Class} object are not considered members of + * the class or interface. * - * </ul> + * <p> The elements in the returned array are not sorted and are not in any + * particular order. * + * @return the array of {@code Method} objects representing the + * public methods of this class + * @throws SecurityException + * If a security manager, <i>s</i>, is present and + * the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of this class. + * + * @jls 8.2 Class Members + * @jls 8.4 Method Declarations * @since JDK1.1 */ @CallerSensitive public Method[] getMethods() throws SecurityException { - // be very careful not to change the stack depth of this - // checkMemberAccess call for security reasons - // see java.lang.SecurityManager.checkMemberAccess checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); return copyMethods(privateGetPublicMethods()); } @@ -1576,46 +1721,33 @@ public final * {@code Constructor<T>[]}. * * @return the array of {@code Constructor} objects representing the - * public constructors of this class - * @exception SecurityException - * If a security manager, <i>s</i>, is present and any of the - * following conditions is met: - * - * <ul> - * - * <li> invocation of - * {@link SecurityManager#checkMemberAccess - * s.checkMemberAccess(this, Member.PUBLIC)} denies - * access to the constructors within this class - * - * <li> the caller's class loader is not the same as or an - * ancestor of the class loader for the current class and - * invocation of {@link SecurityManager#checkPackageAccess - * s.checkPackageAccess()} denies access to the package - * of this class - * - * </ul> + * public constructors of this class + * @throws SecurityException + * If a security manager, <i>s</i>, is present and + * the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of this class. * * @since JDK1.1 */ @CallerSensitive public Constructor<?>[] getConstructors() throws SecurityException { - // be very careful not to change the stack depth of this - // checkMemberAccess call for security reasons - // see java.lang.SecurityManager.checkMemberAccess checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); return copyConstructors(privateGetDeclaredConstructors(true)); } /** - * Returns a {@code Field} object that reflects the specified public - * member field of the class or interface represented by this - * {@code Class} object. The {@code name} parameter is a - * {@code String} specifying the simple name of the desired field. + * Returns a {@code Field} object that reflects the specified public member + * field of the class or interface represented by this {@code Class} + * object. The {@code name} parameter is a {@code String} specifying the + * simple name of the desired field. * * <p> The field to be reflected is determined by the algorithm that - * follows. Let C be the class represented by this object: + * follows. Let C be the class or interface represented by this object: + * * <OL> * <LI> If C declares a public field with the name specified, that is the * field to be reflected.</LI> @@ -1628,41 +1760,30 @@ public final * is thrown.</LI> * </OL> * - * <p> See <em>The Java Language Specification</em>, sections 8.2 and 8.3. + * <p> If this {@code Class} object represents an array type, then this + * method does not find the {@code length} field of the array type. * * @param name the field name - * @return the {@code Field} object of this class specified by - * {@code name} - * @exception NoSuchFieldException if a field with the specified name is - * not found. - * @exception NullPointerException if {@code name} is {@code null} - * @exception SecurityException - * If a security manager, <i>s</i>, is present and any of the - * following conditions is met: - * - * <ul> - * - * <li> invocation of - * {@link SecurityManager#checkMemberAccess - * s.checkMemberAccess(this, Member.PUBLIC)} denies - * access to the field - * - * <li> the caller's class loader is not the same as or an - * ancestor of the class loader for the current class and - * invocation of {@link SecurityManager#checkPackageAccess - * s.checkPackageAccess()} denies access to the package - * of this class - * - * </ul> + * @return the {@code Field} object of this class specified by + * {@code name} + * @throws NoSuchFieldException if a field with the specified name is + * not found. + * @throws NullPointerException if {@code name} is {@code null} + * @throws SecurityException + * If a security manager, <i>s</i>, is present and + * the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of this class. * * @since JDK1.1 + * @jls 8.2 Class Members + * @jls 8.3 Field Declarations */ @CallerSensitive public Field getField(String name) throws NoSuchFieldException, SecurityException { - // be very careful not to change the stack depth of this - // checkMemberAccess call for security reasons - // see java.lang.SecurityManager.checkMemberAccess checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); Field field = getField0(name); if (field == null) { @@ -1682,25 +1803,29 @@ public final * order. If {@code parameterTypes} is {@code null}, it is * treated as if it were an empty array. * - * <p> If the {@code name} is "{@code <init>};"or "{@code <clinit>}" a + * <p> If the {@code name} is "{@code <init>}" or "{@code <clinit>}" a * {@code NoSuchMethodException} is raised. Otherwise, the method to * be reflected is determined by the algorithm that follows. Let C be the - * class represented by this object: + * class or interface represented by this object: * <OL> - * <LI> C is searched for any <I>matching methods</I>. If no matching - * method is found, the algorithm of step 1 is invoked recursively on - * the superclass of C.</LI> - * <LI> If no method was found in step 1 above, the superinterfaces of C - * are searched for a matching method. If any such method is found, it - * is reflected.</LI> + * <LI> C is searched for a <I>matching method</I>, as defined below. If a + * matching method is found, it is reflected.</LI> + * <LI> If no matching method is found by step 1 then: + * <OL TYPE="a"> + * <LI> If C is a class other than {@code Object}, then this algorithm is + * invoked recursively on the superclass of C.</LI> + * <LI> If C is the class {@code Object}, or if C is an interface, then + * the superinterfaces of C (if any) are searched for a matching + * method. If any such method is found, it is reflected.</LI> + * </OL></LI> * </OL> * - * To find a matching method in a class C: If C declares exactly one - * public method with the specified name and exactly the same formal - * parameter types, that is the method reflected. If more than one such - * method is found in C, and one of these methods has a return type that is - * more specific than any of the others, that method is reflected; - * otherwise one of the methods is chosen arbitrarily. + * <p> To find a matching method in a class or interface C: If C + * declares exactly one public method with the specified name and exactly + * the same formal parameter types, that is the method reflected. If more + * than one such method is found in C, and one of these methods has a + * return type that is more specific than any of the others, that method is + * reflected; otherwise one of the methods is chosen arbitrarily. * * <p>Note that there may be more than one matching method in a * class because while the Java language forbids a class to @@ -1713,44 +1838,37 @@ public final * method and the method being overridden would have the same * signature but different return types. * - * <p> See <em>The Java Language Specification</em>, sections 8.2 and 8.4. + * <p> If this {@code Class} object represents an array type, then this + * method does not find the {@code clone()} method. + * + * <p> Static methods declared in superinterfaces of the class or interface + * represented by this {@code Class} object are not considered members of + * the class or interface. * * @param name the name of the method * @param parameterTypes the list of parameters * @return the {@code Method} object that matches the specified - * {@code name} and {@code parameterTypes} - * @exception NoSuchMethodException if a matching method is not found - * or if the name is "<init>"or "<clinit>". - * @exception NullPointerException if {@code name} is {@code null} - * @exception SecurityException - * If a security manager, <i>s</i>, is present and any of the - * following conditions is met: - * - * <ul> - * - * <li> invocation of - * {@link SecurityManager#checkMemberAccess - * s.checkMemberAccess(this, Member.PUBLIC)} denies - * access to the method - * - * <li> the caller's class loader is not the same as or an - * ancestor of the class loader for the current class and - * invocation of {@link SecurityManager#checkPackageAccess - * s.checkPackageAccess()} denies access to the package - * of this class - * - * </ul> - * + * {@code name} and {@code parameterTypes} + * @throws NoSuchMethodException if a matching method is not found + * or if the name is "<init>"or "<clinit>". + * @throws NullPointerException if {@code name} is {@code null} + * @throws SecurityException + * If a security manager, <i>s</i>, is present and + * the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of this class. + * + * @jls 8.2 Class Members + * @jls 8.4 Method Declarations * @since JDK1.1 */ @CallerSensitive public Method getMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException { - // be very careful not to change the stack depth of this - // checkMemberAccess call for security reasons - // see java.lang.SecurityManager.checkMemberAccess checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); - Method method = getMethod0(name, parameterTypes); + Method method = getMethod0(name, parameterTypes, true); if (method == null) { throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes)); } @@ -1775,35 +1893,21 @@ public final * * @param parameterTypes the parameter array * @return the {@code Constructor} object of the public constructor that - * matches the specified {@code parameterTypes} - * @exception NoSuchMethodException if a matching method is not found. - * @exception SecurityException - * If a security manager, <i>s</i>, is present and any of the - * following conditions is met: - * - * <ul> - * - * <li> invocation of - * {@link SecurityManager#checkMemberAccess - * s.checkMemberAccess(this, Member.PUBLIC)} denies - * access to the constructor - * - * <li> the caller's class loader is not the same as or an - * ancestor of the class loader for the current class and - * invocation of {@link SecurityManager#checkPackageAccess - * s.checkPackageAccess()} denies access to the package - * of this class - * - * </ul> + * matches the specified {@code parameterTypes} + * @throws NoSuchMethodException if a matching method is not found. + * @throws SecurityException + * If a security manager, <i>s</i>, is present and + * the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of this class. * * @since JDK1.1 */ @CallerSensitive public Constructor<T> getConstructor(Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException { - // be very careful not to change the stack depth of this - // checkMemberAccess call for security reasons - // see java.lang.SecurityManager.checkMemberAccess checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); return getConstructor0(parameterTypes, Member.PUBLIC); } @@ -1820,33 +1924,32 @@ public final * primitive type, an array class, or void. * * @return the array of {@code Class} objects representing all the - * declared members of this class - * @exception SecurityException - * If a security manager, <i>s</i>, is present and any of the - * following conditions is met: + * declared members of this class + * @throws SecurityException + * If a security manager, <i>s</i>, is present and any of the + * following conditions is met: * - * <ul> + * <ul> * - * <li> invocation of - * {@link SecurityManager#checkMemberAccess - * s.checkMemberAccess(this, Member.DECLARED)} denies - * access to the declared classes within this class + * <li> the caller's class loader is not the same as the + * class loader of this class and invocation of + * {@link SecurityManager#checkPermission + * s.checkPermission} method with + * {@code RuntimePermission("accessDeclaredMembers")} + * denies access to the declared classes within this class * - * <li> the caller's class loader is not the same as or an - * ancestor of the class loader for the current class and - * invocation of {@link SecurityManager#checkPackageAccess - * s.checkPackageAccess()} denies access to the package - * of this class + * <li> the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of this class * - * </ul> + * </ul> * * @since JDK1.1 */ @CallerSensitive public Class<?>[] getDeclaredClasses() throws SecurityException { - // be very careful not to change the stack depth of this - // checkMemberAccess call for security reasons - // see java.lang.SecurityManager.checkMemberAccess checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), false); return getDeclaredClasses0(); } @@ -1857,90 +1960,104 @@ public final * declared by the class or interface represented by this * {@code Class} object. This includes public, protected, default * (package) access, and private fields, but excludes inherited fields. - * The elements in the array returned are not sorted and are not in any - * particular order. This method returns an array of length 0 if the class - * or interface declares no fields, or if this {@code Class} object - * represents a primitive type, an array class, or void. * - * <p> See <em>The Java Language Specification</em>, sections 8.2 and 8.3. + * <p> If this {@code Class} object represents a class or interface with no + * declared fields, then this method returns an array of length 0. * - * @return the array of {@code Field} objects representing all the - * declared fields of this class - * @exception SecurityException - * If a security manager, <i>s</i>, is present and any of the - * following conditions is met: + * <p> If this {@code Class} object represents an array type, a primitive + * type, or void, then this method returns an array of length 0. + * + * <p> The elements in the returned array are not sorted and are not in any + * particular order. * - * <ul> + * @return the array of {@code Field} objects representing all the + * declared fields of this class + * @throws SecurityException + * If a security manager, <i>s</i>, is present and any of the + * following conditions is met: * - * <li> invocation of - * {@link SecurityManager#checkMemberAccess - * s.checkMemberAccess(this, Member.DECLARED)} denies - * access to the declared fields within this class + * <ul> * - * <li> the caller's class loader is not the same as or an - * ancestor of the class loader for the current class and - * invocation of {@link SecurityManager#checkPackageAccess - * s.checkPackageAccess()} denies access to the package - * of this class + * <li> the caller's class loader is not the same as the + * class loader of this class and invocation of + * {@link SecurityManager#checkPermission + * s.checkPermission} method with + * {@code RuntimePermission("accessDeclaredMembers")} + * denies access to the declared fields within this class * - * </ul> + * <li> the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of this class + * + * </ul> * * @since JDK1.1 + * @jls 8.2 Class Members + * @jls 8.3 Field Declarations */ @CallerSensitive public Field[] getDeclaredFields() throws SecurityException { - // be very careful not to change the stack depth of this - // checkMemberAccess call for security reasons - // see java.lang.SecurityManager.checkMemberAccess checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); return copyFields(privateGetDeclaredFields(false)); } /** - * Returns an array of {@code Method} objects reflecting all the - * methods declared by the class or interface represented by this - * {@code Class} object. This includes public, protected, default - * (package) access, and private methods, but excludes inherited methods. - * The elements in the array returned are not sorted and are not in any - * particular order. This method returns an array of length 0 if the class - * or interface declares no methods, or if this {@code Class} object - * represents a primitive type, an array class, or void. The class - * initialization method {@code <clinit>} is not included in the - * returned array. If the class declares multiple public member methods - * with the same parameter types, they are all included in the returned - * array. * - * <p> See <em>The Java Language Specification</em>, section 8.2. + * Returns an array containing {@code Method} objects reflecting all the + * declared methods of the class or interface represented by this {@code + * Class} object, including public, protected, default (package) + * access, and private methods, but excluding inherited methods. * - * @return the array of {@code Method} objects representing all the - * declared methods of this class - * @exception SecurityException - * If a security manager, <i>s</i>, is present and any of the - * following conditions is met: + * <p> If this {@code Class} object represents a type that has multiple + * declared methods with the same name and parameter types, but different + * return types, then the returned array has a {@code Method} object for + * each such method. * - * <ul> + * <p> If this {@code Class} object represents a type that has a class + * initialization method {@code <clinit>}, then the returned array does + * <em>not</em> have a corresponding {@code Method} object. * - * <li> invocation of - * {@link SecurityManager#checkMemberAccess - * s.checkMemberAccess(this, Member.DECLARED)} denies - * access to the declared methods within this class + * <p> If this {@code Class} object represents a class or interface with no + * declared methods, then the returned array has length 0. * - * <li> the caller's class loader is not the same as or an - * ancestor of the class loader for the current class and - * invocation of {@link SecurityManager#checkPackageAccess - * s.checkPackageAccess()} denies access to the package - * of this class + * <p> If this {@code Class} object represents an array type, a primitive + * type, or void, then the returned array has length 0. * - * </ul> + * <p> The elements in the returned array are not sorted and are not in any + * particular order. * + * @return the array of {@code Method} objects representing all the + * declared methods of this class + * @throws SecurityException + * If a security manager, <i>s</i>, is present and any of the + * following conditions is met: + * + * <ul> + * + * <li> the caller's class loader is not the same as the + * class loader of this class and invocation of + * {@link SecurityManager#checkPermission + * s.checkPermission} method with + * {@code RuntimePermission("accessDeclaredMembers")} + * denies access to the declared methods within this class + * + * <li> the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of this class + * + * </ul> + * + * @jls 8.2 Class Members + * @jls 8.4 Method Declarations * @since JDK1.1 */ @CallerSensitive public Method[] getDeclaredMethods() throws SecurityException { - // be very careful not to change the stack depth of this - // checkMemberAccess call for security reasons - // see java.lang.SecurityManager.checkMemberAccess checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); return copyMethods(privateGetDeclaredMethods(false)); } @@ -1959,34 +2076,33 @@ public final * * <p> See <em>The Java Language Specification</em>, section 8.2. * - * @return the array of {@code Constructor} objects representing all the - * declared constructors of this class - * @exception SecurityException - * If a security manager, <i>s</i>, is present and any of the - * following conditions is met: + * @return the array of {@code Constructor} objects representing all the + * declared constructors of this class + * @throws SecurityException + * If a security manager, <i>s</i>, is present and any of the + * following conditions is met: * - * <ul> + * <ul> * - * <li> invocation of - * {@link SecurityManager#checkMemberAccess - * s.checkMemberAccess(this, Member.DECLARED)} denies - * access to the declared constructors within this class + * <li> the caller's class loader is not the same as the + * class loader of this class and invocation of + * {@link SecurityManager#checkPermission + * s.checkPermission} method with + * {@code RuntimePermission("accessDeclaredMembers")} + * denies access to the declared constructors within this class * - * <li> the caller's class loader is not the same as or an - * ancestor of the class loader for the current class and - * invocation of {@link SecurityManager#checkPackageAccess - * s.checkPackageAccess()} denies access to the package - * of this class + * <li> the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of this class * - * </ul> + * </ul> * * @since JDK1.1 */ @CallerSensitive public Constructor<?>[] getDeclaredConstructors() throws SecurityException { - // be very careful not to change the stack depth of this - // checkMemberAccess call for security reasons - // see java.lang.SecurityManager.checkMemberAccess checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); return copyConstructors(privateGetDeclaredConstructors(false)); } @@ -1995,43 +2111,46 @@ public final /** * Returns a {@code Field} object that reflects the specified declared * field of the class or interface represented by this {@code Class} - * object. The {@code name} parameter is a {@code String} that - * specifies the simple name of the desired field. Note that this method - * will not reflect the {@code length} field of an array class. + * object. The {@code name} parameter is a {@code String} that specifies + * the simple name of the desired field. * - * @param name the name of the field - * @return the {@code Field} object for the specified field in this - * class - * @exception NoSuchFieldException if a field with the specified name is - * not found. - * @exception NullPointerException if {@code name} is {@code null} - * @exception SecurityException - * If a security manager, <i>s</i>, is present and any of the - * following conditions is met: + * <p> If this {@code Class} object represents an array type, then this + * method does not find the {@code length} field of the array type. * - * <ul> - * - * <li> invocation of - * {@link SecurityManager#checkMemberAccess - * s.checkMemberAccess(this, Member.DECLARED)} denies - * access to the declared field - * - * <li> the caller's class loader is not the same as or an - * ancestor of the class loader for the current class and - * invocation of {@link SecurityManager#checkPackageAccess - * s.checkPackageAccess()} denies access to the package - * of this class - * - * </ul> + * @param name the name of the field + * @return the {@code Field} object for the specified field in this + * class + * @throws NoSuchFieldException if a field with the specified name is + * not found. + * @throws NullPointerException if {@code name} is {@code null} + * @throws SecurityException + * If a security manager, <i>s</i>, is present and any of the + * following conditions is met: + * + * <ul> + * + * <li> the caller's class loader is not the same as the + * class loader of this class and invocation of + * {@link SecurityManager#checkPermission + * s.checkPermission} method with + * {@code RuntimePermission("accessDeclaredMembers")} + * denies access to the declared field + * + * <li> the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of this class + * + * </ul> * * @since JDK1.1 + * @jls 8.2 Class Members + * @jls 8.3 Field Declarations */ @CallerSensitive public Field getDeclaredField(String name) throws NoSuchFieldException, SecurityException { - // be very careful not to change the stack depth of this - // checkMemberAccess call for security reasons - // see java.lang.SecurityManager.checkMemberAccess checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); Field field = searchFields(privateGetDeclaredFields(false), name); if (field == null) { @@ -2055,39 +2174,43 @@ public final * name is "<init>"or "<clinit>" a {@code NoSuchMethodException} * is raised. * + * <p> If this {@code Class} object represents an array type, then this + * method does not find the {@code clone()} method. + * * @param name the name of the method * @param parameterTypes the parameter array - * @return the {@code Method} object for the method of this class - * matching the specified name and parameters - * @exception NoSuchMethodException if a matching method is not found. - * @exception NullPointerException if {@code name} is {@code null} - * @exception SecurityException - * If a security manager, <i>s</i>, is present and any of the - * following conditions is met: - * - * <ul> - * - * <li> invocation of - * {@link SecurityManager#checkMemberAccess - * s.checkMemberAccess(this, Member.DECLARED)} denies - * access to the declared method - * - * <li> the caller's class loader is not the same as or an - * ancestor of the class loader for the current class and - * invocation of {@link SecurityManager#checkPackageAccess - * s.checkPackageAccess()} denies access to the package - * of this class - * - * </ul> - * + * @return the {@code Method} object for the method of this class + * matching the specified name and parameters + * @throws NoSuchMethodException if a matching method is not found. + * @throws NullPointerException if {@code name} is {@code null} + * @throws SecurityException + * If a security manager, <i>s</i>, is present and any of the + * following conditions is met: + * + * <ul> + * + * <li> the caller's class loader is not the same as the + * class loader of this class and invocation of + * {@link SecurityManager#checkPermission + * s.checkPermission} method with + * {@code RuntimePermission("accessDeclaredMembers")} + * denies access to the declared method + * + * <li> the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of this class + * + * </ul> + * + * @jls 8.2 Class Members + * @jls 8.4 Method Declarations * @since JDK1.1 */ @CallerSensitive public Method getDeclaredMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException { - // be very careful not to change the stack depth of this - // checkMemberAccess call for security reasons - // see java.lang.SecurityManager.checkMemberAccess checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes); if (method == null) { @@ -2109,36 +2232,35 @@ public final * include the explicit enclosing instance as the first parameter. * * @param parameterTypes the parameter array - * @return The {@code Constructor} object for the constructor with the - * specified parameter list - * @exception NoSuchMethodException if a matching method is not found. - * @exception SecurityException - * If a security manager, <i>s</i>, is present and any of the - * following conditions is met: - * - * <ul> - * - * <li> invocation of - * {@link SecurityManager#checkMemberAccess - * s.checkMemberAccess(this, Member.DECLARED)} denies - * access to the declared constructor - * - * <li> the caller's class loader is not the same as or an - * ancestor of the class loader for the current class and - * invocation of {@link SecurityManager#checkPackageAccess - * s.checkPackageAccess()} denies access to the package - * of this class - * - * </ul> + * @return The {@code Constructor} object for the constructor with the + * specified parameter list + * @throws NoSuchMethodException if a matching method is not found. + * @throws SecurityException + * If a security manager, <i>s</i>, is present and any of the + * following conditions is met: + * + * <ul> + * + * <li> the caller's class loader is not the same as the + * class loader of this class and invocation of + * {@link SecurityManager#checkPermission + * s.checkPermission} method with + * {@code RuntimePermission("accessDeclaredMembers")} + * denies access to the declared constructor + * + * <li> the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of this class + * + * </ul> * * @since JDK1.1 */ @CallerSensitive public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException { - // be very careful not to change the stack depth of this - // checkMemberAccess call for security reasons - // see java.lang.SecurityManager.checkMemberAccess checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); return getConstructor0(parameterTypes, Member.DECLARED); } @@ -2283,28 +2405,11 @@ public final */ private native java.security.ProtectionDomain getProtectionDomain0(); - - /** - * Set the ProtectionDomain for this class. Called by - * ClassLoader.defineClass. - */ - native void setProtectionDomain0(java.security.ProtectionDomain pd); - - /* * Return the Virtual Machine's Class object for the named * primitive type. */ - static native Class getPrimitiveClass(String name); - - private static boolean isCheckMemberAccessOverridden(SecurityManager smgr) { - if (smgr.getClass() == SecurityManager.class) return false; - - Class<?>[] paramTypes = new Class<?>[] {Class.class, int.class}; - return smgr.getClass().getMethod0("checkMemberAccess", paramTypes). - getDeclaringClass() != SecurityManager.class; - } - + static native Class<?> getPrimitiveClass(String name); /* * Check if client is allowed to access members. If access is denied, @@ -2318,19 +2423,17 @@ public final private void checkMemberAccess(int which, Class<?> caller, boolean checkProxyInterfaces) { final SecurityManager s = System.getSecurityManager(); if (s != null) { + /* Default policy allows access to all {@link Member#PUBLIC} members, + * as well as access to classes that have the same class loader as the caller. + * In all other cases, it requires RuntimePermission("accessDeclaredMembers") + * permission. + */ final ClassLoader ccl = ClassLoader.getClassLoader(caller); final ClassLoader cl = getClassLoader0(); - if (!isCheckMemberAccessOverridden(s)) { - // Inlined SecurityManager.checkMemberAccess - if (which != Member.PUBLIC) { - if (ccl != cl) { - s.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION); - } + if (which != Member.PUBLIC) { + if (ccl != cl) { + s.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION); } - } else { - // Don't refactor; otherwise break the stack depth for - // checkMemberAccess of subclasses of SecurityManager as specified. - s.checkMemberAccess(this, which); } this.checkPackageAccess(ccl, checkProxyInterfaces); } @@ -2345,6 +2448,7 @@ public final final SecurityManager s = System.getSecurityManager(); if (s != null) { final ClassLoader cl = getClassLoader0(); + if (ReflectUtil.needsPackageAccessCheck(ccl, cl)) { String name = this.getName(); int i = name.lastIndexOf('.'); @@ -2389,52 +2493,101 @@ public final } /** + * Atomic operations support. + */ + private static class Atomic { + @ikvm.internal.InterlockedCompareAndSet("reflectionData") + static native <T> boolean casReflectionData(Class<?> clazz, + SoftReference<ReflectionData<T>> oldData, + SoftReference<ReflectionData<T>> newData); + + @ikvm.internal.InterlockedCompareAndSet("annotationType") + static native <T> boolean casAnnotationType(Class<?> clazz, + AnnotationType oldType, + AnnotationType newType); + + @ikvm.internal.InterlockedCompareAndSet("annotationData") + static native <T> boolean casAnnotationData(Class<?> clazz, + AnnotationData oldData, + AnnotationData newData); + } + + /** * Reflection support. */ // Caches for certain reflective results private static boolean useCaches; - private volatile transient SoftReference<Field[]> declaredFields; - private volatile transient SoftReference<Field[]> publicFields; - private volatile transient SoftReference<Method[]> declaredMethods; - private volatile transient SoftReference<Method[]> publicMethods; - private volatile transient SoftReference<Constructor<T>[]> declaredConstructors; - private volatile transient SoftReference<Constructor<T>[]> publicConstructors; - // Intermediate results for getFields and getMethods - private volatile transient SoftReference<Field[]> declaredPublicFields; - private volatile transient SoftReference<Method[]> declaredPublicMethods; + + // reflection data that might get invalidated when JVM TI RedefineClasses() is called + private static class ReflectionData<T> { + volatile Field[] declaredFields; + volatile Field[] publicFields; + volatile Method[] declaredMethods; + volatile Method[] publicMethods; + volatile Constructor<T>[] declaredConstructors; + volatile Constructor<T>[] publicConstructors; + // Intermediate results for getFields and getMethods + volatile Field[] declaredPublicFields; + volatile Method[] declaredPublicMethods; + volatile Class<?>[] interfaces; + + // Value of classRedefinedCount when we created this ReflectionData instance + final int redefinedCount; + + ReflectionData(int redefinedCount) { + this.redefinedCount = redefinedCount; + } + } + + private volatile transient SoftReference<ReflectionData<T>> reflectionData; // Incremented by the VM on each call to JVM TI RedefineClasses() // that redefines this class or a superclass. private volatile transient int classRedefinedCount; - // Value of classRedefinedCount when we last cleared the cached values - // that are sensitive to class redefinition. - private volatile transient int lastRedefinedCount; - - // Clears cached values that might possibly have been obsoleted by - // a class redefinition. - private void clearCachesOnClassRedefinition() { - if (lastRedefinedCount != classRedefinedCount) { - declaredFields = publicFields = declaredPublicFields = null; - declaredMethods = publicMethods = declaredPublicMethods = null; - declaredConstructors = publicConstructors = null; - annotations = declaredAnnotations = null; - - // Use of "volatile" (and synchronization by caller in the case - // of annotations) ensures that no thread sees the update to - // lastRedefinedCount before seeing the caches cleared. - // We do not guard against brief windows during which multiple - // threads might redundantly work to fill an empty cache. - lastRedefinedCount = classRedefinedCount; + // Lazily create and cache ReflectionData + private ReflectionData<T> reflectionData() { + SoftReference<ReflectionData<T>> reflectionData = this.reflectionData; + int classRedefinedCount = this.classRedefinedCount; + ReflectionData<T> rd; + if (useCaches && + reflectionData != null && + (rd = reflectionData.get()) != null && + rd.redefinedCount == classRedefinedCount) { + return rd; + } + // else no SoftReference or cleared SoftReference or stale ReflectionData + // -> create and replace new instance + return newReflectionData(reflectionData, classRedefinedCount); + } + + private ReflectionData<T> newReflectionData(SoftReference<ReflectionData<T>> oldReflectionData, + int classRedefinedCount) { + if (!useCaches) return null; + + while (true) { + ReflectionData<T> rd = new ReflectionData<>(classRedefinedCount); + // try to CAS it... + if (Atomic.casReflectionData(this, oldReflectionData, new SoftReference<>(rd))) { + return rd; + } + // else retry + oldReflectionData = this.reflectionData; + classRedefinedCount = this.classRedefinedCount; + if (oldReflectionData != null && + (rd = oldReflectionData.get()) != null && + rd.redefinedCount == classRedefinedCount) { + return rd; + } } } // Generic signature handling - private native String getGenericSignature(); + private native String getGenericSignature0(); // Generic info repository; lazily initialized - private transient ClassRepository genericInfo; + private volatile transient ClassRepository genericInfo; // accessor for factory private GenericsFactory getFactory() { @@ -2442,19 +2595,31 @@ public final return CoreReflectionFactory.make(this, ClassScope.make(this)); } - // accessor for generic info repository + // accessor for generic info repository; + // generic info is lazily initialized private ClassRepository getGenericInfo() { - // lazily initialize repository if necessary + ClassRepository genericInfo = this.genericInfo; if (genericInfo == null) { - // create and cache generic info repository - genericInfo = ClassRepository.make(getGenericSignature(), - getFactory()); + String signature = getGenericSignature0(); + if (signature == null) { + genericInfo = ClassRepository.NONE; + } else { + genericInfo = ClassRepository.make(signature, getFactory()); + } + this.genericInfo = genericInfo; } - return genericInfo; //return cached repository + return (genericInfo != ClassRepository.NONE) ? genericInfo : null; } // Annotations handling private native Map<Class<? extends Annotation>, Annotation> getDeclaredAnnotationsImpl(); + // Since 1.8 + native byte[] getRawTypeAnnotations(); + static byte[] getExecutableTypeAnnotationBytes(Executable ex) { + return getReflectionFactory().getExecutableTypeAnnotationBytes(ex); + } + + native ConstantPool getConstantPool(); // // @@ -2467,27 +2632,19 @@ public final // via ReflectionFactory.copyField. private Field[] privateGetDeclaredFields(boolean publicOnly) { checkInitted(); - Field[] res = null; - if (useCaches) { - clearCachesOnClassRedefinition(); - if (publicOnly) { - if (declaredPublicFields != null) { - res = declaredPublicFields.get(); - } - } else { - if (declaredFields != null) { - res = declaredFields.get(); - } - } + Field[] res; + ReflectionData<T> rd = reflectionData(); + if (rd != null) { + res = publicOnly ? rd.declaredPublicFields : rd.declaredFields; if (res != null) return res; } // No cached value available; request value from VM res = Reflection.filterFields(this, getDeclaredFields0(publicOnly)); - if (useCaches) { + if (rd != null) { if (publicOnly) { - declaredPublicFields = new SoftReference<>(res); + rd.declaredPublicFields = res; } else { - declaredFields = new SoftReference<>(res); + rd.declaredFields = res; } } return res; @@ -2498,12 +2655,10 @@ public final // via ReflectionFactory.copyField. private Field[] privateGetPublicFields(Set<Class<?>> traversedInterfaces) { checkInitted(); - Field[] res = null; - if (useCaches) { - clearCachesOnClassRedefinition(); - if (publicFields != null) { - res = publicFields.get(); - } + Field[] res; + ReflectionData<T> rd = reflectionData(); + if (rd != null) { + res = rd.publicFields; if (res != null) return res; } @@ -2536,8 +2691,8 @@ public final res = new Field[fields.size()]; fields.toArray(res); - if (useCaches) { - publicFields = new SoftReference<>(res); + if (rd != null) { + rd.publicFields = res; } return res; } @@ -2560,31 +2715,25 @@ public final // instead be copied via ReflectionFactory.copyConstructor. private Constructor<T>[] privateGetDeclaredConstructors(boolean publicOnly) { checkInitted(); - Constructor<T>[] res = null; - if (useCaches) { - clearCachesOnClassRedefinition(); - if (publicOnly) { - if (publicConstructors != null) { - res = publicConstructors.get(); - } - } else { - if (declaredConstructors != null) { - res = declaredConstructors.get(); - } - } + Constructor<T>[] res; + ReflectionData<T> rd = reflectionData(); + if (rd != null) { + res = publicOnly ? rd.publicConstructors : rd.declaredConstructors; if (res != null) return res; } // No cached value available; request value from VM if (isInterface()) { - res = new Constructor[0]; + @SuppressWarnings("unchecked") + Constructor<T>[] temporaryRes = (Constructor<T>[]) new Constructor<?>[0]; + res = temporaryRes; } else { res = getDeclaredConstructors0(publicOnly); } - if (useCaches) { + if (rd != null) { if (publicOnly) { - publicConstructors = new SoftReference<>(res); + rd.publicConstructors = res; } else { - declaredConstructors = new SoftReference<>(res); + rd.declaredConstructors = res; } } return res; @@ -2601,27 +2750,19 @@ public final // via ReflectionFactory.copyMethod. private Method[] privateGetDeclaredMethods(boolean publicOnly) { checkInitted(); - Method[] res = null; - if (useCaches) { - clearCachesOnClassRedefinition(); - if (publicOnly) { - if (declaredPublicMethods != null) { - res = declaredPublicMethods.get(); - } - } else { - if (declaredMethods != null) { - res = declaredMethods.get(); - } - } + Method[] res; + ReflectionData<T> rd = reflectionData(); + if (rd != null) { + res = publicOnly ? rd.declaredPublicMethods : rd.declaredMethods; if (res != null) return res; } // No cached value available; request value from VM res = Reflection.filterMethods(this, getDeclaredMethods0(publicOnly)); - if (useCaches) { + if (rd != null) { if (publicOnly) { - declaredPublicMethods = new SoftReference<>(res); + rd.declaredPublicMethods = res; } else { - declaredMethods = new SoftReference<>(res); + rd.declaredMethods = res; } } return res; @@ -2674,6 +2815,14 @@ public final } } + void addAllNonStatic(Method[] methods) { + for (Method candidate : methods) { + if (!Modifier.isStatic(candidate.getModifiers())) { + add(candidate); + } + } + } + int length() { return length; } @@ -2723,12 +2872,10 @@ public final // via ReflectionFactory.copyMethod. private Method[] privateGetPublicMethods() { checkInitted(); - Method[] res = null; - if (useCaches) { - clearCachesOnClassRedefinition(); - if (publicMethods != null) { - res = publicMethods.get(); - } + Method[] res; + ReflectionData<T> rd = reflectionData(); + if (rd != null) { + res = rd.publicMethods; if (res != null) return res; } @@ -2746,7 +2893,7 @@ public final MethodArray inheritedMethods = new MethodArray(); Class<?>[] interfaces = getInterfaces(); for (int i = 0; i < interfaces.length; i++) { - inheritedMethods.addAll(interfaces[i].privateGetPublicMethods()); + inheritedMethods.addAllNonStatic(interfaces[i].privateGetPublicMethods()); } if (!isInterface()) { Class<?> c = getSuperclass(); @@ -2776,8 +2923,8 @@ public final methods.addAllIfNotPresent(inheritedMethods); methods.compactAndTrim(); res = methods.getArray(); - if (useCaches) { - publicMethods = new SoftReference<>(res); + if (rd != null) { + rd.publicMethods = res; } return res; } @@ -2787,7 +2934,7 @@ public final // Helpers for fetchers of one field, method, or constructor // - private Field searchFields(Field[] fields, String name) { + private static Field searchFields(Field[] fields, String name) { String internedName = name.intern(); for (int i = 0; i < fields.length; i++) { if (fields[i].getName() == internedName) { @@ -2805,7 +2952,7 @@ public final // of Field objects which have to be created for the common // case where the field being requested is declared in the // class which is being queried. - Field res = null; + Field res; // Search declared public fields if ((res = searchFields(privateGetDeclaredFields(true), name)) != null) { return res; @@ -2849,7 +2996,7 @@ public final } - private Method getMethod0(String name, Class<?>[] parameterTypes) { + private Method getMethod0(String name, Class<?>[] parameterTypes, boolean includeStaticMethods) { // Note: the intent is that the search algorithm this routine // uses be equivalent to the ordering imposed by // privateGetPublicMethods(). It fetches only the declared @@ -2857,30 +3004,28 @@ public final // number of Method objects which have to be created for the // common case where the method being requested is declared in // the class which is being queried. - Method res = null; + Method res; // Search declared public methods if ((res = searchMethods(privateGetDeclaredMethods(true), name, parameterTypes)) != null) { - return res; + if (includeStaticMethods || !Modifier.isStatic(res.getModifiers())) + return res; } // Search superclass's methods if (!isInterface()) { Class<? super T> c = getSuperclass(); if (c != null) { - if ((res = c.getMethod0(name, parameterTypes)) != null) { + if ((res = c.getMethod0(name, parameterTypes, true)) != null) { return res; } } } // Search superinterfaces' methods Class<?>[] interfaces = getInterfaces(); - for (int i = 0; i < interfaces.length; i++) { - Class<?> c = interfaces[i]; - if ((res = c.getMethod0(name, parameterTypes)) != null) { + for (Class<?> c : interfaces) + if ((res = c.getMethod0(name, parameterTypes, false)) != null) return res; - } - } // Not found return null; } @@ -3082,16 +3227,13 @@ public final // initialized. This is needed because reflection code is // called very early in the initialization process (before // command-line arguments have been parsed and therefore - // these user-settable properties installed.) We assume that - // if System.out is non-null then the System class has been - // fully initialized and that the bulk of the startup code - // has been run. + // these user-settable properties installed.) - if (System.out == null) { - // java.lang.System not yet fully initialized + if (!sun.misc.VM.isBooted()) { return null; } + // Doesn't use Boolean.getBoolean to avoid class init. String val = System.getProperty("sun.reflect.noCaches"); if (val != null && val.equals("true")) { @@ -3137,13 +3279,14 @@ public final return null; } }); - enumConstants = (T[])values.invoke(null); + @SuppressWarnings("unchecked") + T[] temporaryConstants = (T[])values.invoke(null); + enumConstants = temporaryConstants; } // These can happen when users concoct enum-like classes // that don't comply with the enum spec. - catch (InvocationTargetException ex) { return null; } - catch (NoSuchMethodException ex) { return null; } - catch (IllegalAccessException ex) { return null; } + catch (InvocationTargetException | NoSuchMethodException | + IllegalAccessException ex) { return null; } } return enumConstants; } @@ -3152,7 +3295,7 @@ public final /** * Returns a map from simple name to enum constant. This package-private * method is used internally by Enum to implement - * public static <T extends Enum<T>> T valueOf(Class<T>, String) + * {@code public static <T extends Enum<T>> T valueOf(Class<T>, String)} * efficiently. Note that the map is returned by this method is * created lazily on first use. Typically it won't ever get created. */ @@ -3183,6 +3326,7 @@ public final * * @since 1.5 */ + @SuppressWarnings("unchecked") public T cast(Object obj) { if (obj != null && !isInstance(obj)) throw new ClassCastException(cannotCastMsg(obj)); @@ -3195,7 +3339,7 @@ public final /** * Casts this {@code Class} object to represent a subclass of the class - * represented by the specified class object. Checks that that the cast + * represented by the specified class object. Checks that the cast * is valid, and throws a {@code ClassCastException} if it is not. If * this method succeeds, it always returns a reference to this class object. * @@ -3206,6 +3350,8 @@ public final * could not be checked at runtime (because generic types are implemented * by erasure). * + * @param <U> the type to cast this class object to + * @param clazz the class of the type to cast this class object to * @return this {@code Class} object, cast to represent a subclass of * the specified class object. * @throws ClassCastException if this {@code Class} object does not @@ -3213,6 +3359,7 @@ public final * the class itself). * @since 1.5 */ + @SuppressWarnings("unchecked") public <U> Class<? extends U> asSubclass(Class<U> clazz) { if (clazz.isAssignableFrom(this)) return (Class<? extends U>) this; @@ -3224,83 +3371,231 @@ public final * @throws NullPointerException {@inheritDoc} * @since 1.5 */ + @SuppressWarnings("unchecked") public <A extends Annotation> A getAnnotation(Class<A> annotationClass) { - if (annotationClass == null) - throw new NullPointerException(); + Objects.requireNonNull(annotationClass); - initAnnotationsIfNecessary(); - return (A) annotations.get(annotationClass); + return (A) annotationData().annotations.get(annotationClass); } /** + * {@inheritDoc} * @throws NullPointerException {@inheritDoc} * @since 1.5 */ - public boolean isAnnotationPresent( - Class<? extends Annotation> annotationClass) { - if (annotationClass == null) - throw new NullPointerException(); - - return getAnnotation(annotationClass) != null; + @Override + public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) { + return GenericDeclaration.super.isAnnotationPresent(annotationClass); } + /** + * @throws NullPointerException {@inheritDoc} + * @since 1.8 + */ + @Override + public <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationClass) { + Objects.requireNonNull(annotationClass); + + AnnotationData annotationData = annotationData(); + return AnnotationSupport.getAssociatedAnnotations(annotationData.declaredAnnotations, + this, + annotationClass); + } /** * @since 1.5 */ public Annotation[] getAnnotations() { - initAnnotationsIfNecessary(); - Collection<Annotation> values = annotations.values(); - return values.toArray(new Annotation[values.size()]); + return AnnotationParser.toArray(annotationData().annotations); + } + + /** + * @throws NullPointerException {@inheritDoc} + * @since 1.8 + */ + @Override + @SuppressWarnings("unchecked") + public <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass) { + Objects.requireNonNull(annotationClass); + + return (A) annotationData().declaredAnnotations.get(annotationClass); + } + + /** + * @throws NullPointerException {@inheritDoc} + * @since 1.8 + */ + @Override + public <A extends Annotation> A[] getDeclaredAnnotationsByType(Class<A> annotationClass) { + Objects.requireNonNull(annotationClass); + + return AnnotationSupport.getDirectlyAndIndirectlyPresent(annotationData().declaredAnnotations, + annotationClass); } /** * @since 1.5 */ public Annotation[] getDeclaredAnnotations() { - initAnnotationsIfNecessary(); - Collection<Annotation> values = declaredAnnotations.values(); - return values.toArray(new Annotation[values.size()]); + return AnnotationParser.toArray(annotationData().declaredAnnotations); + } + + // annotation data that might get invalidated when JVM TI RedefineClasses() is called + private static class AnnotationData { + final Map<Class<? extends Annotation>, Annotation> annotations; + final Map<Class<? extends Annotation>, Annotation> declaredAnnotations; + + // Value of classRedefinedCount when we created this AnnotationData instance + final int redefinedCount; + + AnnotationData(Map<Class<? extends Annotation>, Annotation> annotations, + Map<Class<? extends Annotation>, Annotation> declaredAnnotations, + int redefinedCount) { + this.annotations = annotations; + this.declaredAnnotations = declaredAnnotations; + this.redefinedCount = redefinedCount; + } } // Annotations cache - private transient Map<Class<? extends Annotation>, Annotation> annotations; - private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations; - - private synchronized void initAnnotationsIfNecessary() { - clearCachesOnClassRedefinition(); - if (annotations != null) - return; - declaredAnnotations = getDeclaredAnnotationsImpl(); + @SuppressWarnings("UnusedDeclaration") + private volatile transient AnnotationData annotationData; + + private AnnotationData annotationData() { + while (true) { // retry loop + AnnotationData annotationData = this.annotationData; + int classRedefinedCount = this.classRedefinedCount; + if (annotationData != null && + annotationData.redefinedCount == classRedefinedCount) { + return annotationData; + } + // null or stale annotationData -> optimistically create new instance + AnnotationData newAnnotationData = createAnnotationData(classRedefinedCount); + // try to install it + if (Atomic.casAnnotationData(this, annotationData, newAnnotationData)) { + // successfully installed new AnnotationData + return newAnnotationData; + } + } + } + + private AnnotationData createAnnotationData(int classRedefinedCount) { + Map<Class<? extends Annotation>, Annotation> declaredAnnotations = + getDeclaredAnnotationsImpl(); Class<?> superClass = getSuperclass(); - if (superClass == null) { - annotations = declaredAnnotations; - } else { - annotations = new HashMap<>(); - superClass.initAnnotationsIfNecessary(); - for (Map.Entry<Class<? extends Annotation>, Annotation> e : superClass.annotations.entrySet()) { + Map<Class<? extends Annotation>, Annotation> annotations = null; + if (superClass != null) { + Map<Class<? extends Annotation>, Annotation> superAnnotations = + superClass.annotationData().annotations; + for (Map.Entry<Class<? extends Annotation>, Annotation> e : superAnnotations.entrySet()) { Class<? extends Annotation> annotationClass = e.getKey(); - if (AnnotationType.getInstance(annotationClass).isInherited()) + if (AnnotationType.getInstance(annotationClass).isInherited()) { + if (annotations == null) { // lazy construction + annotations = new LinkedHashMap<>((Math.max( + declaredAnnotations.size(), + Math.min(12, declaredAnnotations.size() + superAnnotations.size()) + ) * 4 + 2) / 3 + ); + } annotations.put(annotationClass, e.getValue()); + } } + } + if (annotations == null) { + // no inherited annotations -> share the Map with declaredAnnotations + annotations = declaredAnnotations; + } else { + // at least one inherited annotation -> declared may override inherited annotations.putAll(declaredAnnotations); } + return new AnnotationData(annotations, declaredAnnotations, classRedefinedCount); } // Annotation types cache their internal (AnnotationType) form - private AnnotationType annotationType; + @SuppressWarnings("UnusedDeclaration") + private volatile transient AnnotationType annotationType; - void setAnnotationType(AnnotationType type) { - annotationType = type; + boolean casAnnotationType(AnnotationType oldType, AnnotationType newType) { + return Atomic.casAnnotationType(this, oldType, newType); } AnnotationType getAnnotationType() { return annotationType; } + Map<Class<? extends Annotation>, Annotation> getDeclaredAnnotationMap() { + return annotationData().declaredAnnotations; + } + /* Backing store of user-defined values pertaining to this class. * Maintained by the ClassValue class. */ transient ClassValue.ClassValueMap classValueMap; + + /** + * Returns an {@code AnnotatedType} object that represents the use of a + * type to specify the superclass of the entity represented by this {@code + * Class} object. (The <em>use</em> of type Foo to specify the superclass + * in '... extends Foo' is distinct from the <em>declaration</em> of type + * Foo.) + * + * <p> If this {@code Class} object represents a type whose declaration + * does not explicitly indicate an annotated superclass, then the return + * value is an {@code AnnotatedType} object representing an element with no + * annotations. + * + * <p> If this {@code Class} represents either the {@code Object} class, an + * interface type, an array type, a primitive type, or void, the return + * value is {@code null}. + * + * @return an object representing the superclass + * @since 1.8 + */ + public AnnotatedType getAnnotatedSuperclass() { + if (this == Object.class || + isInterface() || + isArray() || + isPrimitive() || + this == Void.TYPE) { + return null; + } + + return TypeAnnotationParser.buildAnnotatedSuperclass(getRawTypeAnnotations(), getConstantPool(), this); + } + + /** + * Returns an array of {@code AnnotatedType} objects that represent the use + * of types to specify superinterfaces of the entity represented by this + * {@code Class} object. (The <em>use</em> of type Foo to specify a + * superinterface in '... implements Foo' is distinct from the + * <em>declaration</em> of type Foo.) + * + * <p> If this {@code Class} object represents a class, the return value is + * an array containing objects representing the uses of interface types to + * specify interfaces implemented by the class. The order of the objects in + * the array corresponds to the order of the interface types used in the + * 'implements' clause of the declaration of this {@code Class} object. + * + * <p> If this {@code Class} object represents an interface, the return + * value is an array containing objects representing the uses of interface + * types to specify interfaces directly extended by the interface. The + * order of the objects in the array corresponds to the order of the + * interface types used in the 'extends' clause of the declaration of this + * {@code Class} object. + * + * <p> If this {@code Class} object represents a class or interface whose + * declaration does not explicitly indicate any annotated superinterfaces, + * the return value is an array of length 0. + * + * <p> If this {@code Class} object represents either the {@code Object} + * class, an array type, a primitive type, or void, the return value is an + * array of length 0. + * + * @return an array representing the superinterfaces + * @since 1.8 + */ + public AnnotatedType[] getAnnotatedInterfaces() { + return TypeAnnotationParser.buildAnnotatedInterfaces(getRawTypeAnnotations(), getConstantPool(), this); + } } diff --git a/runtime/DynamicClassLoader.cs b/runtime/DynamicClassLoader.cs index 59308058..e31fbc76 100644 --- a/runtime/DynamicClassLoader.cs +++ b/runtime/DynamicClassLoader.cs @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2013 Jeroen Frijters + Copyright (C) 2002-2014 Jeroen Frijters This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -62,6 +62,7 @@ namespace IKVM.Internal #endif // STATIC_COMPILER private Dictionary<string, TypeBuilder> unloadables; private TypeBuilder unloadableContainer; + private Type[] delegates; #if !STATIC_COMPILER && !CLASSGC private static DynamicClassLoader instance = new DynamicClassLoader(CreateModuleBuilder(), false); #endif @@ -222,21 +223,29 @@ namespace IKVM.Internal return mangledTypeName; } - internal sealed override TypeWrapper DefineClassImpl(Dictionary<string, TypeWrapper> types, ClassFile f, ClassLoaderWrapper classLoader, ProtectionDomain protectionDomain) + internal sealed override TypeWrapper DefineClassImpl(Dictionary<string, TypeWrapper> types, TypeWrapper host, ClassFile f, ClassLoaderWrapper classLoader, ProtectionDomain protectionDomain) { #if STATIC_COMPILER AotTypeWrapper type = new AotTypeWrapper(f, (CompilerClassLoader)classLoader); type.CreateStep1(); types[f.Name] = type; return type; +#elif FIRST_PASS + return null; #else // this step can throw a retargettable exception, if the class is incorrect - DynamicTypeWrapper type = new DynamicTypeWrapper(f, classLoader, protectionDomain); + DynamicTypeWrapper type = new DynamicTypeWrapper(host, f, classLoader, protectionDomain); // This step actually creates the TypeBuilder. It is not allowed to throw any exceptions, // if an exception does occur, it is due to a programming error in the IKVM or CLR runtime // and will cause a CriticalFailure and exit the process. type.CreateStep1(); type.CreateStep2(); + if(types == null) + { + // we're defining an anonymous class, so we don't need any locking + TieClassAndWrapper(type, protectionDomain); + return type; + } lock(types) { // in very extreme conditions another thread may have beaten us to it @@ -248,16 +257,7 @@ namespace IKVM.Internal if(race == null) { types[f.Name] = type; -#if !FIRST_PASS - java.lang.Class clazz = new java.lang.Class(null); -#if __MonoCS__ - TypeWrapper.SetTypeWrapperHack(clazz, type); -#else - clazz.typeWrapper = type; -#endif - clazz.pd = protectionDomain; - type.SetClassObject(clazz); -#endif + TieClassAndWrapper(type, protectionDomain); } else { @@ -268,42 +268,37 @@ namespace IKVM.Internal #endif // STATIC_COMPILER } +#if !STATIC_COMPILER && !FIRST_PASS + private static java.lang.Class TieClassAndWrapper(TypeWrapper type, ProtectionDomain protectionDomain) + { + java.lang.Class clazz = new java.lang.Class(null); +#if __MonoCS__ + TypeWrapper.SetTypeWrapperHack(clazz, type); +#else + clazz.typeWrapper = type; +#endif + clazz.pd = protectionDomain; + type.SetClassObject(clazz); + return clazz; + } +#endif + #if STATIC_COMPILER - internal TypeBuilder DefineProxy(TypeWrapper proxyClass, TypeWrapper[] interfaces) + internal TypeBuilder DefineProxy(string name, TypeAttributes typeAttributes, Type parent, Type[] interfaces) { if (proxiesContainer == null) { - proxiesContainer = moduleBuilder.DefineType("__<Proxies>", TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.Abstract); + proxiesContainer = moduleBuilder.DefineType(TypeNameUtil.ProxiesContainer, TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.Abstract); AttributeHelper.HideFromJava(proxiesContainer); AttributeHelper.SetEditorBrowsableNever(proxiesContainer); proxies = new List<TypeBuilder>(); } - Type[] ifaces = new Type[interfaces.Length]; - for (int i = 0; i < ifaces.Length; i++) - { - ifaces[i] = interfaces[i].TypeAsBaseType; - } - TypeBuilder tb = proxiesContainer.DefineNestedType(GetProxyNestedName(interfaces), TypeAttributes.NestedPublic | TypeAttributes.Class | TypeAttributes.Sealed, proxyClass.TypeAsBaseType, ifaces); + TypeBuilder tb = proxiesContainer.DefineNestedType(name, typeAttributes, parent, interfaces); proxies.Add(tb); return tb; } #endif - private static string GetProxyNestedName(TypeWrapper[] interfaces) - { - System.Text.StringBuilder sb = new System.Text.StringBuilder(); - foreach (TypeWrapper tw in interfaces) - { - sb.Append(tw.Name.Length).Append('|').Append(tw.Name); - } - return TypeNameUtil.MangleNestedTypeName(sb.ToString()); - } - - internal static string GetProxyName(TypeWrapper[] interfaces) - { - return "__<Proxies>+" + GetProxyNestedName(interfaces); - } - internal override Type DefineUnloadable(string name) { lock(this) @@ -328,6 +323,47 @@ namespace IKVM.Internal } } + internal override Type DefineDelegate(int parameterCount, bool returnVoid) + { + lock (this) + { + if (delegates == null) + { + delegates = new Type[512]; + } + int index = parameterCount + (returnVoid ? 256 : 0); + Type type = delegates[index]; + if (type != null) + { + return type; + } + TypeBuilder tb = moduleBuilder.DefineType(returnVoid ? "__<>NVIV`" + parameterCount : "__<>NVI`" + (parameterCount + 1), TypeAttributes.NotPublic | TypeAttributes.Sealed, Types.MulticastDelegate); + string[] names = new string[parameterCount + (returnVoid ? 0 : 1)]; + for (int i = 0; i < names.Length; i++) + { + names[i] = "P" + i; + } + if (!returnVoid) + { + names[names.Length - 1] = "R"; + } + Type[] genericParameters = tb.DefineGenericParameters(names); + Type[] parameterTypes = genericParameters; + if (!returnVoid) + { + parameterTypes = new Type[genericParameters.Length - 1]; + Array.Copy(genericParameters, parameterTypes, parameterTypes.Length); + } + tb.DefineMethod(ConstructorInfo.ConstructorName, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, Types.Void, new Type[] { Types.Object, Types.IntPtr }) + .SetImplementationFlags(MethodImplAttributes.Runtime); + MethodBuilder mb = tb.DefineMethod("Invoke", MethodAttributes.Public | MethodAttributes.NewSlot | MethodAttributes.Virtual, returnVoid ? Types.Void : genericParameters[genericParameters.Length - 1], parameterTypes); + mb.SetImplementationFlags(MethodImplAttributes.Runtime); + type = tb.CreateType(); + delegates[index] = type; + return type; + } + } + internal override bool HasInternalAccess { get { return hasInternalAccess; } @@ -403,7 +439,7 @@ namespace IKVM.Internal { AssemblyName name = new AssemblyName(); name.Name = "jniproxy"; - jniProxyAssemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.RunAndSave, null, null, null, null, null, true); + jniProxyAssemblyBuilder = DefineDynamicAssembly(name, AssemblyBuilderAccess.RunAndSave, null); return jniProxyAssemblyBuilder.DefineDynamicModule("jniproxy.dll", "jniproxy.dll"); } #endif @@ -544,12 +580,7 @@ namespace IKVM.Internal attribs.Add(new CustomAttributeBuilder(typeof(System.Security.SecurityTransparentAttribute).GetConstructor(Type.EmptyTypes), new object[0])); } #endif - AssemblyBuilder assemblyBuilder = -#if NET_4_0 - AppDomain.CurrentDomain.DefineDynamicAssembly(name, access, null, true, attribs); -#else - AppDomain.CurrentDomain.DefineDynamicAssembly(name, access, null, null, null, null, null, true, attribs); -#endif + AssemblyBuilder assemblyBuilder = DefineDynamicAssembly(name, access, attribs); AttributeHelper.SetRuntimeCompatibilityAttribute(assemblyBuilder); bool debug = JVM.EmitSymbols; CustomAttributeBuilder debugAttr = new CustomAttributeBuilder(typeof(DebuggableAttribute).GetConstructor(new Type[] { typeof(bool), typeof(bool) }), new object[] { true, debug }); @@ -558,6 +589,15 @@ namespace IKVM.Internal moduleBuilder.SetCustomAttribute(new CustomAttributeBuilder(typeof(IKVM.Attributes.JavaModuleAttribute).GetConstructor(Type.EmptyTypes), new object[0])); return moduleBuilder; } + + private static AssemblyBuilder DefineDynamicAssembly(AssemblyName name, AssemblyBuilderAccess access, IEnumerable<CustomAttributeBuilder> assemblyAttributes) + { +#if NET_4_0 + return AppDomain.CurrentDomain.DefineDynamicAssembly(name, access, null, true, assemblyAttributes); +#else + return AppDomain.CurrentDomain.DefineDynamicAssembly(name, access, null, null, null, null, null, true, assemblyAttributes); +#endif + } #endif // !STATIC_COMPILER } } diff --git a/runtime/TypeWrapper.cs b/runtime/TypeWrapper.cs index 54f3378c..b610dd7b 100644 --- a/runtime/TypeWrapper.cs +++ b/runtime/TypeWrapper.cs @@ -5695,7 +5695,7 @@ namespace IKVM.Internal private readonly Type type; internal AnonymousTypeWrapper(Type type) - : base(TypeFlags.None, Modifiers.Final | Modifiers.Synthetic, GetName(type)) + : base(TypeFlags.Anonymous, Modifiers.Final | Modifiers.Synthetic, GetName(type)) { this.type = type; } @@ -5707,11 +5707,10 @@ namespace IKVM.Internal && AttributeHelper.IsJavaModule(type.Module); } - internal static string GetName(Type type) + private static string GetName(Type type) { return ClassLoaderWrapper.GetWrapperFromType(type.DeclaringType).Name - + type.Name.Replace(NestedTypeName.IntrinsifiedAnonymousClass, "$$Lambda$") - + "/" + (type.GetHashCode() & Int32.MaxValue); + + type.Name.Replace(NestedTypeName.IntrinsifiedAnonymousClass, "$$Lambda$"); } internal override ClassLoaderWrapper GetClassLoader() diff --git a/runtime/openjdk/java.lang.cs b/runtime/openjdk/java.lang.cs index 9d277487..948bd25b 100644 --- a/runtime/openjdk/java.lang.cs +++ b/runtime/openjdk/java.lang.cs @@ -220,6 +220,14 @@ static class Java_java_lang_Class return "void"; } } + if (tw.IsUnsafeAnonymous) + { +#if !FIRST_PASS + // for OpenJDK compatibility and debugging convenience we modify the class name to + // include the identity hashcode of the class object + return tw.Name + "/" + java.lang.System.identityHashCode(thisClass); +#endif + } return tw.Name; } |