[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
java.lang.Class patches
From: |
Archie Cobbs |
Subject: |
java.lang.Class patches |
Date: |
Thu, 27 Feb 2003 21:26:19 -0800 (PST) |
Below is a subset of my current set of diffs for java.lang.Class.
I'm sending them just for anyone to look at and for consideration
for checking in. I think some of them could be useful for classpath.
I'd be interested to hear what other people think.
Notes about this patch...
- The 'vmData' field is VM specific, ignore that part.
A neat idea stolen from SableVM.
- The Class.initialize() method is from SableVM and I like it
a lot as it simplifies the work that the JVM has to do for class
initialization. Since initialization is a one time thing it's
less important if things are slower. The integer thread ID might
need to be generalized to long or byte[] or something.
- Is the Class.forName() patch correct?? I just uncommented
the code that was already there but commented out.
- getComponentType() became native, this is probably VM specific.
Seems like an obvious and easy native method though.
- Several of the get*Field*(), get*Method*(), and get*Constructor()
methods became non-native. This may make them slower (?) but for me
it's worth it because it saves a lot of work in the VM.
Cheers,
-Archie
__________________________________________________________________________
Archie Cobbs * Precision I/O * http://www.precisionio.com
--- classpath/classpath-0.05/vm/reference/java/lang/Class.java Sat Oct 26
11:41:59 2002
+++ /home/archie/jc/classpath/java/lang/Class.java Thu Feb 27 17:24:32 2003
@@ -42,11 +42,14 @@
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.net.URL;
import java.security.AllPermission;
import java.security.Permissions;
import java.security.ProtectionDomain;
+import java.util.ArrayList;
+import java.util.Arrays;
import gnu.java.lang.ClassHelper;
/*
@@ -103,11 +106,102 @@
}
/**
+ * Pointer to VM internal class structure.
+ */
+ private final byte[] vmData;
+
+ /**
* Class is non-instantiable from Java code; only the VM can create
* instances of this class.
*/
- private Class()
+ private Class(byte[] vmData)
{
+ this.vmData = vmData;
+ }
+
+ /*
+ * Class initialization mostly-in-Java copied from SableVM.
+ * The steps below follow the JVM spec, 2nd edition, sec. 2.17.5.
+ */
+ private int initializing_thread;
+ private boolean erroneous_state;
+
+ private native boolean isInitialized();
+ private native void setInitialized();
+ private native void step7();
+ private native void step8();
+
+ private void initialize(int thread) throws InterruptedException
+ {
+ Error error;
+
+ /* 1 */
+ synchronized (this)
+ {
+ /* 2 */
+ while (initializing_thread != 0 && initializing_thread != thread)
+ wait();
+
+ /* 3 */
+ if (initializing_thread == thread)
+ return;
+
+ /* 4 */
+ if (isInitialized())
+ return;
+
+ /* 5 */
+ if (erroneous_state)
+ throw new NoClassDefFoundError();
+
+ /* 6 */
+ initializing_thread = thread;
+ }
+
+ /* 7 */
+ try {
+ step7();
+ }
+ catch(Error e) {
+ synchronized(this) {
+ erroneous_state = true;
+ initializing_thread = 0;
+ notifyAll();
+ throw e;
+ }
+ }
+
+ /* 8 */
+ try {
+ step8();
+
+ /* 9 */
+ synchronized(this) {
+ setInitialized();
+ initializing_thread = 0;
+ notifyAll();
+ return;
+ }
+ }
+
+ /* 10 */
+ catch(Exception e) {
+ try {
+ error = new ExceptionInInitializerError(e);
+ } catch (OutOfMemoryError e2) {
+ error = e2;
+ }
+ } catch(Error e) {
+ error = e;
+ }
+
+ /* 11 */
+ synchronized(this) {
+ erroneous_state = true;
+ initializing_thread = 0;
+ notifyAll();
+ throw error;
+ }
}
/**
@@ -137,15 +231,11 @@
* @throws ExceptionInInitializerError if the class loads, but an exception
* occurs during initialization
*/
- //XXX This does not need to be native.
- public static native Class forName(String name)
- throws ClassNotFoundException;
- /*
+ public static Class forName(String name) throws ClassNotFoundException
{
return forName(name, true,
VMSecurityManager.getClassContext()[1].getClassLoader());
}
- */
/**
* Use the specified classloader to load and link a class. If the loader
@@ -313,7 +403,7 @@
* void V
* array type [<em>element type</em>
* class or interface, alone: <dotted name>
- * class or interface, as element type: L<dotten name>;
+ * class or interface, as element type: L<dotted name>;
*
* @return the name of this class
*/
@@ -400,46 +490,7 @@
* @see Array
* @since 1.1
*/
- public Class getComponentType()
- {
- if (isArray())
- try
- {
- String name = getName();
- switch (name.charAt(1))
- {
- case 'B':
- return byte.class;
- case 'C':
- return char.class;
- case 'D':
- return double.class;
- case 'F':
- return float.class;
- case 'I':
- return int.class;
- case 'J':
- return long.class;
- case 'S':
- return short.class;
- case 'Z':
- return boolean.class;
- default:
- return null;
- case '[':
- name = name.substring(1);
- break;
- case 'L':
- name = name.substring(2, name.length() - 1);
- }
- return Class.forName(name, false, getClassLoader());
- }
- catch(ClassNotFoundException e)
- {
- // Shouldn't happen, but ignore it anyway.
- }
- return null;
- }
+ public native Class getComponentType();
/**
* Get the modifiers of this class. These can be decoded using Modifier,
@@ -478,6 +529,20 @@
}
/**
+ * Perform security checks common to all of the methods that
+ * get members of this Class.
+ */
+ private void memberAccessCheck(int which) {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkMemberAccess(this, which);
+ Package pkg = getPackage();
+ if (pkg != null)
+ sm.checkPackageAccess(pkg.getName());
+ }
+ }
+
+ /**
* If this is a nested or inner class, return the class that declared it.
* If not, return null.
*
@@ -498,7 +563,22 @@
* @throws SecurityException if the security check fails
* @since 1.1
*/
- public native Class[] getClasses();
+ public Class[] getClasses() {
+ memberAccessCheck(Member.PUBLIC);
+ return internalGetClasses();
+ }
+
+ /**
+ * Like <code>getClasses()</code> but without the security checks.
+ */
+ private Class[] internalGetClasses() {
+ ArrayList list = new ArrayList();
+ list.add(Arrays.asList(nativeGetDeclaredClasses(true)));
+ Class superClass = getSuperclass();
+ if (superClass != null)
+ list.add(Arrays.asList(superClass.internalGetClasses()));
+ return (Class[])list.toArray(new Class[list.size()]);
+ }
/**
* Get all the public fields declared in this class or inherited from
@@ -512,7 +592,28 @@
* @throws SecurityException if the security check fails
* @since 1.1
*/
- public native Field[] getFields();
+ public Field[] getFields() {
+ memberAccessCheck(Member.PUBLIC);
+ return internalGetFields();
+ }
+
+ /**
+ * Like <code>getFields()</code> but without the security checks.
+ */
+ private Field[] internalGetFields() {
+ ArrayList list = new ArrayList();
+ list.add(Arrays.asList(nativeGetDeclaredFields(true)));
+ if (isInterface()) {
+ Class[] interfaces = getInterfaces();
+ for (int i = 0; i < interfaces.length; i++)
+ list.add(Arrays.asList(interfaces[i].internalGetFields()));
+ } else {
+ Class superClass = getSuperclass();
+ if (superClass != null)
+ list.add(Arrays.asList(superClass.internalGetFields()));
+ }
+ return (Field[])list.toArray(new Field[list.size()]);
+ }
/**
* Get all the public methods declared in this class or inherited from
@@ -530,7 +631,25 @@
* @throws SecurityException if the security check fails
* @since 1.1
*/
- public native Method[] getMethods();
+ public Method[] getMethods() {
+ memberAccessCheck(Member.PUBLIC);
+ return internalGetMethods();
+ }
+
+ /**
+ * Like <code>getMethods()</code> but without the security checks.
+ */
+ private Method[] internalGetMethods() {
+ ArrayList list = new ArrayList();
+ list.add(Arrays.asList(nativeGetDeclaredMethods(true)));
+ Class[] interfaces = getInterfaces();
+ for (int i = 0; i < interfaces.length; i++)
+ list.add(Arrays.asList(interfaces[i].internalGetMethods()));
+ Class superClass = getSuperclass();
+ if (superClass != null)
+ list.add(Arrays.asList(superClass.internalGetMethods()));
+ return (Method[])list.toArray(new Method[list.size()]);
+ }
/**
* Get all the public constructors of this class. This returns an array of
@@ -544,7 +663,10 @@
* @throws SecurityException if the security check fails
* @since 1.1
*/
- public native Constructor[] getConstructors();
+ public Constructor[] getConstructors() {
+ memberAccessCheck(Member.PUBLIC);
+ return nativeGetDeclaredConstructors(true);
+ }
/**
* Get a public field declared or inherited in this class, where name is
@@ -561,7 +683,26 @@
* @see #getFields()
* @since 1.1
*/
- public native Field getField(String name) throws NoSuchFieldException;
+ public Field getField(String name) throws NoSuchFieldException {
+ memberAccessCheck(Member.PUBLIC);
+ Field[] fields = nativeGetDeclaredFields(true);
+ for (int i = 0; i < fields.length; i++) {
+ Field field = fields[i];
+ if (field.getName().equals(name))
+ return field;
+ }
+ Class[] interfaces = getInterfaces();
+ for (int i = 0; i < interfaces.length; i++) {
+ try {
+ return interfaces[i].getField(name);
+ } catch (NoSuchFieldException e) {
+ }
+ }
+ Class superclass = getSuperclass();
+ if (superclass != null)
+ return superclass.getField(name);
+ throw new NoSuchFieldException();
+ }
/**
* Get a public method declared or inherited in this class, where name is
@@ -585,8 +726,62 @@
* @see #getMethods()
* @since 1.1
*/
- public native Method getMethod(String name, Class[] args)
- throws NoSuchMethodException;
+ public Method getMethod(String name, Class[] args)
+ throws NoSuchMethodException {
+ memberAccessCheck(Member.PUBLIC);
+ for (Class c = this; c != null; c = c.getSuperclass()) {
+ Method match = matchMethod(c.nativeGetDeclaredMethods(true), name, args);
+ if (match != null)
+ return match;
+ }
+ throw new NoSuchMethodException();
+ }
+
+ /**
+ * Find the best matching method in <code>list</code> according to
+ * the definition of ``best matching'' used by <code>getMethod()</code>
+ *
+ * <p>
+ * Returns the method if any, otherwise <code>null</code>.
+ *
+ * @param list List of methods to search
+ * @param name Name of method
+ * @param args Method parameter types
+ * @see #getMethod()
+ */
+ private static Method matchMethod(Method[] list, String name, Class[] args) {
+ Method match = null;
+ for (int i = 0; i < list.length; i++) {
+ Method method = list[i];
+ if (!method.getName().equals(name))
+ continue;
+ if (!matchParameters(args, method.getParameterTypes()))
+ continue;
+ if (match == null
+ || match.getReturnType().isAssignableFrom(method.getReturnType()))
+ match = method;
+ }
+ return match;
+ }
+
+ /**
+ * Check for an exact match between parameter type lists.
+ * Either list may be <code>null</code> to mean a list of
+ * length zero.
+ */
+ private static boolean matchParameters(Class[] types1, Class[] types2) {
+ if (types1 == null)
+ return types2 == null || types2.length == 0;
+ if (types2 == null)
+ return types1 == null || types1.length == 0;
+ if (types1.length != types2.length)
+ return false;
+ for (int i = 0; i < types1.length; i++) {
+ if (!types1[i].equals(types2[i]))
+ return false;
+ }
+ return true;
+ }
/**
* Get a public constructor declared in this class. If the constructor takes
@@ -602,8 +797,16 @@
* @see #getConstructors()
* @since 1.1
*/
- public native Constructor getConstructor(Class[] args)
- throws NoSuchMethodException;
+ public Constructor getConstructor(Class[] args) throws NoSuchMethodException
{
+ memberAccessCheck(Member.PUBLIC);
+ Constructor[] constructors = nativeGetDeclaredConstructors(true);
+ for (int i = 0; i < constructors.length; i++) {
+ Constructor constructor = constructors[i];
+ if (matchParameters(args, constructor.getParameterTypes()))
+ return constructor;
+ }
+ throw new NoSuchMethodException();
+ }
/**
* Get all the declared member classes and interfaces in this class, but
@@ -617,7 +820,17 @@
* @throws SecurityException if the security check fails
* @since 1.1
*/
- public native Class[] getDeclaredClasses();
+ public Class[] getDeclaredClasses() {
+ memberAccessCheck(Member.DECLARED);
+ return nativeGetDeclaredClasses(false);
+ }
+
+ /**
+ * Like <code>getDeclaredClasses()</code> but without the security checks.
+ *
+ * @param pulicOnly Only public classes should be returned
+ */
+ private native Class[] nativeGetDeclaredClasses(boolean pulicOnly);
/**
* Get all the declared fields in this class, but not those inherited from
@@ -631,7 +844,17 @@
* @throws SecurityException if the security check fails
* @since 1.1
*/
- public native Field[] getDeclaredFields();
+ public Field[] getDeclaredFields() {
+ memberAccessCheck(Member.DECLARED);
+ return nativeGetDeclaredFields(false);
+ }
+
+ /**
+ * Like <code>getDeclaredFields()</code> but without the security checks.
+ *
+ * @param pulicOnly Only public fields should be returned
+ */
+ private native Field[] nativeGetDeclaredFields(boolean pulicOnly);
/**
* Get all the declared methods in this class, but not those inherited from
@@ -649,7 +872,17 @@
* @throws SecurityException if the security check fails
* @since 1.1
*/
- public native Method[] getDeclaredMethods();
+ public Method[] getDeclaredMethods() {
+ memberAccessCheck(Member.DECLARED);
+ return nativeGetDeclaredMethods(false);
+ }
+
+ /**
+ * Like <code>getDeclaredMethods()</code> but without the security checks.
+ *
+ * @param pulicOnly Only public methods should be returned
+ */
+ private native Method[] nativeGetDeclaredMethods(boolean pulicOnly);
/**
* Get all the declared constructors of this class. This returns an array of
@@ -663,7 +896,19 @@
* @throws SecurityException if the security check fails
* @since 1.1
*/
- public native Constructor[] getDeclaredConstructors();
+ public Constructor[] getDeclaredConstructors() {
+ memberAccessCheck(Member.DECLARED);
+ return nativeGetDeclaredConstructors(false);
+ }
+
+ /**
+ * Like <code>getDeclaredConstructors()</code> but without
+ * the security checks.
+ *
+ * @param pulicOnly Only public constructors should be returned
+ */
+ private native Constructor[]
+ nativeGetDeclaredConstructors(boolean publicOnly);
/**
* Get a field declared in this class, where name is its simple name. The
@@ -678,8 +923,15 @@
* @see #getDeclaredFields()
* @since 1.1
*/
- public native Field getDeclaredField(String name)
- throws NoSuchFieldException;
+ public Field getDeclaredField(String name) throws NoSuchFieldException {
+ memberAccessCheck(Member.DECLARED);
+ Field[] fields = nativeGetDeclaredFields(false);
+ for (int i = 0; i < fields.length; i++) {
+ if (fields[i].getName().equals(name))
+ return fields[i];
+ }
+ throw new NoSuchFieldException();
+ }
/**
* Get a method declared in this class, where name is its simple name. The
@@ -702,8 +954,14 @@
* @see #getDeclaredMethods()
* @since 1.1
*/
- public native Method getDeclaredMethod(String name, Class[] args)
- throws NoSuchMethodException;
+ public Method getDeclaredMethod(String name, Class[] args)
+ throws NoSuchMethodException {
+ memberAccessCheck(Member.DECLARED);
+ Method match = matchMethod(nativeGetDeclaredMethods(false), name, args);
+ if (match != null)
+ return match;
+ throw new NoSuchMethodException();
+ }
/**
* Get a constructor declared in this class. If the constructor takes no
@@ -719,8 +977,17 @@
* @see #getDeclaredConstructors()
* @since 1.1
*/
- public native Constructor getDeclaredConstructor(Class[] args)
- throws NoSuchMethodException;
+ public Constructor getDeclaredConstructor(Class[] args)
+ throws NoSuchMethodException {
+ memberAccessCheck(Member.DECLARED);
+ Constructor[] constructors = nativeGetDeclaredConstructors(false);
+ for (int i = 0; i < constructors.length; i++) {
+ Constructor constructor = constructors[i];
+ if (matchParameters(args, constructor.getParameterTypes()))
+ return constructor;
+ }
+ throw new NoSuchMethodException();
+ }
/**
* Get a resource using this class's package using the
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- java.lang.Class patches,
Archie Cobbs <=