8065172: More core reflection final and volatile annotations

More fiddling with "final" and "volatile" field modifiers

Reviewed-by: jfranck, plevart, psandoz
This commit is contained in:
Martin Buchholz 2014-11-21 16:30:02 -08:00
parent b479361747
commit 0a3973c5a6
28 changed files with 260 additions and 288 deletions

View File

@ -52,7 +52,7 @@ class Label {
final short patchBCI;
final int stackDepth;
}
private List<PatchInfo> patches = new ArrayList<>();
private final List<PatchInfo> patches = new ArrayList<>();
public Label() {
}

View File

@ -135,7 +135,7 @@ public class ReflectionFactory {
* be initialized and therefore must not be called until the
* first get/set of this field.
* @param field the field
* @param override true if caller has overridden aaccessibility
* @param override true if caller has overridden accessibility
*/
public FieldAccessor newFieldAccessor(Field field, boolean override) {
checkInitted();

View File

@ -280,19 +280,25 @@ class AnnotationInvocationHandler implements InvocationHandler, Serializable {
* be rare).
*/
private Method[] getMemberMethods() {
if (memberMethods == null) {
memberMethods = AccessController.doPrivileged(
new PrivilegedAction<Method[]>() {
public Method[] run() {
final Method[] mm = type.getDeclaredMethods();
validateAnnotationMethods(mm);
AccessibleObject.setAccessible(mm, true);
return mm;
}
});
Method[] value = memberMethods;
if (value == null) {
value = computeMemberMethods();
memberMethods = value;
}
return memberMethods;
return value;
}
private Method[] computeMemberMethods() {
return AccessController.doPrivileged(
new PrivilegedAction<Method[]>() {
public Method[] run() {
final Method[] methods = type.getDeclaredMethods();
validateAnnotationMethods(methods);
AccessibleObject.setAccessible(methods, true);
return methods;
}});
}
private transient volatile Method[] memberMethods = null;
/**

View File

@ -772,7 +772,7 @@ public class AnnotationParser {
}
/**
* Return an appropriate exception proxy for a mismatching array
* Returns an appropriate exception proxy for a mismatching array
* annotation where the erroneous array has the specified tag.
*/
private static ExceptionProxy exceptionProxy(int tag) {

View File

@ -115,7 +115,7 @@ public final class AnnotationSupport {
/**
* Figures out if conatiner class comes before containee class among the
* Figures out if container class comes before containee class among the
* keys of the given map.
*
* @return true if container class is found before containee class when

View File

@ -55,7 +55,7 @@ public class AnnotationType {
private final Map<String, Object> memberDefaults;
/**
* Member name -> Method object mapping. This (and its assoicated
* Member name -> Method object mapping. This (and its associated
* accessor) are used only to generate AnnotationTypeMismatchExceptions.
*/
private final Map<String, Method> members;
@ -117,7 +117,7 @@ public class AnnotationType {
memberDefaults = new HashMap<String, Object>(0);
members = new HashMap<String, Method>(methods.length+1, 1.0f);
for (Method method : methods) {
for (Method method : methods) {
if (method.getParameterTypes().length != 0)
throw new IllegalArgumentException(method + " has params");
String name = method.getName();

View File

@ -36,7 +36,7 @@ import java.lang.reflect.Method;
class AnnotationTypeMismatchExceptionProxy extends ExceptionProxy {
private static final long serialVersionUID = 7844069490309503934L;
private Method member;
private String foundType;
private final String foundType;
/**
* It turns out to be convenient to construct these proxies in

View File

@ -33,8 +33,8 @@ package sun.reflect.annotation;
*/
public class EnumConstantNotPresentExceptionProxy extends ExceptionProxy {
private static final long serialVersionUID = -604662101303187330L;
Class<? extends Enum<?>> enumType;
String constName;
final Class<? extends Enum<?>> enumType;
final String constName;
public EnumConstantNotPresentExceptionProxy(Class<? extends Enum<?>> enumType,
String constName) {

View File

@ -34,8 +34,8 @@ import java.lang.annotation.*;
*/
public class TypeNotPresentExceptionProxy extends ExceptionProxy {
private static final long serialVersionUID = 5565925172427947573L;
String typeName;
Throwable cause;
final String typeName;
final Throwable cause;
public TypeNotPresentExceptionProxy(String typeName, Throwable cause) {
this.typeName = typeName;

View File

@ -76,11 +76,11 @@ public class CoreReflectionFactory implements GenericsFactory {
* kind. Classes produced will be those that would be loaded by the
* defining class loader of the declaration <tt>d</tt> (if <tt>d</tt>
* is a type declaration, or by the defining loader of the declaring
* class of <tt>d</tt> otherwise.
* class of <tt>d</tt> otherwise.
* <p> Type variables will be created or lookup as necessary in the
* scope <tt> s</tt>.
* @param d - the generic declaration (class, interface, method or
* constructor) that thsi factory services
* constructor) that this factory services
* @param s the scope in which the factory will allocate and search for
* type variables
* @return an instance of <tt>CoreReflectionFactory</tt>

View File

@ -42,7 +42,7 @@ import sun.reflect.generics.tree.FieldTypeSignature;
* of a specific implementation by using this interface. For example,
* repositories of generic type information are initialized with a
* factory conforming to this interface, and use it to generate the
* tpe information they are required to provide. As a result, such
* type information they are required to provide. As a result, such
* repository code can be shared across different reflective systems.
*/
public interface GenericsFactory {
@ -60,7 +60,7 @@ public interface GenericsFactory {
TypeVariable<?> makeTypeVariable(String name,
FieldTypeSignature[] bounds);
/**
* Return an instance of the <tt>ParameterizedType</tt> interface
* Returns an instance of the <tt>ParameterizedType</tt> interface
* that corresponds to a generic type instantiation of the
* generic declaration <tt>declaration</tt> with actual type arguments
* <tt>typeArgs</tt>.
@ -123,7 +123,7 @@ public interface GenericsFactory {
/**
* Returns a (possibly generic) array type.
* If the component type is a parameterized type, it must
* only have unbounded wildcard arguemnts, otherwise
* only have unbounded wildcard arguments, otherwise
* a MalformedParameterizedTypeException is thrown.
* @param componentType - the component type of the array
* @return a (possibly generic) array type.

View File

@ -227,7 +227,7 @@ public class SignatureParser {
* "<" FormalTypeParameter+ ">"
*/
private FormalTypeParameter[] parseFormalTypeParameters(){
List<FormalTypeParameter> ftps = new ArrayList<>(3);
List<FormalTypeParameter> ftps = new ArrayList<>(3);
assert(current() == '<'); // should not have been called at all
if (current() != '<') { throw error("expected '<'");}
advance();

View File

@ -53,10 +53,10 @@ public class GenericArrayTypeImpl
/**
* Returns a <tt>Type</tt> object representing the component type
* Returns a <tt>Type</tt> object representing the component type
* of this array.
*
* @return a <tt>Type</tt> object representing the component type
* @return a <tt>Type</tt> object representing the component type
* of this array
* @since 1.5
*/

View File

@ -25,7 +25,9 @@
package sun.reflect.generics.reflectiveObjects;
import java.lang.reflect.Type;
import sun.reflect.generics.factory.GenericsFactory;
import sun.reflect.generics.tree.FieldTypeSignature;
import sun.reflect.generics.visitor.Reifier;
@ -54,4 +56,16 @@ public abstract class LazyReflectiveObjectGenerator {
// produce a reifying visitor (could this be typed as a TypeTreeVisitor?
protected Reifier getReifier(){return Reifier.make(getFactory());}
Type[] reifyBounds(FieldTypeSignature[] boundASTs) {
final int length = boundASTs.length;
final Type[] bounds = new Type[length];
// iterate over bound trees, reifying each in turn
for (int i = 0; i < length; i++) {
Reifier r = getReifier();
boundASTs[i].accept(r);
bounds[i] = r.getResult();
}
return bounds;
}
}

View File

@ -51,17 +51,16 @@ import sun.reflect.misc.ReflectUtil;
*/
public class TypeVariableImpl<D extends GenericDeclaration>
extends LazyReflectiveObjectGenerator implements TypeVariable<D> {
D genericDeclaration;
private String name;
// upper bounds - evaluated lazily
private Type[] bounds;
private final D genericDeclaration;
private final String name;
// The ASTs for the bounds. We are required to evaluate the bounds
// lazily, so we store these at least until we are first asked
// for the bounds. This also neatly solves the
// problem with F-bounds - you can't reify them before the formal
// is defined.
private FieldTypeSignature[] boundASTs;
/**
* The upper bounds. Lazily converted from FieldTypeSignature[] to Type[].
* We are required to evaluate the bounds lazily, so we store them as ASTs
* until we are first asked for them. This also neatly solves the problem
* with F-bounds - you can't reify them before the formal is defined.
*/
private volatile Object[] bounds;
// constructor is private to enforce access through static factory
private TypeVariableImpl(D decl, String n, FieldTypeSignature[] bs,
@ -69,18 +68,7 @@ public class TypeVariableImpl<D extends GenericDeclaration>
super(f);
genericDeclaration = decl;
name = n;
boundASTs = bs;
}
// Accessors
// accessor for ASTs for bounds. Must not be called after
// bounds have been evaluated, because we might throw the ASTs
// away (but that is not thread-safe, is it?)
private FieldTypeSignature[] getBoundASTs() {
// check that bounds were not evaluated yet
assert(bounds == null);
return boundASTs;
bounds = bs;
}
/**
@ -123,7 +111,7 @@ public class TypeVariableImpl<D extends GenericDeclaration>
* <li>Otherwise, B is resolved.
* </ul>
*
* @throws <tt>TypeNotPresentException</tt> if any of the
* @throws <tt>TypeNotPresentException</tt> if any of the
* bounds refers to a non-existent type declaration
* @throws <tt>MalformedParameterizedTypeException</tt> if any of the
* bounds refer to a parameterized type that cannot be instantiated
@ -132,34 +120,23 @@ public class TypeVariableImpl<D extends GenericDeclaration>
* type variable
*/
public Type[] getBounds() {
// lazily initialize bounds if necessary
if (bounds == null) {
FieldTypeSignature[] fts = getBoundASTs(); // get AST
// allocate result array; note that
// keeping ts and bounds separate helps with threads
Type[] ts = new Type[fts.length];
// iterate over bound trees, reifying each in turn
for ( int j = 0; j < fts.length; j++) {
Reifier r = getReifier();
fts[j].accept(r);
ts[j] = r.getResult();
}
// cache result
bounds = ts;
// could throw away bound ASTs here; thread safety?
Object[] value = bounds;
if (value instanceof FieldTypeSignature[]) {
value = reifyBounds((FieldTypeSignature[])value);
bounds = value;
}
return bounds.clone(); // return cached bounds
return (Type[])value.clone();
}
/**
* Returns the <tt>GenericDeclaration</tt> object representing the
* Returns the <tt>GenericDeclaration</tt> object representing the
* generic declaration that declared this type variable.
*
* @return the generic declaration that declared this type variable.
*
* @since 1.5
*/
public D getGenericDeclaration(){
public D getGenericDeclaration() {
if (genericDeclaration instanceof Class)
ReflectUtil.checkPackageAccess((Class)genericDeclaration);
else if ((genericDeclaration instanceof Method) ||

View File

@ -39,25 +39,26 @@ import java.util.Arrays;
*/
public class WildcardTypeImpl extends LazyReflectiveObjectGenerator
implements WildcardType {
// upper bounds - evaluated lazily
private Type[] upperBounds;
// lower bounds - evaluated lazily
private Type[] lowerBounds;
// The ASTs for the bounds. We are required to evaluate the bounds
// lazily, so we store these at least until we are first asked
// for the bounds. This also neatly solves the
// problem with F-bounds - you can't reify them before the formal
// is defined.
private FieldTypeSignature[] upperBoundASTs;
private FieldTypeSignature[] lowerBoundASTs;
/*
* We are required to evaluate the bounds lazily, so we store them as ASTs
* until we are first asked for them. This also neatly solves the problem
* with F-bounds - you can't reify them before the formal is defined.
*/
/** The upper bounds. Lazily converted from FieldTypeSignature[] to Type[]. */
private volatile Object[] upperBounds;
/** The lower bounds. Lazily converted from FieldTypeSignature[] to Type[]. */
private volatile Object[] lowerBounds;
// constructor is private to enforce access through static factory
private WildcardTypeImpl(FieldTypeSignature[] ubs,
FieldTypeSignature[] lbs,
GenericsFactory f) {
super(f);
upperBoundASTs = ubs;
lowerBoundASTs = lbs;
upperBounds = ubs;
lowerBounds = lbs;
}
/**
@ -76,27 +77,8 @@ public class WildcardTypeImpl extends LazyReflectiveObjectGenerator
return new WildcardTypeImpl(ubs, lbs, f);
}
// Accessors
// accessor for ASTs for upper bounds. Must not be called after upper
// bounds have been evaluated, because we might throw the ASTs
// away (but that is not thread-safe, is it?)
private FieldTypeSignature[] getUpperBoundASTs() {
// check that upper bounds were not evaluated yet
assert(upperBounds == null);
return upperBoundASTs;
}
// accessor for ASTs for lower bounds. Must not be called after lower
// bounds have been evaluated, because we might throw the ASTs
// away (but that is not thread-safe, is it?)
private FieldTypeSignature[] getLowerBoundASTs() {
// check that lower bounds were not evaluated yet
assert(lowerBounds == null);
return lowerBoundASTs;
}
/**
* Returns an array of <tt>Type</tt> objects representing the upper
* Returns an array of <tt>Type</tt> objects representing the upper
* bound(s) of this type variable. Note that if no upper bound is
* explicitly declared, the upper bound is <tt>Object</tt>.
*
@ -117,24 +99,12 @@ public class WildcardTypeImpl extends LazyReflectiveObjectGenerator
* for any reason
*/
public Type[] getUpperBounds() {
// lazily initialize bounds if necessary
if (upperBounds == null) {
FieldTypeSignature[] fts = getUpperBoundASTs(); // get AST
// allocate result array; note that
// keeping ts and bounds separate helps with threads
Type[] ts = new Type[fts.length];
// iterate over bound trees, reifying each in turn
for ( int j = 0; j < fts.length; j++) {
Reifier r = getReifier();
fts[j].accept(r);
ts[j] = r.getResult();
}
// cache result
upperBounds = ts;
// could throw away upper bound ASTs here; thread safety?
Object[] value = upperBounds;
if (value instanceof FieldTypeSignature[]) {
value = reifyBounds((FieldTypeSignature[])value);
upperBounds = value;
}
return upperBounds.clone(); // return cached bounds
return (Type[])value.clone();
}
/**
@ -160,23 +130,12 @@ public class WildcardTypeImpl extends LazyReflectiveObjectGenerator
* for any reason
*/
public Type[] getLowerBounds() {
// lazily initialize bounds if necessary
if (lowerBounds == null) {
FieldTypeSignature[] fts = getLowerBoundASTs(); // get AST
// allocate result array; note that
// keeping ts and bounds separate helps with threads
Type[] ts = new Type[fts.length];
// iterate over bound trees, reifying each in turn
for ( int j = 0; j < fts.length; j++) {
Reifier r = getReifier();
fts[j].accept(r);
ts[j] = r.getResult();
}
// cache result
lowerBounds = ts;
// could throw away lower bound ASTs here; thread safety?
Object[] value = lowerBounds;
if (value instanceof FieldTypeSignature[]) {
value = reifyBounds((FieldTypeSignature[])value);
lowerBounds = value;
}
return lowerBounds.clone(); // return cached bounds
return (Type[])value.clone();
}
public String toString() {

View File

@ -56,7 +56,7 @@ public abstract class AbstractRepository<T extends Tree> {
/**
* Returns a <tt>Reifier</tt> used to convert parts of the
* AST into reflective objects.
* @return a <tt>Reifier</tt> used to convert parts of the
* @return a <tt>Reifier</tt> used to convert parts of the
* AST into reflective objects
*/
protected Reifier getReifier(){return Reifier.make(getFactory());}
@ -76,7 +76,7 @@ public abstract class AbstractRepository<T extends Tree> {
}
/**
* Returns the AST for the genric type info of this entity.
* Returns the AST for the generic type info of this entity.
* @param s - a string representing the generic signature of this
* entity
* @return the AST for the generic type info of this entity.

View File

@ -25,12 +25,12 @@
package sun.reflect.generics.repository;
import java.lang.reflect.Type;
import sun.reflect.generics.factory.GenericsFactory;
import sun.reflect.generics.tree.ClassSignature;
import sun.reflect.generics.tree.TypeTree;
import sun.reflect.generics.visitor.Reifier;
import sun.reflect.generics.parser.SignatureParser;
import java.lang.reflect.Type;
/**
@ -70,47 +70,54 @@ public class ClassRepository extends GenericDeclRepository<ClassSignature> {
return new ClassRepository(rawSig, f);
}
// public API
/*
* When queried for a particular piece of type information, the
* general pattern is to consult the corresponding cached value.
* If the corresponding field is non-null, it is returned.
* If not, it is created lazily. This is done by selecting the appropriate
* part of the tree and transforming it into a reflective object
* using a visitor.
* a visitor, which is created by feeding it the factory
* using a visitor, which is created by feeding it the factory
* with which the repository was created.
*/
public Type getSuperclass() {
Type superclass = this.superclass;
if (superclass == null) { // lazily initialize superclass
Reifier r = getReifier(); // obtain visitor
// Extract superclass subtree from AST and reify
getTree().getSuperclass().accept(r);
// extract result from visitor and cache it
superclass = r.getResult();
this.superclass = superclass;
Type value = superclass;
if (value == null) {
value = computeSuperclass();
superclass = value;
}
return superclass; // return cached result
return value;
}
public Type[] getSuperInterfaces() {
Type[] superInterfaces = this.superInterfaces;
if (superInterfaces == null) { // lazily initialize super interfaces
// first, extract super interface subtree(s) from AST
TypeTree[] ts = getTree().getSuperInterfaces();
// create array to store reified subtree(s)
superInterfaces = new Type[ts.length];
// reify all subtrees
for (int i = 0; i < ts.length; i++) {
Reifier r = getReifier(); // obtain visitor
ts[i].accept(r);// reify subtree
// extract result from visitor and store it
superInterfaces[i] = r.getResult();
}
this.superInterfaces = superInterfaces;
Type[] value = superInterfaces;
if (value == null) {
value = computeSuperInterfaces();
superInterfaces = value;
}
return superInterfaces.clone(); // return cached result
return value.clone();
}
private Type computeSuperclass() {
Reifier r = getReifier(); // obtain visitor
// Extract superclass subtree from AST and reify
getTree().getSuperclass().accept(r);
return r.getResult();
}
private Type[] computeSuperInterfaces() {
// first, extract super interface subtree(s) from AST
TypeTree[] ts = getTree().getSuperInterfaces();
// create array to store reified subtree(s)
int length = ts.length;
Type[] superInterfaces = new Type[length];
// reify all subtrees
for (int i = 0; i < length; i++) {
Reifier r = getReifier(); // obtain visitor
ts[i].accept(r);// reify subtree
// extract result from visitor and store it
superInterfaces[i] = r.getResult();
}
return superInterfaces;
}
}

View File

@ -43,8 +43,11 @@ import sun.reflect.generics.visitor.Reifier;
public class ConstructorRepository
extends GenericDeclRepository<MethodTypeSignature> {
private Type[] paramTypes; // caches the generic parameter types info
private Type[] exceptionTypes; // caches the generic exception types info
/** The generic parameter types. Lazily initialized. */
private volatile Type[] parameterTypes;
/** The generic exception types. Lazily initialized. */
private volatile Type[] exceptionTypes;
// protected, to enforce use of static factory yet allow subclassing
protected ConstructorRepository(String rawSig, GenericsFactory f) {
@ -64,57 +67,67 @@ public class ConstructorRepository
* @return a <tt>ConstructorRepository</tt> that manages the generic type
* information represented in the signature <tt>rawSig</tt>
*/
public static ConstructorRepository make(String rawSig,
GenericsFactory f) {
public static ConstructorRepository make(String rawSig, GenericsFactory f) {
return new ConstructorRepository(rawSig, f);
}
// public API
/*
* When queried for a particular piece of type information, the
* general pattern is to consult the corresponding cached value.
* If the corresponding field is non-null, it is returned.
* If not, it is created lazily. This is done by selecting the appropriate
* part of the tree and transforming it into a reflective object
* using a visitor.
* a visitor, which is created by feeding it the factory
* using a visitor, which is created by feeding it the factory
* with which the repository was created.
*/
public Type[] getParameterTypes(){
if (paramTypes == null) { // lazily initialize parameter types
// first, extract parameter type subtree(s) from AST
TypeSignature[] pts = getTree().getParameterTypes();
// create array to store reified subtree(s)
Type[] ps = new Type[pts.length];
// reify all subtrees
for (int i = 0; i < pts.length; i++) {
Reifier r = getReifier(); // obtain visitor
pts[i].accept(r); // reify subtree
// extract result from visitor and store it
ps[i] = r.getResult();
}
paramTypes = ps; // cache overall result
public Type[] getParameterTypes() {
Type[] value = parameterTypes;
if (value == null) {
value = computeParameterTypes();
parameterTypes = value;
}
return paramTypes.clone(); // return cached result
return value.clone();
}
public Type[] getExceptionTypes(){
if (exceptionTypes == null) { // lazily initialize exception types
// first, extract exception type subtree(s) from AST
FieldTypeSignature[] ets = getTree().getExceptionTypes();
// create array to store reified subtree(s)
Type[] es = new Type[ets.length];
// reify all subtrees
for (int i = 0; i < ets.length; i++) {
Reifier r = getReifier(); // obtain visitor
ets[i].accept(r); // reify subtree
// extract result from visitor and store it
es[i] = r.getResult();
}
exceptionTypes = es; // cache overall result
public Type[] getExceptionTypes() {
Type[] value = exceptionTypes;
if (value == null) {
value = computeExceptionTypes();
exceptionTypes = value;
}
return exceptionTypes.clone(); // return cached result
return value.clone();
}
private Type[] computeParameterTypes() {
// first, extract parameter type subtree(s) from AST
TypeSignature[] pts = getTree().getParameterTypes();
// create array to store reified subtree(s)
int length = pts.length;
Type[] parameterTypes = new Type[length];
// reify all subtrees
for (int i = 0; i < length; i++) {
Reifier r = getReifier(); // obtain visitor
pts[i].accept(r); // reify subtree
// extract result from visitor and store it
parameterTypes[i] = r.getResult();
}
return parameterTypes;
}
private Type[] computeExceptionTypes() {
// first, extract exception type subtree(s) from AST
FieldTypeSignature[] ets = getTree().getExceptionTypes();
// create array to store reified subtree(s)
int length = ets.length;
Type[] exceptionTypes = new Type[length];
// reify all subtrees
for (int i = 0; i < length; i++) {
Reifier r = getReifier(); // obtain visitor
ets[i].accept(r); // reify subtree
// extract result from visitor and store it
exceptionTypes[i] = r.getResult();
}
return exceptionTypes;
}
}

View File

@ -41,7 +41,8 @@ import sun.reflect.generics.visitor.Reifier;
*/
public class FieldRepository extends AbstractRepository<TypeSignature> {
private Type genericType; // caches the generic type info
/** The generic type info. Lazily initialized. */
private volatile Type genericType;
// protected, to enforce use of static factory yet allow subclassing
protected FieldRepository(String rawSig, GenericsFactory f) {
@ -61,31 +62,32 @@ public class FieldRepository extends AbstractRepository<TypeSignature> {
* @return a <tt>FieldRepository</tt> that manages the generic type
* information represented in the signature <tt>rawSig</tt>
*/
public static FieldRepository make(String rawSig,
GenericsFactory f) {
public static FieldRepository make(String rawSig, GenericsFactory f) {
return new FieldRepository(rawSig, f);
}
// public API
/*
* When queried for a particular piece of type information, the
* general pattern is to consult the corresponding cached value.
* If the corresponding field is non-null, it is returned.
* If not, it is created lazily. This is done by selecting the appropriate
* part of the tree and transforming it into a reflective object
* using a visitor.
* a visitor, which is created by feeding it the factory
* using a visitor, which is created by feeding it the factory
* with which the repository was created.
*/
public Type getGenericType(){
if (genericType == null) { // lazily initialize generic type
Reifier r = getReifier(); // obtain visitor
getTree().accept(r); // reify subtree
// extract result from visitor and cache it
genericType = r.getResult();
public Type getGenericType() {
Type value = genericType;
if (value == null) {
value = computeGenericType();
genericType = value;
}
return genericType; // return cached result
return value;
}
private Type computeGenericType() {
Reifier r = getReifier(); // obtain visitor
getTree().accept(r); // reify subtree
return r.getResult(); // extract result from visitor
}
}

View File

@ -43,13 +43,12 @@ public abstract class GenericDeclRepository<S extends Signature>
extends AbstractRepository<S> {
/** The formal type parameters. Lazily initialized. */
private volatile TypeVariable<?>[] typeParams;
private volatile TypeVariable<?>[] typeParameters;
protected GenericDeclRepository(String rawSig, GenericsFactory f) {
super(rawSig, f);
}
// public API
/*
* When queried for a particular piece of type information, the
* general pattern is to consult the corresponding cached value.
@ -61,25 +60,31 @@ public abstract class GenericDeclRepository<S extends Signature>
*/
/**
* Return the formal type parameters of this generic declaration.
* Returns the formal type parameters of this generic declaration.
* @return the formal type parameters of this generic declaration
*/
public TypeVariable<?>[] getTypeParameters() {
TypeVariable<?>[] typeParams = this.typeParams;
if (typeParams == null) { // lazily initialize type parameters
// first, extract type parameter subtree(s) from AST
FormalTypeParameter[] ftps = getTree().getFormalTypeParameters();
// create array to store reified subtree(s)
typeParams = new TypeVariable<?>[ftps.length];
// reify all subtrees
for (int i = 0; i < ftps.length; i++) {
Reifier r = getReifier(); // obtain visitor
ftps[i].accept(r); // reify subtree
// extract result from visitor and store it
typeParams[i] = (TypeVariable<?>) r.getResult();
}
this.typeParams = typeParams; // cache overall result
TypeVariable<?>[] value = typeParameters;
if (value == null) {
value = computeTypeParameters();
typeParameters = value;
}
return typeParams.clone(); // return cached result
return value.clone();
}
private TypeVariable<?>[] computeTypeParameters() {
// first, extract type parameter subtree(s) from AST
FormalTypeParameter[] ftps = getTree().getFormalTypeParameters();
// create array to store reified subtree(s)
int length = ftps.length;
TypeVariable<?>[] typeParameters = new TypeVariable<?>[length];
// reify all subtrees
for (int i = 0; i < length; i++) {
Reifier r = getReifier(); // obtain visitor
ftps[i].accept(r); // reify subtree
// extract result from visitor and store it
typeParameters[i] = (TypeVariable<?>) r.getResult();
}
return typeParameters;
}
}

View File

@ -39,7 +39,8 @@ import sun.reflect.generics.visitor.Reifier;
*/
public class MethodRepository extends ConstructorRepository {
private Type returnType; // caches the generic return type info
/** The generic return type info. Lazily initialized. */
private volatile Type returnType;
// private, to enforce use of static factory
private MethodRepository(String rawSig, GenericsFactory f) {
@ -59,18 +60,21 @@ public class MethodRepository extends ConstructorRepository {
return new MethodRepository(rawSig, f);
}
// public API
public Type getReturnType() {
if (returnType == null) { // lazily initialize return type
Reifier r = getReifier(); // obtain visitor
// Extract return type subtree from AST and reify
getTree().getReturnType().accept(r);
// extract result from visitor and cache it
returnType = r.getResult();
}
return returnType; // return cached result
Type value = returnType;
if (value == null) {
value = computeReturnType();
returnType = value;
}
return value;
}
private Type computeReturnType() {
Reifier r = getReifier(); // obtain visitor
// Extract return type subtree from AST and reify
getTree().getReturnType().accept(r);
// extract result from visitor and cache it
return r.getResult();
}
}

View File

@ -29,7 +29,6 @@ import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.TypeVariable;
/**
* Abstract superclass for lazy scope objects, used when building
* factories for generic information repositories.
@ -49,7 +48,7 @@ public abstract class AbstractScope<D extends GenericDeclaration>
/**
* Constructor. Takes a reflective object whose scope the newly
* constructed instance will represent.
* @param D - A generic declaration whose scope the newly
* @param decl - A generic declaration whose scope the newly
* constructed instance will represent
*/
protected AbstractScope(D decl){ recvr = decl;}
@ -63,7 +62,7 @@ public abstract class AbstractScope<D extends GenericDeclaration>
/** This method must be implemented by any concrete subclass.
* It must return the enclosing scope of this scope. If this scope
* is a top-level scope, an instance of DummyScope must be returned.
* is a top-level scope, an instance of DummyScope must be returned.
* @return The enclosing scope of this scope
*/
protected abstract Scope computeEnclosingScope();
@ -72,13 +71,13 @@ public abstract class AbstractScope<D extends GenericDeclaration>
* Accessor for the enclosing scope, which is computed lazily and cached.
* @return the enclosing scope
*/
protected Scope getEnclosingScope(){
Scope enclosingScope = this.enclosingScope;
if (enclosingScope == null) {
enclosingScope = computeEnclosingScope();
this.enclosingScope = enclosingScope;
protected Scope getEnclosingScope() {
Scope value = enclosingScope;
if (value == null) {
value = computeEnclosingScope();
enclosingScope = value;
}
return enclosingScope;
return value;
}
/**

View File

@ -27,7 +27,7 @@ package sun.reflect.generics.tree;
/**
* Common superinterface for generic signatures. These are the signatures
* of complete class and method/constructor delcarations.
* of complete class and method/constructor declarations.
*/
public interface Signature extends Tree{
FormalTypeParameter[] getFormalTypeParameters();

View File

@ -28,8 +28,8 @@ package sun.reflect.generics.tree;
import sun.reflect.generics.visitor.TypeTreeVisitor;
public class Wildcard implements TypeArgument {
private FieldTypeSignature[] upperBounds;
private FieldTypeSignature[] lowerBounds;
private final FieldTypeSignature[] upperBounds;
private final FieldTypeSignature[] lowerBounds;
private Wildcard(FieldTypeSignature[] ubs, FieldTypeSignature[] lbs) {
upperBounds = ubs;
@ -43,11 +43,11 @@ public class Wildcard implements TypeArgument {
return new Wildcard(ubs, lbs);
}
public FieldTypeSignature[] getUpperBounds(){
public FieldTypeSignature[] getUpperBounds() {
return upperBounds;
}
public FieldTypeSignature[] getLowerBounds(){
public FieldTypeSignature[] getLowerBounds() {
if (lowerBounds.length == 1 &&
lowerBounds[0] == BottomSignature.make())
return emptyBounds;

View File

@ -39,7 +39,7 @@ import sun.reflect.generics.factory.*;
*/
public class Reifier implements TypeTreeVisitor<Type> {
private Type resultType;
private GenericsFactory factory;
private final GenericsFactory factory;
private Reifier(GenericsFactory f){
factory = f;

View File

@ -40,6 +40,7 @@ import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import sun.misc.IOUtils;
@ -216,17 +217,21 @@ public final class MethodUtil extends SecureClassLoader {
* key in the method cache.
*/
private static class Signature {
private String methodName;
private Class<?>[] argClasses;
private volatile int hashCode = 0;
private final String methodName;
private final Class<?>[] argClasses;
private final int hashCode;
Signature(Method m) {
this.methodName = m.getName();
this.argClasses = m.getParameterTypes();
this.hashCode = methodName.hashCode() + Arrays.hashCode(argClasses);
}
public boolean equals(Object o2) {
@Override public int hashCode() {
return hashCode;
}
@Override public boolean equals(Object o2) {
if (this == o2) {
return true;
}
@ -244,25 +249,6 @@ public final class MethodUtil extends SecureClassLoader {
}
return true;
}
/**
* Hash code computed using algorithm suggested in
* Effective Java, Item 8.
*/
public int hashCode() {
if (hashCode == 0) {
int result = 17;
result = 37 * result + methodName.hashCode();
if (argClasses != null) {
for (int i = 0; i < argClasses.length; i++) {
result = 37 * result + ((argClasses[i] == null) ? 0 :
argClasses[i].hashCode());
}
}
hashCode = result;
}
return hashCode;
}
}

View File

@ -319,7 +319,7 @@ public final class ReflectUtil {
return;
}
// disallow any method not declared in one of the proxy intefaces
// disallow any method not declared in one of the proxy interfaces
throw new IllegalArgumentException("Can't handle: " + method);
}