Index: java/lang/Class.java =================================================================== RCS file: /cvsroot/classpath/classpath/java/lang/Class.java,v retrieving revision 1.34 diff -u -r1.34 Class.java --- java/lang/Class.java 11 Mar 2005 11:19:54 -0000 1.34 +++ java/lang/Class.java 23 Mar 2005 14:34:00 -0000 @@ -39,7 +39,7 @@ package java.lang; import gnu.classpath.VMStackWalker; - +import gnu.java.lang.reflect.VMField; import java.io.InputStream; import java.io.Serializable; import java.lang.reflect.Constructor; @@ -48,6 +48,7 @@ import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.lang.ref.SoftReference; import java.net.URL; import java.security.AccessController; import java.security.AllPermission; @@ -114,10 +115,15 @@ } } + private static final class ReflectionCache + { + Constructor constructor; + VMField[] fields; + } + final transient Object vmdata; - /** newInstance() caches the default constructor */ - private transient Constructor constructor; + private transient SoftReference reflectionCache; /** * Class is non-instantiable from Java code; only the VM can create @@ -437,11 +443,11 @@ public Field getDeclaredField(String name) throws NoSuchFieldException { memberAccessCheck(Member.DECLARED); - Field[] fields = getDeclaredFields(false); - for (int i = 0; i < fields.length; i++) + VMField[] vmfields = getDeclaredVMFields(); + for (int i = 0; i < vmfields.length; i++) { - if (fields[i].getName().equals(name)) - return fields[i]; + if (vmfields[i].getName().equals(name)) + return vmfields[i].newField(); } throw new NoSuchFieldException(); } @@ -461,12 +467,19 @@ public Field[] getDeclaredFields() { memberAccessCheck(Member.DECLARED); - return getDeclaredFields(false); + VMField[] vmfields = getDeclaredVMFields(); + Field[] fields = new Field[vmfields.length]; + for (int i = 0; i < vmfields.length; i++) + fields[i] = vmfields[i].newField(); + return fields; } - Field[] getDeclaredFields (boolean publicOnly) - { - return VMClass.getDeclaredFields (this, publicOnly); + private VMField[] getDeclaredVMFields() + { + ReflectionCache rc = getReflectionCache(); + if (rc.fields == null) + rc.fields = VMClass.getDeclaredVMFields(this); + return rc.fields; } /** @@ -558,10 +571,10 @@ throws NoSuchFieldException { memberAccessCheck(Member.PUBLIC); - Field field = internalGetField(fieldName); + VMField field = internalGetField(fieldName); if (field == null) throw new NoSuchFieldException(fieldName); - return field; + return field.newField(); } /** @@ -588,7 +601,12 @@ private Field[] internalGetFields() { HashSet set = new HashSet(); - set.addAll(Arrays.asList(getDeclaredFields(true))); + VMField[] vmfields = getDeclaredVMFields(); + for (int i = 0; i < vmfields.length; i++) + { + if (Modifier.isPublic(vmfields[i].getModifiers())) + set.add(vmfields[i].newField()); + } Class[] interfaces = getInterfaces(); for (int i = 0; i < interfaces.length; i++) set.addAll(Arrays.asList(interfaces[i].internalGetFields())); @@ -854,7 +872,7 @@ */ public int getModifiers() { - return VMClass.getModifiers (this); + return VMClass.getModifiers (this, false); } /** @@ -1095,10 +1113,11 @@ throws InstantiationException, IllegalAccessException { memberAccessCheck(Member.PUBLIC); + ReflectionCache rc = getReflectionCache(); Constructor constructor; - synchronized(this) + synchronized (rc) { - constructor = this.constructor; + constructor = rc.constructor; } if (constructor == null) { @@ -1114,7 +1133,7 @@ if (constructor == null) throw new InstantiationException(getName()); if (!Modifier.isPublic(constructor.getModifiers()) - || !Modifier.isPublic(getModifiers())) + || !Modifier.isPublic(VMClass.getModifiers(this, true))) { final Constructor finalConstructor = constructor; AccessController.doPrivileged(new PrivilegedAction() @@ -1126,15 +1145,15 @@ } }); } - synchronized(this) + synchronized (rc) { - if (this.constructor == null) - this.constructor = constructor; - } + if (rc.constructor == null) + rc.constructor = constructor; + } } int modifiers = constructor.getModifiers(); if (!Modifier.isPublic(modifiers) - || !Modifier.isPublic(getModifiers())) + || !Modifier.isPublic(VMClass.getModifiers(this, true))) { Class caller = VMStackWalker.getCallingClass(); if (caller != null && @@ -1270,19 +1289,20 @@ * Like getField(String) but without the security checks and returns null * instead of throwing NoSuchFieldException. */ - private Field internalGetField(String name) + private VMField internalGetField(String name) { - Field[] fields = getDeclaredFields(true); + VMField[] fields = getDeclaredVMFields(); for (int i = 0; i < fields.length; i++) { - Field field = fields[i]; - if (field.getName().equals(name)) + VMField field = fields[i]; + if (Modifier.isPublic(field.getModifiers()) + && field.getName().equals(name)) return field; } Class[] interfaces = getInterfaces(); for (int i = 0; i < interfaces.length; i++) { - Field field = interfaces[i].internalGetField(name); + VMField field = interfaces[i].internalGetField(name); if(field != null) return field; } @@ -1321,4 +1341,17 @@ sm.checkPackageAccess(pkg.getName()); } } + + private ReflectionCache getReflectionCache() + { + ReflectionCache rc = null; + if (reflectionCache != null) + rc = (ReflectionCache)reflectionCache.get(); + if (rc == null) + { + rc = new ReflectionCache(); + reflectionCache = new SoftReference(rc); + } + return rc; + } } Index: vm/reference/java/lang/VMClass.java =================================================================== RCS file: /cvsroot/classpath/classpath/vm/reference/java/lang/VMClass.java,v retrieving revision 1.10 diff -u -r1.10 VMClass.java --- vm/reference/java/lang/VMClass.java 25 Apr 2004 12:03:01 -0000 1.10 +++ vm/reference/java/lang/VMClass.java 23 Mar 2005 14:34:05 -0000 @@ -37,6 +37,7 @@ package java.lang; +import gnu.java.lang.reflect.VMField; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; @@ -185,11 +186,18 @@ * public and final, but not an interface. * * @param klass the Class object that's calling us + * @param ignoreInnerClassesAttrib if set, return the real modifiers, not + * the ones specified in the InnerClasses attribute. * @return the modifiers of this class * @see Modifer * @since 1.1 */ - static native int getModifiers(Class klass); + static int getModifiers(Class klass, boolean ignoreInnerClassesAttrib) + { + return getModifiers(klass); + } + + private static native int getModifiers(Class klass); /** * If this is a nested or inner class, return the class that declared it. @@ -213,9 +221,8 @@ * Like getDeclaredFields() but without the security checks. * * @param klass the Class object that's calling us - * @param pulicOnly Only public fields should be returned */ - static native Field[] getDeclaredFields(Class klass, boolean publicOnly); + static native VMField[] getDeclaredVMFields(Class klass); /** * Like getDeclaredMethods() but without the security checks. Index: vm/reference/java/lang/reflect/Field.java =================================================================== RCS file: /cvsroot/classpath/classpath/vm/reference/java/lang/reflect/Field.java,v retrieving revision 1.9 diff -u -r1.9 Field.java --- vm/reference/java/lang/reflect/Field.java 29 Mar 2004 07:07:40 -0000 1.9 +++ vm/reference/java/lang/reflect/Field.java 23 Mar 2005 14:34:05 -0000 @@ -38,6 +38,9 @@ package java.lang.reflect; +import gnu.classpath.VMStackWalker; +import gnu.java.lang.reflect.VMField; + /** * The Field class represents a member variable of a class. It also allows * dynamic access to a member, via reflection. This works for both @@ -74,18 +77,15 @@ public final class Field extends AccessibleObject implements Member { - private Class declaringClass; - private String name; - private int slot; + // package accessible to allow VM to access it + VMField impl; /** * This class is uninstantiable except natively. */ - private Field(Class declaringClass, String name, int slot) + Field(VMField impl) { - this.declaringClass = declaringClass; - this.name = name; - this.slot = slot; + this.impl = impl; } /** @@ -95,7 +95,7 @@ */ public Class getDeclaringClass() { - return declaringClass; + return impl.getDeclaringClass(); } /** @@ -104,7 +104,7 @@ */ public String getName() { - return name; + return impl.getName(); } /** @@ -116,13 +116,19 @@ * @return an integer representing the modifiers to this Member * @see Modifier */ - public native int getModifiers(); + public int getModifiers() + { + return impl.getModifiers(); + } /** * Gets the type of this field. * @return the type of this field */ - public native Class getType(); + public Class getType() + { + return impl.getType(); + } /** * Compare two objects to see if they are semantically equivalent. @@ -217,8 +223,13 @@ * @see #getFloat(Object) * @see #getDouble(Object) */ - public native Object get(Object o) - throws IllegalAccessException; + public Object get(Object o) + throws IllegalAccessException + { + if(impl.needsAccessCheck(isAccessible())) + impl.checkAccess(o, VMStackWalker.getCallingClass()); + return impl.get(o); + } /** * Get the value of this boolean Field. If the field is static, @@ -237,8 +248,13 @@ * class initialization, which then failed * @see #get(Object) */ - public native boolean getBoolean(Object o) - throws IllegalAccessException; + public boolean getBoolean(Object o) + throws IllegalAccessException + { + if(impl.needsAccessCheck(isAccessible())) + impl.checkAccess(o, VMStackWalker.getCallingClass()); + return impl.getBoolean(o); + } /** * Get the value of this byte Field. If the field is static, @@ -257,8 +273,13 @@ * class initialization, which then failed * @see #get(Object) */ - public native byte getByte(Object o) - throws IllegalAccessException; + public byte getByte(Object o) + throws IllegalAccessException + { + if(impl.needsAccessCheck(isAccessible())) + impl.checkAccess(o, VMStackWalker.getCallingClass()); + return impl.getByte(o); + } /** * Get the value of this Field as a char. If the field is static, @@ -275,8 +296,13 @@ * class initialization, which then failed * @see #get(Object) */ - public native char getChar(Object o) - throws IllegalAccessException; + public char getChar(Object o) + throws IllegalAccessException + { + if(impl.needsAccessCheck(isAccessible())) + impl.checkAccess(o, VMStackWalker.getCallingClass()); + return impl.getChar(o); + } /** * Get the value of this Field as a short. If the field is static, @@ -295,8 +321,13 @@ * class initialization, which then failed * @see #get(Object) */ - public native short getShort(Object o) - throws IllegalAccessException; + public short getShort(Object o) + throws IllegalAccessException + { + if(impl.needsAccessCheck(isAccessible())) + impl.checkAccess(o, VMStackWalker.getCallingClass()); + return impl.getShort(o); + } /** * Get the value of this Field as an int. If the field is static, @@ -315,8 +346,13 @@ * class initialization, which then failed * @see #get(Object) */ - public native int getInt(Object o) - throws IllegalAccessException; + public int getInt(Object o) + throws IllegalAccessException + { + if(impl.needsAccessCheck(isAccessible())) + impl.checkAccess(o, VMStackWalker.getCallingClass()); + return impl.getInt(o); + } /** * Get the value of this Field as a long. If the field is static, @@ -335,8 +371,13 @@ * class initialization, which then failed * @see #get(Object) */ - public native long getLong(Object o) - throws IllegalAccessException; + public long getLong(Object o) + throws IllegalAccessException + { + if(impl.needsAccessCheck(isAccessible())) + impl.checkAccess(o, VMStackWalker.getCallingClass()); + return impl.getLong(o); + } /** * Get the value of this Field as a float. If the field is static, @@ -355,8 +396,13 @@ * class initialization, which then failed * @see #get(Object) */ - public native float getFloat(Object o) - throws IllegalAccessException; + public float getFloat(Object o) + throws IllegalAccessException + { + if(impl.needsAccessCheck(isAccessible())) + impl.checkAccess(o, VMStackWalker.getCallingClass()); + return impl.getFloat(o); + } /** * Get the value of this Field as a double. If the field is static, @@ -376,8 +422,13 @@ * class initialization, which then failed * @see #get(Object) */ - public native double getDouble(Object o) - throws IllegalAccessException; + public double getDouble(Object o) + throws IllegalAccessException + { + if(impl.needsAccessCheck(isAccessible())) + impl.checkAccess(o, VMStackWalker.getCallingClass()); + return impl.getDouble(o); + } /** * Set the value of this Field. If it is a primitive field, the value @@ -424,8 +475,13 @@ * @see #setFloat(Object, float) * @see #setDouble(Object, double) */ - public native void set(Object o, Object value) - throws IllegalAccessException; + public void set(Object o, Object value) + throws IllegalAccessException + { + if(impl.needsAccessCheck(isAccessible())) + impl.checkAccess(o, VMStackWalker.getCallingClass()); + impl.set(o, value, isAccessible()); + } /** * Set this boolean Field. If the field is static, o will be @@ -444,8 +500,13 @@ * class initialization, which then failed * @see #set(Object, Object) */ - public native void setBoolean(Object o, boolean value) - throws IllegalAccessException; + public void setBoolean(Object o, boolean value) + throws IllegalAccessException + { + if(impl.needsAccessCheck(isAccessible())) + impl.checkAccess(o, VMStackWalker.getCallingClass()); + impl.setBoolean(o, value, isAccessible()); + } /** * Set this byte Field. If the field is static, o will be @@ -464,8 +525,13 @@ * class initialization, which then failed * @see #set(Object, Object) */ - public native void setByte(Object o, byte value) - throws IllegalAccessException; + public void setByte(Object o, byte value) + throws IllegalAccessException + { + if(impl.needsAccessCheck(isAccessible())) + impl.checkAccess(o, VMStackWalker.getCallingClass()); + impl.setByte(o, value, isAccessible()); + } /** * Set this char Field. If the field is static, o will be @@ -484,8 +550,13 @@ * class initialization, which then failed * @see #set(Object, Object) */ - public native void setChar(Object o, char value) - throws IllegalAccessException; + public void setChar(Object o, char value) + throws IllegalAccessException + { + if(impl.needsAccessCheck(isAccessible())) + impl.checkAccess(o, VMStackWalker.getCallingClass()); + impl.setChar(o, value, isAccessible()); + } /** * Set this short Field. If the field is static, o will be @@ -504,8 +575,13 @@ * class initialization, which then failed * @see #set(Object, Object) */ - public native void setShort(Object o, short value) - throws IllegalAccessException; + public void setShort(Object o, short value) + throws IllegalAccessException + { + if(impl.needsAccessCheck(isAccessible())) + impl.checkAccess(o, VMStackWalker.getCallingClass()); + impl.setShort(o, value, isAccessible()); + } /** * Set this int Field. If the field is static, o will be @@ -524,8 +600,13 @@ * class initialization, which then failed * @see #set(Object, Object) */ - public native void setInt(Object o, int value) - throws IllegalAccessException; + public void setInt(Object o, int value) + throws IllegalAccessException + { + if(impl.needsAccessCheck(isAccessible())) + impl.checkAccess(o, VMStackWalker.getCallingClass()); + impl.setInt(o, value, isAccessible()); + } /** * Set this long Field. If the field is static, o will be @@ -544,8 +625,13 @@ * class initialization, which then failed * @see #set(Object, Object) */ - public native void setLong(Object o, long value) - throws IllegalAccessException; + public void setLong(Object o, long value) + throws IllegalAccessException + { + if(impl.needsAccessCheck(isAccessible())) + impl.checkAccess(o, VMStackWalker.getCallingClass()); + impl.setLong(o, value, isAccessible()); + } /** * Set this float Field. If the field is static, o will be @@ -564,8 +650,13 @@ * class initialization, which then failed * @see #set(Object, Object) */ - public native void setFloat(Object o, float value) - throws IllegalAccessException; + public void setFloat(Object o, float value) + throws IllegalAccessException + { + if(impl.needsAccessCheck(isAccessible())) + impl.checkAccess(o, VMStackWalker.getCallingClass()); + impl.setFloat(o, value, isAccessible()); + } /** * Set this double Field. If the field is static, o will be @@ -584,6 +675,11 @@ * class initialization, which then failed * @see #set(Object, Object) */ - public native void setDouble(Object o, double value) - throws IllegalAccessException; + public void setDouble(Object o, double value) + throws IllegalAccessException + { + if(impl.needsAccessCheck(isAccessible())) + impl.checkAccess(o, VMStackWalker.getCallingClass()); + impl.setDouble(o, value, isAccessible()); + } }