flesh out ClassLoader, etc.

This commit is contained in:
Joel Dice 2007-07-30 17:19:05 -06:00
parent da692a539f
commit 38d4ee6e07
10 changed files with 272 additions and 144 deletions

View File

@ -6,6 +6,10 @@ import java.lang.reflect.Field;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
public final class Class <T> { public final class Class <T> {
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 short flags;
private byte vmFlags; private byte vmFlags;
private byte arrayDimensions; private byte arrayDimensions;
@ -19,6 +23,7 @@ public final class Class <T> {
private Field[] fieldTable; private Field[] fieldTable;
private Method[] methodTable; private Method[] methodTable;
private Object[] staticTable; private Object[] staticTable;
private ClassLoader loader;
private Class() { } private Class() { }
@ -26,8 +31,25 @@ public final class Class <T> {
return new String(name, 0, name.length - 1, false); return new String(name, 0, name.length - 1, false);
} }
public static native Class forName(String name) public static Class forName(String name) throws ClassNotFoundException {
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("<clinit>", new Class[0]);
if (m != null) {
m.invoke(null);
}
}
return c;
}
private static native Class primitiveClass(char name); private static native Class primitiveClass(char name);
@ -282,7 +304,7 @@ public final class Class <T> {
} }
public ClassLoader getClassLoader() { public ClassLoader getClassLoader() {
return ClassLoader.getSystemClassLoader(); return loader;
} }
public int getModifiers() { public int getModifiers() {

View File

@ -1,15 +1,78 @@
package java.lang; package java.lang;
public class ClassLoader { public abstract class ClassLoader {
private static final ClassLoader instance = new 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() { 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 { 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;
} }
} }

View File

@ -27,63 +27,27 @@ public final class Math {
return (int) (v + 0.5); return (int) (v + 0.5);
} }
public static double floor(double v) { public static native double floor(double v);
// todo
return 0;
}
public static double ceil(double v) { public static native double ceil(double v);
// todo
return 0;
}
public static double exp(double v) { public static native double exp(double v);
// todo
return 0;
}
public static double log(double v) { public static native double log(double v);
// todo
return 0;
}
public static double cos(double v) { public static native double cos(double v);
// todo
return 0;
}
public static double sin(double v) { public static native double sin(double v);
// todo
return 0;
}
public static double tan(double v) { public static native double tan(double v);
// todo
return 0;
}
public static double acos(double v) { public static native double acos(double v);
// todo
return 0;
}
public static double asin(double v) { public static native double asin(double v);
// todo
return 0;
}
public static double atan(double v) { public static native double atan(double v);
// todo
return 0;
}
public static double sqrt(double v) { public static native double sqrt(double v);
// todo
return 0;
}
public static double pow(double v, double e) { public static native double pow(double v, double e);
// todo
return 0;
}
} }

View File

@ -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);
}

View File

@ -21,6 +21,8 @@ public class Method<T> extends AccessibleObject implements Member {
if (v) vmFlags |= Accessible; else vmFlags &= ~Accessible; if (v) vmFlags |= Accessible; else vmFlags &= ~Accessible;
} }
public static native Method getCaller();
public Class<T> getDeclaringClass() { public Class<T> getDeclaringClass() {
return class_; return class_;
} }

View File

@ -59,7 +59,7 @@ Object_notifyAll(Thread* t, jobject this_)
} }
jclass jclass
Class_forName(Thread* t, jclass, jstring name) search(Thread* t, jstring name, object (*op)(Thread*, object))
{ {
if (LIKELY(name)) { if (LIKELY(name)) {
object n = makeByteArray(t, stringLength(t, *name) + 1, false); object n = makeByteArray(t, stringLength(t, *name) + 1, false);
@ -68,18 +68,11 @@ Class_forName(Thread* t, jclass, jstring name)
replace('.', '/', s); replace('.', '/', s);
object c = resolveClass(t, n); object c = op(t, n);
if (t->exception) { if (t->exception) {
return 0; return 0;
} }
if (classVmFlags(t, c) & NeedInitFlag) {
PROTECT(t, c);
classVmFlags(t, c) &= ~NeedInitFlag;
run(t, classInitializer(t, c), 0);
}
return pushReference(t, c); return pushReference(t, c);
} else { } else {
t->exception = makeNullPointerException(t); 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<uint8_t*>(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 jclass
Class_primitiveClass(Thread* t, jclass, jchar name) Class_primitiveClass(Thread* t, jclass, jchar name)
{ {
@ -297,6 +313,13 @@ Constructor_make(Thread* t, jclass, jclass c)
return pushReference(t, make(t, 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 jobject
Method_invoke(Thread* t, jobject this_, jobject instancep, Method_invoke(Thread* t, jobject this_, jobject instancep,
jobjectArray argumentsp) jobjectArray argumentsp)
@ -638,16 +661,22 @@ populateBuiltinMap(Thread* t, object map)
const char* key; const char* key;
void* value; void* value;
} builtins[] = { } builtins[] = {
{ "Java_java_lang_Class_forName",
reinterpret_cast<void*>(::Class_forName) },
{ "Java_java_lang_Class_isAssignableFrom", { "Java_java_lang_Class_isAssignableFrom",
reinterpret_cast<void*>(::Class_isAssignableFrom) }, reinterpret_cast<void*>(::Class_isAssignableFrom) },
{ "Java_java_lang_Class_primitiveClass", { "Java_java_lang_Class_primitiveClass",
reinterpret_cast<void*>(::Class_primitiveClass) }, reinterpret_cast<void*>(::Class_primitiveClass) },
{ "Java_java_lang_ClassLoader_defineClass",
reinterpret_cast<void*>(::ClassLoader_defineClass) },
{ "Java_java_lang_System_arraycopy", { "Java_java_lang_System_arraycopy",
reinterpret_cast<void*>(::System_arraycopy) }, reinterpret_cast<void*>(::System_arraycopy) },
{ "Java_java_lang_SystemClassLoader_findClass",
reinterpret_cast<void*>(::SystemClassLoader_findClass) },
{ "Java_java_lang_SystemClassLoader_findLoadedClass",
reinterpret_cast<void*>(::SystemClassLoader_findLoadedClass) },
{ "Java_java_lang_Runtime_loadLibrary", { "Java_java_lang_Runtime_loadLibrary",
reinterpret_cast<void*>(::Runtime_loadLibrary) }, reinterpret_cast<void*>(::Runtime_loadLibrary) },
{ "Java_java_lang_Runtime_gc", { "Java_java_lang_Runtime_gc",
@ -698,6 +727,8 @@ populateBuiltinMap(Thread* t, object map)
{ "Java_java_lang_reflect_Field_set", { "Java_java_lang_reflect_Field_set",
reinterpret_cast<void*>(::Field_set) }, reinterpret_cast<void*>(::Field_set) },
{ "Java_java_lang_reflect_Method_getCaller",
reinterpret_cast<void*>(::Method_getCaller) },
{ "Java_java_lang_reflect_Method_invoke", { "Java_java_lang_reflect_Method_invoke",
reinterpret_cast<void*>(::Method_invoke) }, reinterpret_cast<void*>(::Method_invoke) },

View File

@ -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 void
updateBootstrapClass(Thread* t, object bootstrapClass, object class_) 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)), classVirtualTable(t, arrayBody(t, t->vm->types, Machine::JobjectType)),
0, 0,
0, 0,
0); 0,
t->vm->loader);
} }
object object
@ -1285,7 +1219,7 @@ Machine::Machine(System* system, Heap* heap, ClassFinder* classFinder):
classLock(0), classLock(0),
referenceLock(0), referenceLock(0),
libraries(0), libraries(0),
classMap(0), loader(0),
bootstrapClassMap(0), bootstrapClassMap(0),
builtinMap(0), builtinMap(0),
monitorMap(0), monitorMap(0),
@ -1358,11 +1292,18 @@ Thread::Thread(Machine* m, object javaThread, Thread* parent):
Thread* t = this; Thread* t = this;
t->vm->loader = allocate(t, sizeof(void*) * 3);
memset(t->vm->loader, 0, sizeof(void*) * 2);
#include "type-initializations.cpp" #include "type-initializations.cpp"
object arrayClass = arrayBody(t, t->vm->types, Machine::ArrayType); object arrayClass = arrayBody(t, t->vm->types, Machine::ArrayType);
set(t, cast<object>(t->vm->types, 0), arrayClass); set(t, cast<object>(t->vm->types, 0), arrayClass);
object loaderClass = arrayBody
(t, t->vm->types, Machine::SystemClassLoaderType);
set(t, cast<object>(t->vm->loader, 0), loaderClass);
object objectClass = arrayBody(t, m->types, Machine::JobjectType); object objectClass = arrayBody(t, m->types, Machine::JobjectType);
object classClass = arrayBody(t, m->types, Machine::ClassType); 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" #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->builtinMap = makeHashMap(this, 0, 0);
m->monitorMap = makeWeakHashMap(this, 0, 0); m->monitorMap = makeWeakHashMap(this, 0, 0);
m->stringMap = 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 object
resolveClass(Thread* t, object spec) resolveClass(Thread* t, object spec)
{ {
PROTECT(t, spec); PROTECT(t, spec);
ACQUIRE(t, t->vm->classLock); ACQUIRE(t, t->vm->classLock);
object class_ = hashMapFind object class_ = hashMapFind(t, systemClassLoaderMap(t, t->vm->loader),
(t, t->vm->classMap, spec, byteArrayHash, byteArrayEqual); spec, byteArrayHash, byteArrayEqual);
if (class_ == 0) { if (class_ == 0) {
if (byteArrayBody(t, spec, 0) == '[') { if (byteArrayBody(t, spec, 0) == '[') {
class_ = hashMapFind class_ = hashMapFind
@ -2137,7 +2158,8 @@ resolveClass(Thread* t, object spec)
if (class_) { if (class_) {
PROTECT(t, 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) { } else if (t->exception == 0) {
object message = makeString(t, "%s", &byteArrayBody(t, spec, 0)); object message = makeString(t, "%s", &byteArrayBody(t, spec, 0));
t->exception = makeClassNotFoundException(t, message); t->exception = makeClassNotFoundException(t, message);
@ -2285,7 +2307,7 @@ collect(Thread* t, Heap::CollectionType type)
Client(Machine* m): m(m) { } Client(Machine* m): m(m) { }
virtual void visitRoots(Heap::Visitor* v) { virtual void visitRoots(Heap::Visitor* v) {
v->visit(&(m->classMap)); v->visit(&(m->loader));
v->visit(&(m->bootstrapClassMap)); v->visit(&(m->bootstrapClassMap));
v->visit(&(m->builtinMap)); v->visit(&(m->builtinMap));
v->visit(&(m->monitorMap)); v->visit(&(m->monitorMap));

View File

@ -1106,7 +1106,7 @@ class Machine {
System::Monitor* classLock; System::Monitor* classLock;
System::Monitor* referenceLock; System::Monitor* referenceLock;
System::Library* libraries; System::Library* libraries;
object classMap; object loader;
object bootstrapClassMap; object bootstrapClassMap;
object builtinMap; object builtinMap;
object monitorMap; 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 object
resolveClass(Thread* t, object spec); resolveClass(Thread* t, object spec);

View File

@ -1488,7 +1488,7 @@ writeInitialization(Output* out, Object* type)
out->write(typeFixedSize(type)); out->write(typeFixedSize(type));
out->write(", "); out->write(", ");
out->write(typeArrayElementSize(type)); 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(" set(t, arrayBody(t, t->vm->types, Machine::");
out->write(capitalize(typeName(type))); out->write(capitalize(typeName(type)));

View File

@ -14,7 +14,16 @@
(object virtualTable) (object virtualTable)
(object fieldTable) (object fieldTable)
(object methodTable) (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 (type accessibleObject java/lang/reflect/AccessibleObject
(extends jobject)) (extends jobject))