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());
+ }
}