mirror of
https://github.com/corda/corda.git
synced 2025-01-28 23:24:29 +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;
|
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;
|
||||||
@ -41,17 +37,15 @@ public final class Class <T> {
|
|||||||
throws ClassNotFoundException
|
throws ClassNotFoundException
|
||||||
{
|
{
|
||||||
Class c = loader.loadClass(name);
|
Class c = loader.loadClass(name);
|
||||||
if (initialize && ((c.flags & NeedInitFlag) != 0)) {
|
if (initialize) {
|
||||||
c.flags &= ~NeedInitFlag;
|
c.initialize();
|
||||||
Method m = c.findMethod("<clinit>", new Class[0]);
|
|
||||||
if (m != null) {
|
|
||||||
m.invoke(null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static native Class primitiveClass(char name);
|
private static native Class primitiveClass(char name);
|
||||||
|
|
||||||
|
private native void initialize();
|
||||||
|
|
||||||
static Class forCanonicalName(String name) {
|
static Class forCanonicalName(String name) {
|
||||||
try {
|
try {
|
||||||
|
@ -1,9 +1,19 @@
|
|||||||
package java.net;
|
package java.net;
|
||||||
|
|
||||||
public class URL {
|
public final class URL {
|
||||||
private final String value;
|
// private final String protocol;
|
||||||
|
// private final String host;
|
||||||
|
// private final int port;
|
||||||
|
// private final String file;
|
||||||
|
|
||||||
public URL(String s) throws MalformedURLException {
|
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
|
classpath = classpath
|
||||||
test = test
|
test = test
|
||||||
|
|
||||||
input = $(cls)/Threads.class
|
input = $(cls)/Reflection.class
|
||||||
|
|
||||||
cxx = g++
|
cxx = g++
|
||||||
cc = gcc
|
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
|
jboolean
|
||||||
Class_isAssignableFrom(Thread* t, jobject this_, jclass that)
|
Class_isAssignableFrom(Thread* t, jobject this_, jclass that)
|
||||||
{
|
{
|
||||||
@ -665,6 +680,8 @@ populateBuiltinMap(Thread* t, object map)
|
|||||||
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_Class_initialize",
|
||||||
|
reinterpret_cast<void*>(::Class_initialize) },
|
||||||
|
|
||||||
{ "Java_java_lang_ClassLoader_defineClass",
|
{ "Java_java_lang_ClassLoader_defineClass",
|
||||||
reinterpret_cast<void*>(::ClassLoader_defineClass) },
|
reinterpret_cast<void*>(::ClassLoader_defineClass) },
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "machine.h"
|
#include "machine.h"
|
||||||
#include "stream.h"
|
#include "stream.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
|
#include "run.h"
|
||||||
|
|
||||||
using namespace vm;
|
using namespace vm;
|
||||||
|
|
||||||
@ -948,6 +949,7 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
|
|||||||
if (strcmp(reinterpret_cast<const int8_t*>("<clinit>"),
|
if (strcmp(reinterpret_cast<const int8_t*>("<clinit>"),
|
||||||
&byteArrayBody(t, methodName(t, method), 0)) == 0)
|
&byteArrayBody(t, methodName(t, method), 0)) == 0)
|
||||||
{
|
{
|
||||||
|
methodVmFlags(t, method) |= ClassInitFlag;
|
||||||
classVmFlags(t, class_) |= NeedInitFlag;
|
classVmFlags(t, class_) |= NeedInitFlag;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -55,9 +55,14 @@ enum StackTag {
|
|||||||
const int NativeLine = -1;
|
const int NativeLine = -1;
|
||||||
const int UnknownLine = -2;
|
const int UnknownLine = -2;
|
||||||
|
|
||||||
|
// class flags:
|
||||||
const unsigned ReferenceFlag = 1 << 0;
|
const unsigned ReferenceFlag = 1 << 0;
|
||||||
const unsigned WeakReferenceFlag = 1 << 1;
|
const unsigned WeakReferenceFlag = 1 << 1;
|
||||||
const unsigned NeedInitFlag = 1 << 2;
|
const unsigned NeedInitFlag = 1 << 2;
|
||||||
|
const unsigned InitFlag = 1 << 3;
|
||||||
|
|
||||||
|
// method flags:
|
||||||
|
const unsigned ClassInitFlag = 1 << 0;
|
||||||
|
|
||||||
class Thread;
|
class Thread;
|
||||||
|
|
||||||
@ -1280,18 +1285,32 @@ stress(Thread*)
|
|||||||
|
|
||||||
#endif // not VM_STRESS
|
#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 {
|
class MonitorResource {
|
||||||
public:
|
public:
|
||||||
MonitorResource(Thread* t, System::Monitor* m): t(t), m(m) {
|
MonitorResource(Thread* t, System::Monitor* m): t(t), m(m) {
|
||||||
stress(t);
|
acquire(t, m);
|
||||||
|
|
||||||
if (not m->tryAcquire(t->systemThread)) {
|
|
||||||
ENTER(t, Thread::IdleState);
|
|
||||||
m->acquire(t->systemThread);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~MonitorResource() { m->release(t->systemThread); }
|
~MonitorResource() {
|
||||||
|
release(t, m);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Thread* t;
|
Thread* t;
|
||||||
@ -1301,10 +1320,12 @@ class MonitorResource {
|
|||||||
class RawMonitorResource {
|
class RawMonitorResource {
|
||||||
public:
|
public:
|
||||||
RawMonitorResource(Thread* t, System::Monitor* m): t(t), m(m) {
|
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:
|
private:
|
||||||
Thread* t;
|
Thread* t;
|
||||||
@ -1513,6 +1534,14 @@ makeUnsatisfiedLinkError(Thread* t, object message)
|
|||||||
return makeUnsatisfiedLinkError(t, message, trace, 0);
|
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
|
object
|
||||||
make(Thread* t, object class_);
|
make(Thread* t, object class_);
|
||||||
|
|
||||||
@ -2095,12 +2124,7 @@ acquire(Thread* t, object o)
|
|||||||
t, m, objectHash(t, o));
|
t, m, objectHash(t, o));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (not m->tryAcquire(t->systemThread)) {
|
acquire(t, m);
|
||||||
ENTER(t, Thread::IdleState);
|
|
||||||
m->acquire(t->systemThread);
|
|
||||||
}
|
|
||||||
|
|
||||||
stress(t);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
@ -2113,7 +2137,7 @@ release(Thread* t, object o)
|
|||||||
t, m, objectHash(t, o));
|
t, m, objectHash(t, o));
|
||||||
}
|
}
|
||||||
|
|
||||||
m->release(t->systemThread);
|
release(t, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
|
86
src/run.cpp
86
src/run.cpp
@ -64,6 +64,14 @@ popFrame(Thread* t)
|
|||||||
release(t, peekObject(t, frameBase(t, t->frame)));
|
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->sp = frameBase(t, t->frame);
|
||||||
t->frame = frameNext(t, t->frame);
|
t->frame = frameNext(t, t->frame);
|
||||||
@ -495,6 +503,34 @@ invokeNative(Thread* t, object method)
|
|||||||
return returnCode;
|
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
|
object
|
||||||
run(Thread* t)
|
run(Thread* t)
|
||||||
{
|
{
|
||||||
@ -508,7 +544,13 @@ run(Thread* t)
|
|||||||
object& exception = t->exception;
|
object& exception = t->exception;
|
||||||
uintptr_t* stack = t->stack;
|
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:
|
loop:
|
||||||
instruction = codeBody(t, code, ip++);
|
instruction = codeBody(t, code, ip++);
|
||||||
@ -901,12 +943,7 @@ run(Thread* t)
|
|||||||
object field = resolveField(t, codePool(t, code), index - 1);
|
object field = resolveField(t, codePool(t, code), index - 1);
|
||||||
if (UNLIKELY(exception)) goto throw_;
|
if (UNLIKELY(exception)) goto throw_;
|
||||||
|
|
||||||
if (classVmFlags(t, fieldClass(t, field)) & NeedInitFlag) {
|
if (UNLIKELY(classInit(t, fieldClass(t, field), 3))) goto invoke;
|
||||||
classVmFlags(t, fieldClass(t, field)) &= ~NeedInitFlag;
|
|
||||||
code = classInitializer(t, fieldClass(t, field));
|
|
||||||
ip -= 3;
|
|
||||||
goto invoke;
|
|
||||||
}
|
|
||||||
|
|
||||||
object v = arrayBody(t, classStaticTable(t, fieldClass(t, field)),
|
object v = arrayBody(t, classStaticTable(t, fieldClass(t, field)),
|
||||||
fieldOffset(t, field));
|
fieldOffset(t, field));
|
||||||
@ -1324,12 +1361,7 @@ run(Thread* t)
|
|||||||
resolveClass(t, className(t, class_));
|
resolveClass(t, className(t, class_));
|
||||||
if (UNLIKELY(exception)) goto throw_;
|
if (UNLIKELY(exception)) goto throw_;
|
||||||
|
|
||||||
if (classVmFlags(t, class_) & NeedInitFlag) {
|
if (UNLIKELY(classInit(t, class_, 3))) goto invoke;
|
||||||
classVmFlags(t, class_) &= ~NeedInitFlag;
|
|
||||||
code = classInitializer(t, class_);
|
|
||||||
ip -= 3;
|
|
||||||
goto invoke;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
code = findMethod(t, method, class_);
|
code = findMethod(t, method, class_);
|
||||||
@ -1352,12 +1384,7 @@ run(Thread* t)
|
|||||||
object method = resolveMethod(t, codePool(t, code), index - 1);
|
object method = resolveMethod(t, codePool(t, code), index - 1);
|
||||||
if (UNLIKELY(exception)) goto throw_;
|
if (UNLIKELY(exception)) goto throw_;
|
||||||
|
|
||||||
if (classVmFlags(t, methodClass(t, method)) & NeedInitFlag) {
|
if (UNLIKELY(classInit(t, methodClass(t, method), 3))) goto invoke;
|
||||||
classVmFlags(t, methodClass(t, method)) &= ~NeedInitFlag;
|
|
||||||
code = classInitializer(t, methodClass(t, method));
|
|
||||||
ip -= 3;
|
|
||||||
goto invoke;
|
|
||||||
}
|
|
||||||
|
|
||||||
code = method;
|
code = method;
|
||||||
} goto invoke;
|
} goto invoke;
|
||||||
@ -1380,12 +1407,7 @@ run(Thread* t)
|
|||||||
resolveClass(t, className(t, class_));
|
resolveClass(t, className(t, class_));
|
||||||
if (UNLIKELY(exception)) goto throw_;
|
if (UNLIKELY(exception)) goto throw_;
|
||||||
|
|
||||||
if (classVmFlags(t, class_) & NeedInitFlag) {
|
if (UNLIKELY(classInit(t, class_, 3))) goto invoke;
|
||||||
classVmFlags(t, class_) &= ~NeedInitFlag;
|
|
||||||
code = classInitializer(t, class_);
|
|
||||||
ip -= 3;
|
|
||||||
goto invoke;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
code = findMethod(t, method, class_);
|
code = findMethod(t, method, class_);
|
||||||
@ -1763,12 +1785,7 @@ run(Thread* t)
|
|||||||
object class_ = resolveClass(t, codePool(t, code), index - 1);
|
object class_ = resolveClass(t, codePool(t, code), index - 1);
|
||||||
if (UNLIKELY(exception)) goto throw_;
|
if (UNLIKELY(exception)) goto throw_;
|
||||||
|
|
||||||
if (classVmFlags(t, class_) & NeedInitFlag) {
|
if (UNLIKELY(classInit(t, class_, 3))) goto invoke;
|
||||||
classVmFlags(t, class_) &= ~NeedInitFlag;
|
|
||||||
code = classInitializer(t, class_);
|
|
||||||
ip -= 3;
|
|
||||||
goto invoke;
|
|
||||||
}
|
|
||||||
|
|
||||||
pushObject(t, make(t, class_));
|
pushObject(t, make(t, class_));
|
||||||
} goto loop;
|
} goto loop;
|
||||||
@ -1910,12 +1927,7 @@ run(Thread* t)
|
|||||||
object field = resolveField(t, codePool(t, code), index - 1);
|
object field = resolveField(t, codePool(t, code), index - 1);
|
||||||
if (UNLIKELY(exception)) goto throw_;
|
if (UNLIKELY(exception)) goto throw_;
|
||||||
|
|
||||||
if (classVmFlags(t, fieldClass(t, field)) & NeedInitFlag) {
|
if (UNLIKELY(classInit(t, fieldClass(t, field), 3))) goto invoke;
|
||||||
classVmFlags(t, fieldClass(t, field)) &= ~NeedInitFlag;
|
|
||||||
code = classInitializer(t, fieldClass(t, field));
|
|
||||||
ip -= 3;
|
|
||||||
goto invoke;
|
|
||||||
}
|
|
||||||
|
|
||||||
PROTECT(t, field);
|
PROTECT(t, field);
|
||||||
|
|
||||||
|
@ -214,6 +214,9 @@
|
|||||||
(type unsatisfiedLinkError java/lang/UnsatisfiedLinkError
|
(type unsatisfiedLinkError java/lang/UnsatisfiedLinkError
|
||||||
(extends linkageError))
|
(extends linkageError))
|
||||||
|
|
||||||
|
(type exceptionInInitializerError java/lang/ExceptionInInitializerError
|
||||||
|
(extends error))
|
||||||
|
|
||||||
(type number java/lang/Number
|
(type number java/lang/Number
|
||||||
(extends jobject))
|
(extends jobject))
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user