mirror of
https://github.com/corda/corda.git
synced 2025-01-16 01:40:17 +00:00
acquire class lock before running static initializer; wrap exceptions thrown from static initializers in ExceptionInInitializerError instances
This commit is contained in:
parent
6ddb8c839c
commit
1997ea6b8c
@ -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,18 +37,16 @@ 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 {
|
||||
if (name.startsWith("[")) {
|
||||
|
@ -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);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
2
makefile
2
makefile
@ -16,7 +16,7 @@ src = src
|
||||
classpath = classpath
|
||||
test = test
|
||||
|
||||
input = $(cls)/Threads.class
|
||||
input = $(cls)/Reflection.class
|
||||
|
||||
cxx = g++
|
||||
cc = gcc
|
||||
|
@ -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) },
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
86
src/run.cpp
86
src/run.cpp
@ -65,6 +65,14 @@ popFrame(Thread* t)
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
if (t->frame >= 0) {
|
||||
@ -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);
|
||||
|
||||
|
@ -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))
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user