acquire class lock before running static initializer; wrap exceptions thrown from static initializers in ExceptionInInitializerError instances

This commit is contained in:
Joel Dice 2007-08-01 17:48:36 -06:00
parent 6ddb8c839c
commit 1997ea6b8c
8 changed files with 129 additions and 67 deletions

View File

@ -6,10 +6,6 @@ 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;
@ -41,17 +37,15 @@ public final class Class <T> {
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);
}
if (initialize) {
c.initialize();
}
return c;
}
private static native Class primitiveClass(char name);
private native void initialize();
static Class forCanonicalName(String name) {
try {

View File

@ -1,9 +1,19 @@
package java.net;
public class URL {
private final String value;
public final class URL {
// private final String protocol;
// private final String host;
// private final int port;
// private final String file;
public URL(String s) throws MalformedURLException {
value = s;
// int colon = s.indexOf(':');
// int slash = s.indexOf('/');
// if (colon > 0 && (slash < 0 || colon < slash)) {
// protocol = s.substring(0, colon);
// // todo
// } else {
// throw new MalformedURLException(s);
// }
}
}

View File

@ -16,7 +16,7 @@ src = src
classpath = classpath
test = test
input = $(cls)/Threads.class
input = $(cls)/Reflection.class
cxx = g++
cc = gcc

View File

@ -131,6 +131,21 @@ Class_primitiveClass(Thread* t, jclass, jchar name)
}
}
void
Class_initialize(Thread* t, jobject this_)
{
acquire(t, t->vm->classLock);
object c = *this_;
if (classVmFlags(t, c) & NeedInitFlag
and (classVmFlags(t, c) & InitFlag) == 0)
{
classVmFlags(t, c) |= InitFlag;
run(t, classInitializer(t, c), 0);
} else {
release(t, t->vm->classLock);
}
}
jboolean
Class_isAssignableFrom(Thread* t, jobject this_, jclass that)
{
@ -665,6 +680,8 @@ populateBuiltinMap(Thread* t, object map)
reinterpret_cast<void*>(::Class_isAssignableFrom) },
{ "Java_java_lang_Class_primitiveClass",
reinterpret_cast<void*>(::Class_primitiveClass) },
{ "Java_java_lang_Class_initialize",
reinterpret_cast<void*>(::Class_initialize) },
{ "Java_java_lang_ClassLoader_defineClass",
reinterpret_cast<void*>(::ClassLoader_defineClass) },

View File

@ -3,6 +3,7 @@
#include "machine.h"
#include "stream.h"
#include "constants.h"
#include "run.h"
using namespace vm;
@ -948,6 +949,7 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
if (strcmp(reinterpret_cast<const int8_t*>("<clinit>"),
&byteArrayBody(t, methodName(t, method), 0)) == 0)
{
methodVmFlags(t, method) |= ClassInitFlag;
classVmFlags(t, class_) |= NeedInitFlag;
}
} else {

View File

@ -55,9 +55,14 @@ enum StackTag {
const int NativeLine = -1;
const int UnknownLine = -2;
// class flags:
const unsigned ReferenceFlag = 1 << 0;
const unsigned WeakReferenceFlag = 1 << 1;
const unsigned NeedInitFlag = 1 << 2;
const unsigned InitFlag = 1 << 3;
// method flags:
const unsigned ClassInitFlag = 1 << 0;
class Thread;
@ -1280,18 +1285,32 @@ stress(Thread*)
#endif // not VM_STRESS
inline void
acquire(Thread* t, System::Monitor* m)
{
if (not m->tryAcquire(t->systemThread)) {
ENTER(t, Thread::IdleState);
m->acquire(t->systemThread);
}
stress(t);
}
inline void
release(Thread* t, System::Monitor* m)
{
m->release(t->systemThread);
}
class MonitorResource {
public:
MonitorResource(Thread* t, System::Monitor* m): t(t), m(m) {
stress(t);
if (not m->tryAcquire(t->systemThread)) {
ENTER(t, Thread::IdleState);
m->acquire(t->systemThread);
}
acquire(t, m);
}
~MonitorResource() { m->release(t->systemThread); }
~MonitorResource() {
release(t, m);
}
private:
Thread* t;
@ -1301,10 +1320,12 @@ class MonitorResource {
class RawMonitorResource {
public:
RawMonitorResource(Thread* t, System::Monitor* m): t(t), m(m) {
m->acquire(t->systemThread);
acquire(t, m);
}
~RawMonitorResource() { m->release(t->systemThread); }
~RawMonitorResource() {
release(t, m);
}
private:
Thread* t;
@ -1513,6 +1534,14 @@ makeUnsatisfiedLinkError(Thread* t, object message)
return makeUnsatisfiedLinkError(t, message, trace, 0);
}
inline object
makeExceptionInInitializerError(Thread* t, object cause)
{
PROTECT(t, cause);
object trace = makeTrace(t);
return makeExceptionInInitializerError(t, 0, trace, cause);
}
object
make(Thread* t, object class_);
@ -2095,12 +2124,7 @@ acquire(Thread* t, object o)
t, m, objectHash(t, o));
}
if (not m->tryAcquire(t->systemThread)) {
ENTER(t, Thread::IdleState);
m->acquire(t->systemThread);
}
stress(t);
acquire(t, m);
}
inline void
@ -2113,7 +2137,7 @@ release(Thread* t, object o)
t, m, objectHash(t, o));
}
m->release(t->systemThread);
release(t, m);
}
inline void

View File

@ -64,6 +64,14 @@ popFrame(Thread* t)
release(t, peekObject(t, frameBase(t, t->frame)));
}
}
if (UNLIKELY(methodVmFlags(t, method) & ClassInitFlag)) {
if (t->exception) {
t->exception = makeExceptionInInitializerError(t, t->exception);
}
classVmFlags(t, methodClass(t, method)) &= ~(NeedInitFlag | InitFlag);
release(t, t->vm->classLock);
}
t->sp = frameBase(t, t->frame);
t->frame = frameNext(t, t->frame);
@ -495,6 +503,34 @@ invokeNative(Thread* t, object method)
return returnCode;
}
bool
classInit2(Thread* t, object class_, unsigned ipOffset)
{
PROTECT(t, class_);
acquire(t, t->vm->classLock);
if (classVmFlags(t, class_) & NeedInitFlag
and (classVmFlags(t, class_) & InitFlag) == 0)
{
classVmFlags(t, class_) |= InitFlag;
t->code = classInitializer(t, class_);
t->ip -= ipOffset;
return true;
} else {
release(t, t->vm->classLock);
return false;
}
}
inline bool
classInit(Thread* t, object class_, unsigned ipOffset)
{
if (UNLIKELY(classVmFlags(t, class_) & NeedInitFlag)) {
return classInit2(t, class_, ipOffset);
} else {
return false;
}
}
object
run(Thread* t)
{
@ -508,7 +544,13 @@ run(Thread* t)
object& exception = t->exception;
uintptr_t* stack = t->stack;
if (UNLIKELY(exception)) goto throw_;
if (UNLIKELY(exception)) {
goto throw_;
}
if (UNLIKELY(classInit(t, methodClass(t, frameMethod(t, frame)), 0))) {
goto invoke;
}
loop:
instruction = codeBody(t, code, ip++);
@ -901,12 +943,7 @@ run(Thread* t)
object field = resolveField(t, codePool(t, code), index - 1);
if (UNLIKELY(exception)) goto throw_;
if (classVmFlags(t, fieldClass(t, field)) & NeedInitFlag) {
classVmFlags(t, fieldClass(t, field)) &= ~NeedInitFlag;
code = classInitializer(t, fieldClass(t, field));
ip -= 3;
goto invoke;
}
if (UNLIKELY(classInit(t, fieldClass(t, field), 3))) goto invoke;
object v = arrayBody(t, classStaticTable(t, fieldClass(t, field)),
fieldOffset(t, field));
@ -1324,12 +1361,7 @@ run(Thread* t)
resolveClass(t, className(t, class_));
if (UNLIKELY(exception)) goto throw_;
if (classVmFlags(t, class_) & NeedInitFlag) {
classVmFlags(t, class_) &= ~NeedInitFlag;
code = classInitializer(t, class_);
ip -= 3;
goto invoke;
}
if (UNLIKELY(classInit(t, class_, 3))) goto invoke;
}
code = findMethod(t, method, class_);
@ -1352,12 +1384,7 @@ run(Thread* t)
object method = resolveMethod(t, codePool(t, code), index - 1);
if (UNLIKELY(exception)) goto throw_;
if (classVmFlags(t, methodClass(t, method)) & NeedInitFlag) {
classVmFlags(t, methodClass(t, method)) &= ~NeedInitFlag;
code = classInitializer(t, methodClass(t, method));
ip -= 3;
goto invoke;
}
if (UNLIKELY(classInit(t, methodClass(t, method), 3))) goto invoke;
code = method;
} goto invoke;
@ -1380,12 +1407,7 @@ run(Thread* t)
resolveClass(t, className(t, class_));
if (UNLIKELY(exception)) goto throw_;
if (classVmFlags(t, class_) & NeedInitFlag) {
classVmFlags(t, class_) &= ~NeedInitFlag;
code = classInitializer(t, class_);
ip -= 3;
goto invoke;
}
if (UNLIKELY(classInit(t, class_, 3))) goto invoke;
}
code = findMethod(t, method, class_);
@ -1763,12 +1785,7 @@ run(Thread* t)
object class_ = resolveClass(t, codePool(t, code), index - 1);
if (UNLIKELY(exception)) goto throw_;
if (classVmFlags(t, class_) & NeedInitFlag) {
classVmFlags(t, class_) &= ~NeedInitFlag;
code = classInitializer(t, class_);
ip -= 3;
goto invoke;
}
if (UNLIKELY(classInit(t, class_, 3))) goto invoke;
pushObject(t, make(t, class_));
} goto loop;
@ -1910,12 +1927,7 @@ run(Thread* t)
object field = resolveField(t, codePool(t, code), index - 1);
if (UNLIKELY(exception)) goto throw_;
if (classVmFlags(t, fieldClass(t, field)) & NeedInitFlag) {
classVmFlags(t, fieldClass(t, field)) &= ~NeedInitFlag;
code = classInitializer(t, fieldClass(t, field));
ip -= 3;
goto invoke;
}
if (UNLIKELY(classInit(t, fieldClass(t, field), 3))) goto invoke;
PROTECT(t, field);

View File

@ -214,6 +214,9 @@
(type unsatisfiedLinkError java/lang/UnsatisfiedLinkError
(extends linkageError))
(type exceptionInInitializerError java/lang/ExceptionInInitializerError
(extends error))
(type number java/lang/Number
(extends jobject))