mirror of
https://github.com/corda/corda.git
synced 2025-01-16 01:40:17 +00:00
flesh out ClassLoader, etc.
This commit is contained in:
parent
da692a539f
commit
38d4ee6e07
@ -6,6 +6,10 @@ import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
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 byte vmFlags;
|
||||
private byte arrayDimensions;
|
||||
@ -19,6 +23,7 @@ public final class Class <T> {
|
||||
private Field[] fieldTable;
|
||||
private Method[] methodTable;
|
||||
private Object[] staticTable;
|
||||
private ClassLoader loader;
|
||||
|
||||
private Class() { }
|
||||
|
||||
@ -26,8 +31,25 @@ public final class Class <T> {
|
||||
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("<clinit>", 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 <T> {
|
||||
}
|
||||
|
||||
public ClassLoader getClassLoader() {
|
||||
return ClassLoader.getSystemClassLoader();
|
||||
return loader;
|
||||
}
|
||||
|
||||
public int getModifiers() {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
9
classpath/java/lang/SystemClassLoader.java
Normal file
9
classpath/java/lang/SystemClassLoader.java
Normal 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);
|
||||
}
|
@ -21,6 +21,8 @@ public class Method<T> extends AccessibleObject implements Member {
|
||||
if (v) vmFlags |= Accessible; else vmFlags &= ~Accessible;
|
||||
}
|
||||
|
||||
public static native Method getCaller();
|
||||
|
||||
public Class<T> getDeclaringClass() {
|
||||
return class_;
|
||||
}
|
||||
|
@ -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<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
|
||||
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<void*>(::Class_forName) },
|
||||
{ "Java_java_lang_Class_isAssignableFrom",
|
||||
reinterpret_cast<void*>(::Class_isAssignableFrom) },
|
||||
{ "Java_java_lang_Class_primitiveClass",
|
||||
reinterpret_cast<void*>(::Class_primitiveClass) },
|
||||
|
||||
{ "Java_java_lang_ClassLoader_defineClass",
|
||||
reinterpret_cast<void*>(::ClassLoader_defineClass) },
|
||||
|
||||
{ "Java_java_lang_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",
|
||||
reinterpret_cast<void*>(::Runtime_loadLibrary) },
|
||||
{ "Java_java_lang_Runtime_gc",
|
||||
@ -698,6 +727,8 @@ populateBuiltinMap(Thread* t, object map)
|
||||
{ "Java_java_lang_reflect_Field_set",
|
||||
reinterpret_cast<void*>(::Field_set) },
|
||||
|
||||
{ "Java_java_lang_reflect_Method_getCaller",
|
||||
reinterpret_cast<void*>(::Method_getCaller) },
|
||||
{ "Java_java_lang_reflect_Method_invoke",
|
||||
reinterpret_cast<void*>(::Method_invoke) },
|
||||
|
||||
|
170
src/machine.cpp
170
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<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 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));
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)));
|
||||
|
@ -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))
|
||||
|
Loading…
Reference in New Issue
Block a user