break each Class, Field, and Method into separate classes

In order to facilitate making the VM compatible with multiple class
libraries, it's useful to separate the VM-specific representation of
these classes from the library implementations.  This commit
introduces VMClass, VMField, and VMMethod for that purpose.
This commit is contained in:
Joel Dice
2010-09-01 10:13:52 -06:00
parent 4273ff834c
commit 17c1a552d5
21 changed files with 547 additions and 348 deletions

View File

@ -10,7 +10,10 @@
package java.lang;
import avian.VMClass;
import avian.ClassAddendum;
import avian.AnnotationInvocationHandler;
import avian.SystemClassLoader;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
@ -38,24 +41,13 @@ public final class Class <T>
{
private static final int PrimitiveFlag = 1 << 5;
private short flags;
public short vmFlags;
private short fixedSize;
private byte arrayElementSize;
private byte arrayDimensions;
private int[] objectMask;
private byte[] name;
private byte[] sourceFile;
public Class super_;
public Object[] interfaceTable;
public Method[] virtualTable;
public Field[] fieldTable;
public Method[] methodTable;
public avian.ClassAddendum addendum;
private Object staticTable;
private ClassLoader loader;
public final VMClass vmClass;
private Class() { }
public Class(VMClass vmClass) {
this.vmClass = vmClass;
}
public static native VMClass vmClass(Object o);
public String toString() {
return getName();
@ -73,26 +65,30 @@ public final class Class <T>
}
public String getName() {
if (name == null) {
if ((vmFlags & PrimitiveFlag) != 0) {
if (this == primitiveClass('V')) {
name = "void\0".getBytes();
} else if (this == primitiveClass('Z')) {
name = "boolean\0".getBytes();
} else if (this == primitiveClass('B')) {
name = "byte\0".getBytes();
} else if (this == primitiveClass('C')) {
name = "char\0".getBytes();
} else if (this == primitiveClass('S')) {
name = "short\0".getBytes();
} else if (this == primitiveClass('I')) {
name = "int\0".getBytes();
} else if (this == primitiveClass('F')) {
name = "float\0".getBytes();
} else if (this == primitiveClass('J')) {
name = "long\0".getBytes();
} else if (this == primitiveClass('D')) {
name = "double\0".getBytes();
return getName(vmClass);
}
public static String getName(VMClass c) {
if (c.name == null) {
if ((c.vmFlags & PrimitiveFlag) != 0) {
if (c == primitiveClass('V')) {
c.name = "void\0".getBytes();
} else if (c == primitiveClass('Z')) {
c.name = "boolean\0".getBytes();
} else if (c == primitiveClass('B')) {
c.name = "byte\0".getBytes();
} else if (c == primitiveClass('C')) {
c.name = "char\0".getBytes();
} else if (c == primitiveClass('S')) {
c.name = "short\0".getBytes();
} else if (c == primitiveClass('I')) {
c.name = "int\0".getBytes();
} else if (c == primitiveClass('F')) {
c.name = "float\0".getBytes();
} else if (c == primitiveClass('J')) {
c.name = "long\0".getBytes();
} else if (c == primitiveClass('D')) {
c.name = "double\0".getBytes();
} else {
throw new AssertionError();
}
@ -102,11 +98,12 @@ public final class Class <T>
}
return new String
(replace('/', '.', name, 0, name.length - 1), 0, name.length - 1, false);
(replace('/', '.', c.name, 0, c.name.length - 1), 0, c.name.length - 1,
false);
}
public String getCanonicalName() {
if ((vmFlags & PrimitiveFlag) != 0) {
if ((vmClass.vmFlags & PrimitiveFlag) != 0) {
return getName();
} else if (isArray()) {
return getComponentType().getCanonicalName() + "[]";
@ -116,7 +113,7 @@ public final class Class <T>
}
public String getSimpleName() {
if ((vmFlags & PrimitiveFlag) != 0) {
if ((vmClass.vmFlags & PrimitiveFlag) != 0) {
return getName();
} else if (isArray()) {
return getComponentType().getSimpleName() + "[]";
@ -131,10 +128,6 @@ public final class Class <T>
}
}
public Object staticTable() {
return staticTable;
}
public T newInstance()
throws IllegalAccessException, InstantiationException
{
@ -148,8 +141,7 @@ public final class Class <T>
}
public static Class forName(String name) throws ClassNotFoundException {
return forName
(name, true, Method.getCaller().getDeclaringClass().getClassLoader());
return forName(name, true, Method.getCaller().class_.loader);
}
public static Class forName(String name, boolean initialize,
@ -157,19 +149,19 @@ public final class Class <T>
throws ClassNotFoundException
{
if (loader == null) {
loader = Class.class.loader;
loader = Class.class.vmClass.loader;
}
Class c = loader.loadClass(name);
avian.SystemClassLoader.link(c, loader);
SystemClassLoader.link(c.vmClass, loader);
if (initialize) {
c.initialize();
initialize(c.vmClass);
}
return c;
}
private static native Class primitiveClass(char name);
private static native VMClass primitiveClass(char name);
private native void initialize();
private static native void initialize(VMClass vmClass);
public static Class forCanonicalName(String name) {
return forCanonicalName(null, name);
@ -183,7 +175,7 @@ public final class Class <T>
return forName(name.substring(1, name.length() - 1), true, loader);
} else {
if (name.length() == 1) {
return primitiveClass(name.charAt(0));
return SystemClassLoader.getClass(primitiveClass(name.charAt(0)));
} else {
throw new ClassNotFoundException(name);
}
@ -197,39 +189,43 @@ public final class Class <T>
if (isArray()) {
String n = getName();
if ("[Z".equals(n)) {
return primitiveClass('Z');
return SystemClassLoader.getClass(primitiveClass('Z'));
} else if ("[B".equals(n)) {
return primitiveClass('B');
return SystemClassLoader.getClass(primitiveClass('B'));
} else if ("[S".equals(n)) {
return primitiveClass('S');
return SystemClassLoader.getClass(primitiveClass('S'));
} else if ("[C".equals(n)) {
return primitiveClass('C');
return SystemClassLoader.getClass(primitiveClass('C'));
} else if ("[I".equals(n)) {
return primitiveClass('I');
return SystemClassLoader.getClass(primitiveClass('I'));
} else if ("[F".equals(n)) {
return primitiveClass('F');
return SystemClassLoader.getClass(primitiveClass('F'));
} else if ("[J".equals(n)) {
return primitiveClass('J');
return SystemClassLoader.getClass(primitiveClass('J'));
} else if ("[D".equals(n)) {
return primitiveClass('D');
return SystemClassLoader.getClass(primitiveClass('D'));
}
if (staticTable == null) throw new AssertionError(name);
return (Class) staticTable;
if (vmClass.staticTable == null) throw new AssertionError();
return SystemClassLoader.getClass((VMClass) vmClass.staticTable);
} else {
return null;
}
}
public native boolean isAssignableFrom(Class c);
public static native boolean isAssignableFrom(VMClass a, VMClass b);
private Field findField(String name) {
if (fieldTable != null) {
avian.SystemClassLoader.link(this);
public boolean isAssignableFrom(Class c) {
return isAssignableFrom(vmClass, c.vmClass);
}
for (int i = 0; i < fieldTable.length; ++i) {
if (fieldTable[i].getName().equals(name)) {
return fieldTable[i];
private static Field findField(VMClass vmClass, String name) {
if (vmClass.fieldTable != null) {
SystemClassLoader.link(vmClass);
for (int i = 0; i < vmClass.fieldTable.length; ++i) {
if (Field.getName(vmClass.fieldTable[i]).equals(name)) {
return new Field(vmClass.fieldTable[i]);
}
}
}
@ -237,7 +233,7 @@ public final class Class <T>
}
public Field getDeclaredField(String name) throws NoSuchFieldException {
Field f = findField(name);
Field f = findField(vmClass, name);
if (f == null) {
throw new NoSuchFieldException(name);
} else {
@ -246,8 +242,8 @@ public final class Class <T>
}
public Field getField(String name) throws NoSuchFieldException {
for (Class c = this; c != null; c = c.super_) {
Field f = c.findField(name);
for (VMClass c = vmClass; c != null; c = c.super_) {
Field f = findField(c, name);
if (f != null) {
return f;
}
@ -268,19 +264,22 @@ public final class Class <T>
}
}
private Method findMethod(String name, Class[] parameterTypes) {
if (methodTable != null) {
avian.SystemClassLoader.link(this);
private static Method findMethod(VMClass vmClass, String name,
Class[] parameterTypes)
{
if (vmClass.methodTable != null) {
SystemClassLoader.link(vmClass);
if (parameterTypes == null) {
parameterTypes = new Class[0];
}
for (int i = 0; i < methodTable.length; ++i) {
if (methodTable[i].getName().equals(name)
&& match(parameterTypes, methodTable[i].getParameterTypes()))
for (int i = 0; i < vmClass.methodTable.length; ++i) {
if (Method.getName(vmClass.methodTable[i]).equals(name)
&& match(parameterTypes,
Method.getParameterTypes(vmClass.methodTable[i])))
{
return methodTable[i];
return new Method(vmClass.methodTable[i]);
}
}
}
@ -293,7 +292,7 @@ public final class Class <T>
if (name.startsWith("<")) {
throw new NoSuchMethodException(name);
}
Method m = findMethod(name, parameterTypes);
Method m = findMethod(vmClass, name, parameterTypes);
if (m == null) {
throw new NoSuchMethodException(name);
} else {
@ -307,8 +306,8 @@ public final class Class <T>
if (name.startsWith("<")) {
throw new NoSuchMethodException(name);
}
for (Class c = this; c != null; c = c.super_) {
Method m = c.findMethod(name, parameterTypes);
for (VMClass c = vmClass; c != null; c = c.super_) {
Method m = findMethod(c, name, parameterTypes);
if (m != null) {
return m;
}
@ -319,7 +318,7 @@ public final class Class <T>
public Constructor getConstructor(Class ... parameterTypes)
throws NoSuchMethodException
{
Method m = findMethod("<init>", parameterTypes);
Method m = findMethod(vmClass, "<init>", parameterTypes);
if (m == null) {
throw new NoSuchMethodException();
} else {
@ -348,11 +347,12 @@ public final class Class <T>
private int countConstructors(boolean publicOnly) {
int count = 0;
if (methodTable != null) {
for (int i = 0; i < methodTable.length; ++i) {
if (vmClass.methodTable != null) {
for (int i = 0; i < vmClass.methodTable.length; ++i) {
if (((! publicOnly)
|| ((methodTable[i].getModifiers() & Modifier.PUBLIC)) != 0)
&& methodTable[i].getName().equals("<init>"))
|| ((vmClass.methodTable[i].flags & Modifier.PUBLIC))
!= 0)
&& Method.getName(vmClass.methodTable[i]).equals("<init>"))
{
++ count;
}
@ -363,13 +363,13 @@ public final class Class <T>
public Constructor[] getDeclaredConstructors() {
Constructor[] array = new Constructor[countConstructors(false)];
if (methodTable != null) {
avian.SystemClassLoader.link(this);
if (vmClass.methodTable != null) {
SystemClassLoader.link(vmClass);
int index = 0;
for (int i = 0; i < methodTable.length; ++i) {
if (methodTable[i].getName().equals("<init>")) {
array[index++] = new Constructor(methodTable[i]);
for (int i = 0; i < vmClass.methodTable.length; ++i) {
if (Method.getName(vmClass.methodTable[i]).equals("<init>")) {
array[index++] = new Constructor(new Method(vmClass.methodTable[i]));
}
}
}
@ -379,15 +379,15 @@ public final class Class <T>
public Constructor[] getConstructors() {
Constructor[] array = new Constructor[countConstructors(true)];
if (methodTable != null) {
avian.SystemClassLoader.link(this);
if (vmClass.methodTable != null) {
SystemClassLoader.link(vmClass);
int index = 0;
for (int i = 0; i < methodTable.length; ++i) {
if (((methodTable[i].getModifiers() & Modifier.PUBLIC) != 0)
&& methodTable[i].getName().equals("<init>"))
for (int i = 0; i < vmClass.methodTable.length; ++i) {
if (((vmClass.methodTable[i].flags & Modifier.PUBLIC) != 0)
&& Method.getName(vmClass.methodTable[i]).equals("<init>"))
{
array[index++] = new Constructor(methodTable[i]);
array[index++] = new Constructor(new Method(vmClass.methodTable[i]));
}
}
}
@ -396,9 +396,11 @@ public final class Class <T>
}
public Field[] getDeclaredFields() {
if (fieldTable != null) {
Field[] array = new Field[fieldTable.length];
System.arraycopy(fieldTable, 0, array, 0, fieldTable.length);
if (vmClass.fieldTable != null) {
Field[] array = new Field[vmClass.fieldTable.length];
for (int i = 0; i < vmClass.fieldTable.length; ++i) {
array[i] = new Field(vmClass.fieldTable[i]);
}
return array;
} else {
return new Field[0];
@ -407,9 +409,9 @@ public final class Class <T>
private int countPublicFields() {
int count = 0;
if (fieldTable != null) {
for (int i = 0; i < fieldTable.length; ++i) {
if (((fieldTable[i].getModifiers() & Modifier.PUBLIC)) != 0) {
if (vmClass.fieldTable != null) {
for (int i = 0; i < vmClass.fieldTable.length; ++i) {
if (((vmClass.fieldTable[i].flags & Modifier.PUBLIC)) != 0) {
++ count;
}
}
@ -419,13 +421,13 @@ public final class Class <T>
public Field[] getFields() {
Field[] array = new Field[countPublicFields()];
if (fieldTable != null) {
avian.SystemClassLoader.link(this);
if (vmClass.fieldTable != null) {
SystemClassLoader.link(vmClass);
int ai = 0;
for (int i = 0; i < fieldTable.length; ++i) {
if (((fieldTable[i].getModifiers() & Modifier.PUBLIC)) != 0) {
array[ai++] = fieldTable[i];
for (int i = 0; i < vmClass.fieldTable.length; ++i) {
if (((vmClass.fieldTable[i].flags & Modifier.PUBLIC)) != 0) {
array[ai++] = new Field(vmClass.fieldTable[i]);
}
}
}
@ -434,11 +436,12 @@ public final class Class <T>
private int countMethods(boolean publicOnly) {
int count = 0;
if (methodTable != null) {
for (int i = 0; i < methodTable.length; ++i) {
if (vmClass.methodTable != null) {
for (int i = 0; i < vmClass.methodTable.length; ++i) {
if (((! publicOnly)
|| ((methodTable[i].getModifiers() & Modifier.PUBLIC)) != 0)
&& (! methodTable[i].getName().startsWith("<")))
|| ((vmClass.methodTable[i].flags & Modifier.PUBLIC))
!= 0)
&& (! Method.getName(vmClass.methodTable[i]).startsWith("<")))
{
++ count;
}
@ -449,13 +452,13 @@ public final class Class <T>
public Method[] getDeclaredMethods() {
Method[] array = new Method[countMethods(false)];
if (methodTable != null) {
avian.SystemClassLoader.link(this);
if (vmClass.methodTable != null) {
SystemClassLoader.link(vmClass);
int ai = 0;
for (int i = 0; i < methodTable.length; ++i) {
if (! methodTable[i].getName().startsWith("<")) {
array[ai++] = methodTable[i];
for (int i = 0; i < vmClass.methodTable.length; ++i) {
if (! Method.getName(vmClass.methodTable[i]).startsWith("<")) {
array[ai++] = new Method(vmClass.methodTable[i]);
}
}
}
@ -465,15 +468,15 @@ public final class Class <T>
public Method[] getMethods() {
Method[] array = new Method[countMethods(true)];
if (methodTable != null) {
avian.SystemClassLoader.link(this);
if (vmClass.methodTable != null) {
SystemClassLoader.link(vmClass);
int index = 0;
for (int i = 0; i < methodTable.length; ++i) {
if (((methodTable[i].getModifiers() & Modifier.PUBLIC) != 0)
&& (! methodTable[i].getName().startsWith("<")))
for (int i = 0; i < vmClass.methodTable.length; ++i) {
if (((vmClass.methodTable[i].flags & Modifier.PUBLIC) != 0)
&& (! Method.getName(vmClass.methodTable[i]).startsWith("<")))
{
array[index++] = methodTable[i];
array[index++] = new Method(vmClass.methodTable[i]);
}
}
}
@ -482,13 +485,14 @@ public final class Class <T>
}
public Class[] getInterfaces() {
if (interfaceTable != null) {
avian.SystemClassLoader.link(this);
if (vmClass.interfaceTable != null) {
SystemClassLoader.link(vmClass);
int stride = (isInterface() ? 1 : 2);
Class[] array = new Class[interfaceTable.length / stride];
Class[] array = new Class[vmClass.interfaceTable.length / stride];
for (int i = 0; i < array.length; ++i) {
array[i] = (Class) interfaceTable[i * stride];
array[i] = SystemClassLoader.getClass
((VMClass) vmClass.interfaceTable[i * stride]);
}
return array;
} else {
@ -509,36 +513,41 @@ public final class Class <T>
}
public ClassLoader getClassLoader() {
return loader;
return vmClass.loader;
}
public int getModifiers() {
return flags;
return vmClass.flags;
}
public boolean isInterface() {
return (flags & Modifier.INTERFACE) != 0;
return (vmClass.flags & Modifier.INTERFACE) != 0;
}
public Class getSuperclass() {
return super_;
return SystemClassLoader.getClass(vmClass.super_);
}
public boolean isArray() {
return arrayDimensions != 0;
return vmClass.arrayDimensions != 0;
}
public static boolean isInstance(VMClass c, Object o) {
return o != null && isAssignableFrom(c, SystemClassLoader.getVMClass(o));
}
public boolean isInstance(Object o) {
return o != null && isAssignableFrom(o.getClass());
return isInstance(vmClass, o);
}
public boolean isPrimitive() {
return (vmFlags & PrimitiveFlag) != 0;
return (vmClass.vmFlags & PrimitiveFlag) != 0;
}
public URL getResource(String path) {
if (! path.startsWith("/")) {
String name = new String(this.name, 0, this.name.length - 1, false);
String name = new String
(vmClass.name, 0, vmClass.name.length - 1, false);
int index = name.lastIndexOf('/');
if (index >= 0) {
path = name.substring(0, index) + "/" + path;
@ -573,11 +582,11 @@ public final class Class <T>
}
public Object[] getSigners() {
return addendum == null ? null : addendum.signers;
return vmClass.addendum.signers;
}
public Package getPackage() {
if ((vmFlags & PrimitiveFlag) != 0 || isArray()) {
if ((vmClass.vmFlags & PrimitiveFlag) != 0 || isArray()) {
return null;
} else {
String name = getCanonicalName();
@ -597,25 +606,25 @@ public final class Class <T>
return getAnnotation(class_) != null;
}
private Annotation getAnnotation(Object[] a) {
private static Annotation getAnnotation(VMClass c, Object[] a) {
if (a[0] == null) {
a[0] = Proxy.newProxyInstance
(loader, new Class[] { (Class) a[1] },
(c.loader, new Class[] { (Class) a[1] },
new AnnotationInvocationHandler(a));
}
return (Annotation) a[0];
}
public <T extends Annotation> T getAnnotation(Class<T> class_) {
for (Class c = this; c != null; c = c.super_) {
for (VMClass c = vmClass; c != null; c = c.super_) {
if (c.addendum != null && c.addendum.annotationTable != null) {
avian.SystemClassLoader.link(c, c.loader);
SystemClassLoader.link(c, c.loader);
Object[] table = (Object[]) c.addendum.annotationTable;
for (int i = 0; i < table.length; ++i) {
Object[] a = (Object[]) table[i];
if (a[1] == class_) {
return (T) c.getAnnotation(a);
return (T) getAnnotation(c, a);
}
}
}
@ -624,13 +633,13 @@ public final class Class <T>
}
public Annotation[] getDeclaredAnnotations() {
if (addendum != null && addendum.annotationTable != null) {
avian.SystemClassLoader.link(this);
if (vmClass.addendum.annotationTable != null) {
SystemClassLoader.link(vmClass);
Object[] table = (Object[]) addendum.annotationTable;
Object[] table = (Object[]) vmClass.addendum.annotationTable;
Annotation[] array = new Annotation[table.length];
for (int i = 0; i < table.length; ++i) {
array[i] = getAnnotation((Object[]) table[i]);
array[i] = getAnnotation(vmClass, (Object[]) table[i]);
}
return array;
} else {
@ -640,7 +649,7 @@ public final class Class <T>
private int countAnnotations() {
int count = 0;
for (Class c = this; c != null; c = c.super_) {
for (VMClass c = vmClass; c != null; c = c.super_) {
if (c.addendum != null && c.addendum.annotationTable != null) {
count += ((Object[]) c.addendum.annotationTable).length;
}
@ -651,11 +660,11 @@ public final class Class <T>
public Annotation[] getAnnotations() {
Annotation[] array = new Annotation[countMethods(true)];
int i = 0;
for (Class c = this; c != null; c = c.super_) {
for (VMClass c = vmClass; c != null; c = c.super_) {
if (c.addendum != null && c.addendum.annotationTable != null) {
Object[] table = (Object[]) c.addendum.annotationTable;
for (int j = 0; j < table.length; ++j) {
array[i++] = getAnnotation((Object[]) table[j]);
array[i++] = getAnnotation(vmClass, (Object[]) table[j]);
}
}
}
@ -692,14 +701,4 @@ public final class Class <T>
p.add(new AllPermission());
return new ProtectionDomain(null, p);
}
// for GNU Classpath compatibility:
void setSigners(Object[] signers) {
if (signers != null && signers.length > 0) {
if (addendum == null) {
addendum = new avian.ClassAddendum();
}
addendum.signers = signers;
}
}
}