From 38d4ee6e079fab6c1e8ebc8128dc459f54bd33d6 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 30 Jul 2007 17:19:05 -0600 Subject: [PATCH] flesh out ClassLoader, etc. --- classpath/java/lang/Class.java | 28 +++- classpath/java/lang/ClassLoader.java | 73 ++++++++- classpath/java/lang/Math.java | 60 ++------ classpath/java/lang/SystemClassLoader.java | 9 ++ classpath/java/lang/reflect/Method.java | 2 + src/builtin.cpp | 53 +++++-- src/machine.cpp | 170 ++++++++++++--------- src/machine.h | 8 +- src/type-generator.cpp | 2 +- src/types.def | 11 +- 10 files changed, 272 insertions(+), 144 deletions(-) create mode 100644 classpath/java/lang/SystemClassLoader.java diff --git a/classpath/java/lang/Class.java b/classpath/java/lang/Class.java index e7df888db0..1142285aae 100644 --- a/classpath/java/lang/Class.java +++ b/classpath/java/lang/Class.java @@ -6,6 +6,10 @@ import java.lang.reflect.Field; import java.lang.reflect.Modifier; public final class Class { + private static final int ReferenceFlag = 1 << 0; + private static final int WeakReferenceFlag = 1 << 1; + private static final int NeedInitFlag = 1 << 2; + private short flags; private byte vmFlags; private byte arrayDimensions; @@ -19,6 +23,7 @@ public final class Class { private Field[] fieldTable; private Method[] methodTable; private Object[] staticTable; + private ClassLoader loader; private Class() { } @@ -26,8 +31,25 @@ public final class Class { return new String(name, 0, name.length - 1, false); } - public static native Class forName(String name) - throws ClassNotFoundException; + public static Class forName(String name) throws ClassNotFoundException { + return forName + (name, true, Method.getCaller().getDeclaringClass().getClassLoader()); + } + + public static Class forName(String name, boolean initialize, + ClassLoader loader) + throws ClassNotFoundException + { + Class c = loader.loadClass(name); + if (initialize && ((c.flags & NeedInitFlag) != 0)) { + c.flags &= ~NeedInitFlag; + Method m = c.findMethod("", new Class[0]); + if (m != null) { + m.invoke(null); + } + } + return c; + } private static native Class primitiveClass(char name); @@ -282,7 +304,7 @@ public final class Class { } public ClassLoader getClassLoader() { - return ClassLoader.getSystemClassLoader(); + return loader; } public int getModifiers() { diff --git a/classpath/java/lang/ClassLoader.java b/classpath/java/lang/ClassLoader.java index 08ef5916bd..c0b88fe669 100644 --- a/classpath/java/lang/ClassLoader.java +++ b/classpath/java/lang/ClassLoader.java @@ -1,15 +1,78 @@ package java.lang; -public class ClassLoader { - private static final ClassLoader instance = new ClassLoader(); +public abstract class ClassLoader { + private final ClassLoader parent; - private ClassLoader() { } + protected ClassLoader(ClassLoader parent) { + if (parent == null) { + this.parent = getSystemClassLoader(); + } else { + this.parent = parent; + } + } + + protected ClassLoader() { + this(getSystemClassLoader()); + } public static ClassLoader getSystemClassLoader() { - return instance; + return ClassLoader.class.getClassLoader(); + } + + private static native Class defineClass(byte[] b, int offset, int length); + + protected Class defineClass(String name, byte[] b, int offset, int length) { + if (b == null) { + throw new NullPointerException(); + } + + if (offset < 0 || offset > length || offset + length > b.length) { + throw new IndexOutOfBoundsException(); + } + + return defineClass(b, offset, length); + } + + protected Class findClass(String name) throws ClassNotFoundException { + throw new ClassNotFoundException(); + } + + protected Class findLoadedClass(String name) { + return null; } public Class loadClass(String name) throws ClassNotFoundException { - return Class.forName(name); + return loadClass(name, false); + } + + protected Class loadClass(String name, boolean resolve) + throws ClassNotFoundException + { + Class c = findLoadedClass(name); + if (c == null) { + if (parent != null) { + try { + c = parent.loadClass(name); + } catch (ClassNotFoundException ok) { } + } + + if (c == null) { + c = findClass(name); + } + } + + if (resolve) { + resolveClass(c); + } + + return c; + } + + protected void resolveClass(Class c) { + // ignore + } + + private ClassLoader getParent() { + return parent; } } diff --git a/classpath/java/lang/Math.java b/classpath/java/lang/Math.java index 186b8c755e..6d622b3125 100644 --- a/classpath/java/lang/Math.java +++ b/classpath/java/lang/Math.java @@ -27,63 +27,27 @@ public final class Math { return (int) (v + 0.5); } - public static double floor(double v) { - // todo - return 0; - } + public static native double floor(double v); - public static double ceil(double v) { - // todo - return 0; - } + public static native double ceil(double v); - public static double exp(double v) { - // todo - return 0; - } + public static native double exp(double v); - public static double log(double v) { - // todo - return 0; - } + public static native double log(double v); - public static double cos(double v) { - // todo - return 0; - } + public static native double cos(double v); - public static double sin(double v) { - // todo - return 0; - } + public static native double sin(double v); - public static double tan(double v) { - // todo - return 0; - } + public static native double tan(double v); - public static double acos(double v) { - // todo - return 0; - } + public static native double acos(double v); - public static double asin(double v) { - // todo - return 0; - } + public static native double asin(double v); - public static double atan(double v) { - // todo - return 0; - } + public static native double atan(double v); - public static double sqrt(double v) { - // todo - return 0; - } + public static native double sqrt(double v); - public static double pow(double v, double e) { - // todo - return 0; - } + public static native double pow(double v, double e); } diff --git a/classpath/java/lang/SystemClassLoader.java b/classpath/java/lang/SystemClassLoader.java new file mode 100644 index 0000000000..8603adc71f --- /dev/null +++ b/classpath/java/lang/SystemClassLoader.java @@ -0,0 +1,9 @@ +package java.lang; + +public class SystemClassLoader extends ClassLoader { + private Object map; + + protected native Class findClass(String name) throws ClassNotFoundException; + + protected native Class findLoadedClass(String name); +} diff --git a/classpath/java/lang/reflect/Method.java b/classpath/java/lang/reflect/Method.java index 84777a0da1..ad5a942e91 100644 --- a/classpath/java/lang/reflect/Method.java +++ b/classpath/java/lang/reflect/Method.java @@ -21,6 +21,8 @@ public class Method extends AccessibleObject implements Member { if (v) vmFlags |= Accessible; else vmFlags &= ~Accessible; } + public static native Method getCaller(); + public Class getDeclaringClass() { return class_; } diff --git a/src/builtin.cpp b/src/builtin.cpp index f1f7ff8df5..98f6ab9797 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -59,7 +59,7 @@ Object_notifyAll(Thread* t, jobject this_) } jclass -Class_forName(Thread* t, jclass, jstring name) +search(Thread* t, jstring name, object (*op)(Thread*, object)) { if (LIKELY(name)) { object n = makeByteArray(t, stringLength(t, *name) + 1, false); @@ -68,18 +68,11 @@ Class_forName(Thread* t, jclass, jstring name) replace('.', '/', s); - object c = resolveClass(t, n); + object c = op(t, n); if (t->exception) { return 0; } - if (classVmFlags(t, c) & NeedInitFlag) { - PROTECT(t, c); - - classVmFlags(t, c) &= ~NeedInitFlag; - run(t, classInitializer(t, c), 0); - } - return pushReference(t, c); } else { t->exception = makeNullPointerException(t); @@ -87,6 +80,29 @@ Class_forName(Thread* t, jclass, jstring name) } } +jclass +ClassLoader_defineClass(Thread* t, jclass, jbyteArray b, jint offset, + jint length) +{ + uint8_t* buffer = static_cast(t->vm->system->allocate(length)); + memcpy(buffer, &byteArrayBody(t, *b, offset), length); + object c = parseClass(t, buffer, length); + t->vm->system->free(buffer); + return pushReference(t, c); +} + +jclass +SystemClassLoader_findLoadedClass(Thread* t, jclass, jstring name) +{ + return search(t, name, findClass); +} + +jclass +SystemClassLoader_findClass(Thread* t, jclass, jstring name) +{ + return search(t, name, resolveClass); +} + jclass Class_primitiveClass(Thread* t, jclass, jchar name) { @@ -297,6 +313,13 @@ Constructor_make(Thread* t, jclass, jclass c) return pushReference(t, make(t, c)); } +jobject +Method_getCaller(Thread* t, jclass) +{ + return pushReference + (t, frameMethod(t, frameNext(t, frameNext(t, t->frame)))); +} + jobject Method_invoke(Thread* t, jobject this_, jobject instancep, jobjectArray argumentsp) @@ -638,16 +661,22 @@ populateBuiltinMap(Thread* t, object map) const char* key; void* value; } builtins[] = { - { "Java_java_lang_Class_forName", - reinterpret_cast(::Class_forName) }, { "Java_java_lang_Class_isAssignableFrom", reinterpret_cast(::Class_isAssignableFrom) }, { "Java_java_lang_Class_primitiveClass", reinterpret_cast(::Class_primitiveClass) }, + { "Java_java_lang_ClassLoader_defineClass", + reinterpret_cast(::ClassLoader_defineClass) }, + { "Java_java_lang_System_arraycopy", reinterpret_cast(::System_arraycopy) }, + { "Java_java_lang_SystemClassLoader_findClass", + reinterpret_cast(::SystemClassLoader_findClass) }, + { "Java_java_lang_SystemClassLoader_findLoadedClass", + reinterpret_cast(::SystemClassLoader_findLoadedClass) }, + { "Java_java_lang_Runtime_loadLibrary", reinterpret_cast(::Runtime_loadLibrary) }, { "Java_java_lang_Runtime_gc", @@ -698,6 +727,8 @@ populateBuiltinMap(Thread* t, object map) { "Java_java_lang_reflect_Field_set", reinterpret_cast(::Field_set) }, + { "Java_java_lang_reflect_Method_getCaller", + reinterpret_cast(::Method_getCaller) }, { "Java_java_lang_reflect_Method_invoke", reinterpret_cast(::Method_invoke) }, diff --git a/src/machine.cpp b/src/machine.cpp index adc2db1855..981b859084 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -1064,73 +1064,6 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool) } } -object -parseClass(Thread* t, const uint8_t* data, unsigned size) -{ - class Client : public Stream::Client { - public: - Client(Thread* t): t(t) { } - - virtual void NO_RETURN handleEOS() { - abort(t); - } - - private: - Thread* t; - } client(t); - - Stream s(&client, data, size); - - uint32_t magic = s.read4(); - assert(t, magic == 0xCAFEBABE); - s.read2(); // minor version - s.read2(); // major version - - object pool = parsePool(t, s); - PROTECT(t, pool); - - unsigned flags = s.read2(); - unsigned name = s.read2(); - - object class_ = makeClass(t, - flags, - 0, // VM flags - 0, // array dimensions - 0, // fixed size - 0, // array size - 0, // object mask - arrayBody(t, pool, name - 1), - 0, // super - 0, // interfaces - 0, // vtable - 0, // fields - 0, // methods - 0); // static table - PROTECT(t, class_); - - unsigned super = s.read2(); - if (super) { - object sc = resolveClass(t, arrayBody(t, pool, super - 1)); - if (UNLIKELY(t->exception)) return 0; - - set(t, classSuper(t, class_), sc); - - classVmFlags(t, class_) - |= (classVmFlags(t, sc) & (ReferenceFlag | WeakReferenceFlag)); - } - - parseInterfaceTable(t, s, class_, pool); - if (UNLIKELY(t->exception)) return 0; - - parseFieldTable(t, s, class_, pool); - if (UNLIKELY(t->exception)) return 0; - - parseMethodTable(t, s, class_, pool); - if (UNLIKELY(t->exception)) return 0; - - return class_; -} - void updateBootstrapClass(Thread* t, object bootstrapClass, object class_) { @@ -1195,7 +1128,8 @@ makeArrayClass(Thread* t, unsigned dimensions, object spec, classVirtualTable(t, arrayBody(t, t->vm->types, Machine::JobjectType)), 0, 0, - 0); + 0, + t->vm->loader); } object @@ -1285,7 +1219,7 @@ Machine::Machine(System* system, Heap* heap, ClassFinder* classFinder): classLock(0), referenceLock(0), libraries(0), - classMap(0), + loader(0), bootstrapClassMap(0), builtinMap(0), monitorMap(0), @@ -1358,11 +1292,18 @@ Thread::Thread(Machine* m, object javaThread, Thread* parent): Thread* t = this; + t->vm->loader = allocate(t, sizeof(void*) * 3); + memset(t->vm->loader, 0, sizeof(void*) * 2); + #include "type-initializations.cpp" object arrayClass = arrayBody(t, t->vm->types, Machine::ArrayType); set(t, cast(t->vm->types, 0), arrayClass); + object loaderClass = arrayBody + (t, t->vm->types, Machine::SystemClassLoaderType); + set(t, cast(t->vm->loader, 0), loaderClass); + object objectClass = arrayBody(t, m->types, Machine::JobjectType); object classClass = arrayBody(t, m->types, Machine::ClassType); @@ -1386,7 +1327,9 @@ Thread::Thread(Machine* m, object javaThread, Thread* parent): #include "type-java-initializations.cpp" - m->classMap = makeHashMap(this, 0, 0); + object loaderMap = makeHashMap(this, 0, 0); + set(t, systemClassLoaderMap(t, m->loader), loaderMap); + m->builtinMap = makeHashMap(this, 0, 0); m->monitorMap = makeWeakHashMap(this, 0, 0); m->stringMap = makeWeakHashMap(this, 0, 0); @@ -2087,14 +2030,92 @@ primitiveSize(Thread* t, unsigned code) } } +object +findClass(Thread* t, object spec) +{ + PROTECT(t, spec); + ACQUIRE(t, t->vm->classLock); + + return hashMapFind(t, systemClassLoaderMap(t, t->vm->loader), + spec, byteArrayHash, byteArrayEqual); +} + +object +parseClass(Thread* t, const uint8_t* data, unsigned size) +{ + class Client : public Stream::Client { + public: + Client(Thread* t): t(t) { } + + virtual void NO_RETURN handleEOS() { + abort(t); + } + + private: + Thread* t; + } client(t); + + Stream s(&client, data, size); + + uint32_t magic = s.read4(); + assert(t, magic == 0xCAFEBABE); + s.read2(); // minor version + s.read2(); // major version + + object pool = parsePool(t, s); + PROTECT(t, pool); + + unsigned flags = s.read2(); + unsigned name = s.read2(); + + object class_ = makeClass(t, + flags, + 0, // VM flags + 0, // array dimensions + 0, // fixed size + 0, // array size + 0, // object mask + arrayBody(t, pool, name - 1), + 0, // super + 0, // interfaces + 0, // vtable + 0, // fields + 0, // methods + 0, // static table + t->vm->loader); + PROTECT(t, class_); + + unsigned super = s.read2(); + if (super) { + object sc = resolveClass(t, arrayBody(t, pool, super - 1)); + if (UNLIKELY(t->exception)) return 0; + + set(t, classSuper(t, class_), sc); + + classVmFlags(t, class_) + |= (classVmFlags(t, sc) & (ReferenceFlag | WeakReferenceFlag)); + } + + parseInterfaceTable(t, s, class_, pool); + if (UNLIKELY(t->exception)) return 0; + + parseFieldTable(t, s, class_, pool); + if (UNLIKELY(t->exception)) return 0; + + parseMethodTable(t, s, class_, pool); + if (UNLIKELY(t->exception)) return 0; + + return class_; +} + object resolveClass(Thread* t, object spec) { PROTECT(t, spec); ACQUIRE(t, t->vm->classLock); - object class_ = hashMapFind - (t, t->vm->classMap, spec, byteArrayHash, byteArrayEqual); + object class_ = hashMapFind(t, systemClassLoaderMap(t, t->vm->loader), + spec, byteArrayHash, byteArrayEqual); if (class_ == 0) { if (byteArrayBody(t, spec, 0) == '[') { class_ = hashMapFind @@ -2137,7 +2158,8 @@ resolveClass(Thread* t, object spec) if (class_) { PROTECT(t, class_); - hashMapInsert(t, t->vm->classMap, spec, class_, byteArrayHash); + hashMapInsert(t, systemClassLoaderMap(t, t->vm->loader), + spec, class_, byteArrayHash); } else if (t->exception == 0) { object message = makeString(t, "%s", &byteArrayBody(t, spec, 0)); t->exception = makeClassNotFoundException(t, message); @@ -2285,7 +2307,7 @@ collect(Thread* t, Heap::CollectionType type) Client(Machine* m): m(m) { } virtual void visitRoots(Heap::Visitor* v) { - v->visit(&(m->classMap)); + v->visit(&(m->loader)); v->visit(&(m->bootstrapClassMap)); v->visit(&(m->builtinMap)); v->visit(&(m->monitorMap)); diff --git a/src/machine.h b/src/machine.h index be335d0e5a..e5c8f642e3 100644 --- a/src/machine.h +++ b/src/machine.h @@ -1106,7 +1106,7 @@ class Machine { System::Monitor* classLock; System::Monitor* referenceLock; System::Library* libraries; - object classMap; + object loader; object bootstrapClassMap; object builtinMap; object monitorMap; @@ -2022,6 +2022,12 @@ fieldSize(Thread* t, object field) } } +object +findClass(Thread* t, object spec); + +object +parseClass(Thread* t, const uint8_t* data, unsigned length); + object resolveClass(Thread* t, object spec); diff --git a/src/type-generator.cpp b/src/type-generator.cpp index 835af84794..c36ec6acae 100644 --- a/src/type-generator.cpp +++ b/src/type-generator.cpp @@ -1488,7 +1488,7 @@ writeInitialization(Output* out, Object* type) out->write(typeFixedSize(type)); out->write(", "); out->write(typeArrayElementSize(type)); - out->write(", mask, 0, super, 0, 0, 0, 0, 0);\n"); + out->write(", mask, 0, super, 0, 0, 0, 0, 0, t->vm->loader);\n"); out->write(" set(t, arrayBody(t, t->vm->types, Machine::"); out->write(capitalize(typeName(type))); diff --git a/src/types.def b/src/types.def index 48e4f03e51..187a46a80f 100644 --- a/src/types.def +++ b/src/types.def @@ -14,7 +14,16 @@ (object virtualTable) (object fieldTable) (object methodTable) - (object staticTable)) + (object staticTable) + (object loader)) + +(type classLoader java/lang/ClassLoader + (extends jobject) + (object parent)) + +(type systemClassLoader java/lang/SystemClassLoader + (extends classLoader) + (object map)) (type accessibleObject java/lang/reflect/AccessibleObject (extends jobject))