/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Common Public License (CPL); * You may not use this file except in compliance with the License. You * may obtain a copy of the License at * * http://www.opensource.org/licenses/cpl1.0.php * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ package java.lang; import java.io.InputStream; import java.io.Serializable; import java.security.AccessController; import java.security.PrivilegedAction; import java.security.ProtectionDomain; import java.security.AllPermission; import java.security.Permissions; import java.lang.annotation.Annotation; import java.lang.reflect.AccessibleObject; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.GenericDeclaration; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.JikesRVMSupport; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.net.URL; import java.util.ArrayList; import org.jikesrvm.classloader.*; import org.jikesrvm.VM; import org.jikesrvm.VM_Callbacks; import org.jikesrvm.runtime.VM_Reflection; import org.jikesrvm.runtime.VM_Runtime; import org.jikesrvm.VM_UnimplementedError; import org.jikesrvm.annotations.NoSubArchCompile; /** * Implementation of java.lang.Class for JikesRVM. * * By convention, order methods in the same order * as they appear in the method summary list of Sun's 1.4 Javadoc API. */ public final class Class<T> implements Serializable, Type, AnnotatedElement, GenericDeclaration { private static final class StaticData { static final ProtectionDomain unknownProtectionDomain; static { Permissions permissions = new Permissions(); permissions.add(new AllPermission()); unknownProtectionDomain = new ProtectionDomain(null, permissions); } } static final long serialVersionUID = 3206093459760846163L; /** * Prevents this class from being instantiated, except by the * create method in this class. */ private Class() {} /** * This field holds the VM_Type object for this class. */ VM_Type type; /** * This field holds the protection domain of this class. */ ProtectionDomain pd; /** * The signers of this class */ Object[] signers; public boolean desiredAssertionStatus() { return true; // TODO: assertion status support isn't yet present } public static Class<?> forName(String typeName) throws ClassNotFoundException { ClassLoader parentCL = VM_Class.getClassLoaderFromStackFrame(1); return forNameInternal(typeName, true, parentCL); } @NoSubArchCompile public static Class<?> forName(String className, boolean initialize, ClassLoader classLoader) throws ClassNotFoundException, LinkageError, ExceptionInInitializerError { if (classLoader == null) { SecurityManager security = System.getSecurityManager(); if (security != null) { ClassLoader parentCL = VM_Class.getClassLoaderFromStackFrame(1); if (parentCL != null) { try { security.checkPermission(new RuntimePermission("getClassLoader")); } catch (SecurityException e) { throw new ClassNotFoundException("Security exception when" + " trying to get a classloader so we can load the" + " class named \"" + className +"\"", e); } } } classLoader = VM_BootstrapClassLoader.getBootstrapClassLoader(); } return forNameInternal(className, initialize, classLoader); } @NoSubArchCompile public Class<?>[] getClasses() throws SecurityException { checkMemberAccess(Member.PUBLIC); if (!type.isClassType()) return new Class[0]; ArrayList<Class<?>> publicClasses = new ArrayList<Class<?>>(); for (Class<?> c = this; c != null; c = c.getSuperclass()) { c.checkMemberAccess(Member.PUBLIC); VM_TypeReference[] declaredClasses = c.type.asClass().getDeclaredClasses(); if (declaredClasses != null) { for (VM_TypeReference declaredClass : declaredClasses) { if (declaredClass != null) { VM_Class dc = declaredClass.resolve(false).asClass(); if (dc.isPublic()) { publicClasses.add(dc.getClassForType()); } } } } } Class<?>[] result = new Class[publicClasses.size()]; result = publicClasses.toArray(result); return result; } @NoSubArchCompile public ClassLoader getClassLoader() { SecurityManager security = System.getSecurityManager(); if (security != null) { ClassLoader parentCL = VM_Class.getClassLoaderFromStackFrame(1); if (parentCL != null) { security.checkPermission(new RuntimePermission("getClassLoader")); } } ClassLoader cl = type.getClassLoader(); return cl == VM_BootstrapClassLoader.getBootstrapClassLoader() ? null : cl; } public Class<?> getComponentType() { return type.isArrayType() ? type.asArray().getElementType().getClassForType(): null; } public Constructor<?> getConstructor(Class<?>[] parameterTypes) throws NoSuchMethodException, SecurityException { checkMemberAccess(Member.PUBLIC); if (!type.isClassType()) throw new NoSuchMethodException(); VM_Method[] methods = type.asClass().getConstructorMethods(); for (VM_Method method : methods) { if (method.isPublic() && parametersMatch(method.getParameterTypes(), parameterTypes)) { return JikesRVMSupport.createConstructor(method); } } throw new NoSuchMethodException("<init> " + parameterTypes); } @NoSubArchCompile public Constructor<?>[] getConstructors() throws SecurityException { checkMemberAccess(Member.PUBLIC); if (!type.isClassType()) return new Constructor[0]; VM_Method[] methods = type.asClass().getConstructorMethods(); Collector coll = new Collector(methods.length); for (VM_Method method : methods) { if (method.isPublic()) { coll.collect(JikesRVMSupport.createConstructor(method)); } } return coll.constructorArray(); } @NoSubArchCompile public Class<?>[] getDeclaredClasses() throws SecurityException { checkMemberAccess(Member.DECLARED); if (!type.isClassType()) return new Class[0]; // Get array of declared classes from VM_Class object VM_Class cls = type.asClass(); VM_TypeReference[] declaredClasses = cls.getDeclaredClasses(); // The array can be null if the class has no declared inner class members if (declaredClasses == null) return new Class[0]; // Count the number of actual declared inner and static classes. // (The array may contain null elements, which we want to skip.) int count = 0; int length = declaredClasses.length; for (int i = 0; i < length; ++i) { if (declaredClasses[i] != null) { ++count; } } // Now build actual result array. Class<?>[] result = new Class[count]; count = 0; for (int i = 0; i < length; ++i) { if (declaredClasses[i] != null) { result[count++] = declaredClasses[i].resolve(false).getClassForType(); } } return result; } public Constructor<?> getDeclaredConstructor(Class<?>[] parameterTypes) throws NoSuchMethodException, SecurityException { checkMemberAccess(Member.DECLARED); if (!type.isClassType()) throw new NoSuchMethodException(); VM_Method[] methods = type.asClass().getConstructorMethods(); for (int i = 0, n = methods.length; i < n; ++i) { VM_Method method = methods[i]; if (parametersMatch(method.getParameterTypes(), parameterTypes)) { return JikesRVMSupport.createConstructor(method); } } throw new NoSuchMethodException("<init> " + parameterTypes); } @NoSubArchCompile public Constructor<?>[] getDeclaredConstructors() throws SecurityException { checkMemberAccess(Member.DECLARED); if (!type.isClassType()) return new Constructor[0]; VM_Method[] methods = type.asClass().getConstructorMethods(); Constructor<?>[] ans = new Constructor[methods.length]; for (int i = 0; i<methods.length; i++) { ans[i] = JikesRVMSupport.createConstructor(methods[i]); } return ans; } public Field getDeclaredField(String name) throws NoSuchFieldException, SecurityException { checkMemberAccess(Member.DECLARED); if (!type.isClassType()) throw new NoSuchFieldException(); VM_Atom aName = VM_Atom.findUnicodeAtom(name); if (aName == null) throw new NoSuchFieldException(name); VM_Field[] fields = type.asClass().getDeclaredFields(); for (VM_Field field : fields) { if (field.getName() == aName) { return JikesRVMSupport.createField(field); } } throw new NoSuchFieldException(name); } @NoSubArchCompile public Field[] getDeclaredFields() throws SecurityException { checkMemberAccess(Member.DECLARED); if (!type.isClassType()) return new Field[0]; VM_Field[] fields = type.asClass().getDeclaredFields(); Field[] ans = new Field[fields.length]; for (int i = 0; i < fields.length; i++) { ans[i] = JikesRVMSupport.createField(fields[i]); } return ans; } @NoSubArchCompile public Method getDeclaredMethod(String name, Class<?>[] parameterTypes) throws NoSuchMethodException, SecurityException { checkMemberAccess(Member.DECLARED); if (!type.isClassType()) { throw new NoSuchMethodException(name + parameterTypes); } VM_Atom aName = VM_Atom.findUnicodeAtom(name); if (aName == null || aName == VM_ClassLoader.StandardClassInitializerMethodName || aName == VM_ClassLoader.StandardObjectInitializerMethodName) { // null means that we don't have such an atom; // <init> and <clinit> are not methods. throw new NoSuchMethodException(name + parameterTypes); } VM_Method[] methods = type.asClass().getDeclaredMethods(); Method answer = null; for (VM_Method meth : methods) { if (meth.getName() == aName && parametersMatch(meth.getParameterTypes(), parameterTypes)) { if (answer == null) { answer = JikesRVMSupport.createMethod(meth); } else { Method m2 = JikesRVMSupport.createMethod(meth); if (answer.getReturnType().isAssignableFrom(m2.getReturnType())) { answer = m2; } } } } if (answer != null) return answer; throw new NoSuchMethodException(name + parameterTypes); } @NoSubArchCompile public Method[] getDeclaredMethods() throws SecurityException { checkMemberAccess(Member.DECLARED); if (!type.isClassType()) return new Method[0]; VM_Method[] methods = type.asClass().getDeclaredMethods(); Collector coll = new Collector(methods.length); for (VM_Method meth : methods) { if (!meth.isClassInitializer() && !meth.isObjectInitializer()) { coll.collect(JikesRVMSupport.createMethod(meth)); } } return coll.methodArray(); } public Class<?> getDeclaringClass() { if (!type.isClassType()) return null; VM_TypeReference dc = type.asClass().getDeclaringClass(); if (dc == null) return null; return dc.resolve(false).getClassForType(); } public Field getField(String name) throws NoSuchFieldException, SecurityException { checkMemberAccess(Member.PUBLIC); if (!type.isClassType()) throw new NoSuchFieldException(); VM_Atom aName = VM_Atom.findUnicodeAtom(name); if (aName == null) throw new NoSuchFieldException(name); Field ans = getFieldInternal(aName); if (ans == null) { throw new NoSuchFieldException(name); } else { return ans; } } @NoSubArchCompile public Field[] getFields() throws SecurityException { checkMemberAccess(Member.PUBLIC); VM_Field[] static_fields = type.getStaticFields(); VM_Field[] instance_fields = type.getInstanceFields(); Collector coll = new Collector(static_fields.length + instance_fields.length); for (VM_Field field : static_fields) { if (field.isPublic()) { coll.collect(JikesRVMSupport.createField(field)); } } for (VM_Field field : instance_fields) { if (field.isPublic()) { coll.collect(JikesRVMSupport.createField(field)); } } return coll.fieldArray(); } @NoSubArchCompile public Class<?>[] getInterfaces() { if (type.isArrayType()) { // arrays implement JavaLangSerializable & JavaLangCloneable return new Class[] { VM_Type.JavaLangCloneableType.getClassForType(), VM_Type.JavaIoSerializableType.getClassForType() }; } else if (type.isClassType()) { VM_Class[] interfaces = type.asClass().getDeclaredInterfaces(); Class<?>[] jinterfaces = new Class[interfaces.length]; for (int i = 0; i != interfaces.length; i++) jinterfaces[i] = interfaces[i].getClassForType(); return jinterfaces; } else { return new Class[0]; } } @NoSubArchCompile public Method getMethod(String name, Class<?>[] parameterTypes) throws NoSuchMethodException, SecurityException { checkMemberAccess(Member.PUBLIC); if (!type.isClassType()) throw new NoSuchMethodException(name + parameterTypes); VM_Atom aName = VM_Atom.findUnicodeAtom(name); if (aName == null || aName == VM_ClassLoader.StandardClassInitializerMethodName || aName == VM_ClassLoader.StandardObjectInitializerMethodName) { // null means that we don't have such an atom; <init> and <clinit> are not methods. throw new NoSuchMethodException(name + parameterTypes); } // (1) Scan the declared public methods of this class and each of its superclasses for (VM_Class current = type.asClass(); current != null; current = current.getSuperClass()) { VM_Method[] methods = current.getDeclaredMethods(); Method answer = null; for (VM_Method meth : methods) { if (meth.getName() == aName && meth.isPublic() && parametersMatch(meth.getParameterTypes(), parameterTypes)) { if (answer == null) { answer = JikesRVMSupport.createMethod(meth); } else { Method m2 = JikesRVMSupport.createMethod(meth); if (answer.getReturnType().isAssignableFrom(m2.getReturnType())) { answer = m2; } } } } if (answer != null) return answer; } // (2) Now we need to consider methods inherited from interfaces. // Because we inject the requisite Miranda methods, we can do this simply // by looking at this class's virtual methods instead of searching interface hierarchies. VM_Method[] methods = type.asClass().getVirtualMethods(); Method answer = null; for (VM_Method meth : methods) { if (meth.getName() == aName && meth.isPublic() && parametersMatch(meth.getParameterTypes(), parameterTypes)) { if (answer == null) { answer = JikesRVMSupport.createMethod(meth); } else { Method m2 = JikesRVMSupport.createMethod(meth); if (answer.getReturnType().isAssignableFrom(m2.getReturnType())) { answer = m2; } } } } if (answer != null) return answer; throw new NoSuchMethodException(name + parameterTypes); } @NoSubArchCompile public Method[] getMethods() throws SecurityException { checkMemberAccess(Member.PUBLIC); VM_Method[] static_methods = type.getStaticMethods(); VM_Method[] virtual_methods = type.getVirtualMethods(); Collector coll = new Collector(static_methods.length + virtual_methods.length); for (VM_Method meth : static_methods) { if (meth.isPublic()) { coll.collect(JikesRVMSupport.createMethod(meth)); } } for (VM_Method meth : virtual_methods) { if (meth.isPublic()) { coll.collect(JikesRVMSupport.createMethod(meth)); } } return coll.methodArray(); } public int getModifiers() { if (type.isClassType()) { return type.asClass().getModifiers(); } else if (type.isArrayType()) { VM_Type innermostElementType = type.asArray().getInnermostElementType(); int result = Modifier.FINAL; if (innermostElementType.isClassType()) { int component = innermostElementType.asClass().getModifiers(); result |= (component & (Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE)); } else { result |= Modifier.PUBLIC; // primitive } return result; } else { return Modifier.PUBLIC | Modifier.FINAL; } } public String getName() { return type.toString(); } public Package getPackage() { ClassLoader cl = type.getClassLoader(); return cl.getPackage(getPackageName()); } @NoSubArchCompile public ProtectionDomain getProtectionDomain() { SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkPermission(new RuntimePermission("getProtectionDomain")); } return pd == null ? StaticData.unknownProtectionDomain : pd; } public URL getResource(String resName) { ClassLoader loader = type.getClassLoader(); if (loader == VM_BootstrapClassLoader.getBootstrapClassLoader()) return ClassLoader.getSystemResource(toResourceName(resName)); else return loader.getResource(toResourceName(resName)); } public InputStream getResourceAsStream(String resName) { ClassLoader loader = type.getClassLoader(); if (loader == VM_BootstrapClassLoader.getBootstrapClassLoader()) return ClassLoader.getSystemResourceAsStream(toResourceName(resName)); else return loader.getResourceAsStream(toResourceName(resName)); } public Object[] getSigners() { if (signers == null) { return null; } else { return signers.clone(); } } public Class<?> getSuperclass() { if (type.isArrayType()) { return VM_Type.JavaLangObjectType.getClassForType(); } else if (type.isClassType()) { VM_Class myClass = type.asClass(); if (myClass.isInterface()) return null; VM_Type supe = myClass.getSuperClass(); return supe == null ? null : supe.getClassForType(); } else { return null; } } public boolean isArray() { return type.isArrayType(); } public boolean isAssignableFrom(Class<?> cls) { return type == cls.type || VM_Runtime.isAssignableWith(type, cls.type); } public boolean isInstance(Object object) { if (object == null) return false; if (isPrimitive()) return false; return isAssignableFrom(object.getClass()); } public boolean isInterface() { return type.isClassType() && type.asClass().isInterface(); } public boolean isPrimitive() { return type.isPrimitiveType(); } @NoSubArchCompile public T newInstance() throws IllegalAccessException, InstantiationException, ExceptionInInitializerError, SecurityException { // Basic checks checkMemberAccess(Member.PUBLIC); if (!type.isClassType()) throw new InstantiationException(); VM_Class cls = type.asClass(); if (cls.isAbstract() || cls.isInterface()) throw new InstantiationException(); if (!cls.isInitialized(false)) { cls.resolve(false); cls.instantiate(false); cls.initialize(false); } if (cls.isDeclaredForSubArch()) { cls.load(true); cls.resolve(true); cls.instantiate(true); cls.initialize(true); } // Find the defaultConstructor VM_Method defaultConstructor = null; VM_Method[] methods = type.asClass().getConstructorMethods(); for (VM_Method method : methods) { if (method.getParameterTypes().length == 0) { defaultConstructor = method; break; } } if (defaultConstructor == null) throw new InstantiationException(); // Check that caller is allowed to access it if (!defaultConstructor.isPublic()) { VM_Class accessingClass = VM_Class.getClassFromStackFrame(1); JikesRVMSupport.checkAccess(defaultConstructor, accessingClass); } // Ensure that the class is initialized if (!cls.isInitialized(false)) { try { VM_Runtime.initializeClassForDynamicLink(cls); } catch (Throwable e) { ExceptionInInitializerError ex = new ExceptionInInitializerError(); ex.initCause(e); throw ex; } } // Allocate an uninitialized instance; @SuppressWarnings("unchecked") // yes, we're giving an anonymous object a type. T obj = (T)VM_Runtime.resolvedNewScalar(cls); // Run the default constructor on the it. VM_Reflection.invoke(defaultConstructor, obj, null); return obj; } public String toString() { String name = getName(); if (isPrimitive()) { return name; } else if (isInterface()) { return "interface "+name; } else { return "class "+name; } } /* * Implementation below */ /** * Create a java.lang.Class corresponding to a given VM_Type */ static <T> Class<T> create(VM_Type type) { Class<T> c = new Class<T>(); c.type = type; return c; } void setSigners(Object[] signers) { this.signers = signers; } private static Class<?> forNameInternal(String className, boolean initialize, ClassLoader classLoader) throws ClassNotFoundException, LinkageError, ExceptionInInitializerError { try { if (className.startsWith("[")) { if (!validArrayDescriptor(className)) { throw new ClassNotFoundException(className); } } VM_Atom descriptor = VM_Atom .findOrCreateAsciiAtom(className.replace('.','/')) .descriptorFromClassName(); VM_TypeReference tRef = VM_TypeReference.findOrCreate(classLoader, descriptor); VM_Type ans = tRef.resolve(false); VM_Callbacks.notifyForName(ans); if (initialize && !ans.isInitialized(false)) { ans.resolve(false); ans.instantiate(false); ans.initialize(false); if (ans.isDeclaredForSubArch()) { ans.load(true); ans.resolve(true); ans.instantiate(true); ans.initialize(true); } } return ans.getClassForType(); } catch (NoClassDefFoundError ncdfe) { Throwable cause2 = ncdfe.getCause(); ClassNotFoundException cnf; // If we get a NCDFE that was caused by a CNFE, throw the original CNFE. if (cause2 instanceof ClassNotFoundException) cnf = (ClassNotFoundException) cause2; else cnf = new ClassNotFoundException(className, ncdfe); throw cnf; } } private Field getFieldInternal(VM_Atom name) { VM_Class ctype = type.asClass(); // (1) Check my public declared fields VM_Field[] fields = ctype.getDeclaredFields(); for (VM_Field field : fields) { if (field.isPublic() && field.getName() == name) { return JikesRVMSupport.createField(field); } } // (2) Check superinterfaces VM_Class[] interfaces = ctype.getDeclaredInterfaces(); for (VM_Class anInterface : interfaces) { Field ans = anInterface.getClassForType().getFieldInternal(name); if (ans != null) return ans; } // (3) Check superclass (if I have one). if (ctype.getSuperClass() != null) { return ctype.getSuperClass().getClassForType().getFieldInternal(name); } return null; } private String getPackageName() { String name = getName(); int index = name.lastIndexOf('.'); if (index >= 0) return name.substring(0, index); return ""; } private String toResourceName(String resName) { // Turn package name into a directory path if (resName.charAt(0) == '/') return resName.substring(1); String qualifiedClassName = getName(); int classIndex = qualifiedClassName.lastIndexOf('.'); if (classIndex == -1) return resName; // from a default package return qualifiedClassName.substring(0, classIndex + 1).replace('.', '/') + resName; } private static boolean validArrayDescriptor(String name) { int i; int length = name.length(); for (i = 0; i < length; i++) if (name.charAt(i) != '[') break; if (i == length) return false; // string of only ['s if (i == length - 1) { switch (name.charAt(i)) { case 'B': return true; // byte case 'C': return true; // char case 'D': return true; // double case 'F': return true; // float case 'I': return true; // integer case 'J': return true; // long case 'S': return true; // short case 'Z': return true; // boolean default: return false; } } else if (name.charAt(i) != 'L') { return false; // not a class descriptor } else if (name.charAt(length - 1) != ';') { return false; // ditto } return true; // a valid class descriptor } /** * Utility for security checks */ @NoSubArchCompile private void checkMemberAccess(int type) { SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkMemberAccess(this, type); String packageName = getPackageName(); if(packageName != "") { security.checkPackageAccess(packageName); } } } /** * Compare parameter lists for agreement. */ private boolean parametersMatch(VM_TypeReference[] lhs, Class<?>[] rhs) { if (rhs == null) return lhs.length == 0; if (lhs.length != rhs.length) return false; for (int i = 0, n = lhs.length; i < n; ++i) { if (rhs[i] == null) return false; if (lhs[i].resolve(false) != rhs[i].type) { return false; } } return true; } // aux class to build up collections of things private static final class Collector { private int n = 0; private final Object[] coll; Collector(int max) { coll = new Object[max]; } void collect(Object thing) { coll[n++] = thing; } // repeat for each class of interest // Method[] methodArray() { Method[] ans = new Method[n]; System.arraycopy(coll, 0, ans, 0, n); return ans; } Field[] fieldArray() { Field[] ans = new Field[n]; System.arraycopy(coll, 0, ans, 0, n); return ans; } Constructor<?>[] constructorArray() { Constructor<?>[] ans = new Constructor[n]; System.arraycopy(coll, 0, ans, 0, n); return ans; } } public boolean isAnonymousClass() { if (type.isClassType()) { return type.asClass().isAnonymousClass(); } else { return false; } } public boolean isLocalClass() { if (type.isClassType()) { return type.asClass().isLocalClass(); } else { return false; } } public boolean isMemberClass() { if (type.isClassType()) { return type.asClass().isMemberClass(); } else { return false; } } // AnnotatedElement interface public Annotation[] getDeclaredAnnotations() { return type.getDeclaredAnnotations(); } public Annotation[] getAnnotations() { return type.getAnnotations(); } //@Override public <U extends Annotation> U getAnnotation(Class<U> annotationClass) { return type.getAnnotation(annotationClass); } //@Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) { return type.isAnnotationPresent(annotationClass); } // Generics support @NoSubArchCompile public Type[] getGenericInterfaces() { if (type.isPrimitiveType()) { return new Type[0]; } else if (type.isArrayType()) { // arrays implement JavaLangSerializable & JavaLangCloneable return new Class[] { VM_Type.JavaLangCloneableType.getClassForType(), VM_Type.JavaIoSerializableType.getClassForType()}; } else { VM_Class klass = type.asClass(); VM_Atom sig = klass.getSignature(); if (sig == null) { return getInterfaces(); } else { return JikesRVMHelpers.getInterfaceTypesFromSignature(this, sig); } } } public Type getGenericSuperclass() { if (type.isArrayType()) { return Object.class; } else if (type.isPrimitiveType() || (type.isClassType() && type.asClass().isInterface()) || this == Object.class) { return null; } else { VM_Class klass = type.asClass(); VM_Atom sig = klass.getSignature(); if (sig == null) { return getSuperclass(); } else { return JikesRVMHelpers.getSuperclassType(this, sig); } } } @NoSubArchCompile public TypeVariable<?>[] getTypeParameters() { if (!type.isClassType()) { return new TypeVariable[0]; } else { VM_Class klass = type.asClass(); VM_Atom sig = klass.getSignature(); if (sig == null) { return new TypeVariable[0]; } else { return JikesRVMHelpers.getTypeParameters(this, sig); } } } public String getSimpleName() { if (type.isArrayType()) { return getComponentType().getSimpleName() + "[]"; } else { String fullName = getName(); return fullName.substring(fullName.lastIndexOf(".") + 1); } } public String getCanonicalName() { if (type.isArrayType()) { String componentName = getComponentType().getCanonicalName(); if (componentName != null) return componentName + "[]"; } if (isMemberClass()) { String memberName = getDeclaringClass().getCanonicalName(); if (memberName != null) return memberName + "." + getSimpleName(); } if (isLocalClass() || isAnonymousClass()) return null; return getName(); } public Class<?> getEnclosingClass() { if (type.isClassType()) { VM_TypeReference enclosingClass = type.asClass().getEnclosingClass(); if(enclosingClass != null) { return enclosingClass.resolve(false).getClassForType(); } else { return null; } } else { return null; } } @NoSubArchCompile public Constructor<? super T> getEnclosingConstructor() { throw new VM_UnimplementedError(); } @NoSubArchCompile public Method getEnclosingMethod() { throw new VM_UnimplementedError(); } @NoSubArchCompile public Object cast(Object obj) { if (obj != null && ! isInstance(obj)) { throw new ClassCastException(); } return obj; } // Enumeration support @NoSubArchCompile public Object[] getEnumConstants() { if (isEnum()) { try { return (Object[])getMethod("values", new Class[0]).invoke(null, new Object[0]); } catch (NoSuchMethodException exception) { throw new Error("Enum lacks values() method"); } catch (IllegalAccessException exception) { throw new Error("Unable to access Enum class"); } catch (InvocationTargetException exception) { throw new RuntimeException("The values method threw an exception", exception); } } else { return null; } } public boolean isEnum() { if(type.isClassType()) { return type.asClass().isEnum(); } else { return false; } } /** * Utility method for use by classes in this package. */ static void setAccessible(final AccessibleObject obj) { AccessController.doPrivileged(new PrivilegedAction<Object>() { public Object run() { obj.setAccessible(true); return null; } }); } }