mirror of
https://github.com/corda/corda.git
synced 2025-01-07 13:38:47 +00:00
fix various classloading deadlocks and races
This commit is contained in:
parent
efd3ccb04f
commit
89f6adc93c
@ -85,7 +85,8 @@ Avian_avian_SystemClassLoader_resourceExists
|
|||||||
RUNTIME_ARRAY(char, n, stringLength(t, name) + 1);
|
RUNTIME_ARRAY(char, n, stringLength(t, name) + 1);
|
||||||
stringChars(t, name, RUNTIME_ARRAY_BODY(n));
|
stringChars(t, name, RUNTIME_ARRAY_BODY(n));
|
||||||
|
|
||||||
bool r = getFinder(t, loader)->exists(RUNTIME_ARRAY_BODY(n));
|
bool r = static_cast<Finder*>(systemClassLoaderFinder(t, loader))->exists
|
||||||
|
(RUNTIME_ARRAY_BODY(n));
|
||||||
|
|
||||||
// fprintf(stderr, "resource %s exists? %d\n", n, r);
|
// fprintf(stderr, "resource %s exists? %d\n", n, r);
|
||||||
|
|
||||||
|
@ -176,7 +176,7 @@ loadLibrary(Thread* t, const char* name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
System::Library* lib;
|
System::Library* lib;
|
||||||
if (LIKELY(t->m->system->success(t->m->system->load(&lib, name)))) {
|
if (t->m->system->success(t->m->system->load(&lib, name))) {
|
||||||
last->setNext(lib);
|
last->setNext(lib);
|
||||||
return lib;
|
return lib;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1602,6 +1602,7 @@ JVM_FindLoadedClass(Thread* t, jobject loader, jstring name)
|
|||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
object spec = makeByteArray(t, stringLength(t, *name) + 1);
|
object spec = makeByteArray(t, stringLength(t, *name) + 1);
|
||||||
|
|
||||||
{ char* s = reinterpret_cast<char*>(&byteArrayBody(t, spec, 0));
|
{ char* s = reinterpret_cast<char*>(&byteArrayBody(t, spec, 0));
|
||||||
stringChars(t, *name, s);
|
stringChars(t, *name, s);
|
||||||
replace('.', '/', s);
|
replace('.', '/', s);
|
||||||
|
@ -8226,7 +8226,7 @@ boot(MyThread* t, BootImage* image)
|
|||||||
|
|
||||||
syncInstructionCache(code, image->codeSize);
|
syncInstructionCache(code, image->codeSize);
|
||||||
|
|
||||||
setRoot(t, Machine::ClassMap, makeClassMap
|
set(t, root(t, Machine::BootLoader), ClassLoaderMap, makeClassMap
|
||||||
(t, bootClassTable, image->bootClassCount, heap));
|
(t, bootClassTable, image->bootClassCount, heap));
|
||||||
|
|
||||||
set(t, root(t, Machine::AppLoader), ClassLoaderMap, makeClassMap
|
set(t, root(t, Machine::AppLoader), ClassLoaderMap, makeClassMap
|
||||||
@ -8249,7 +8249,8 @@ boot(MyThread* t, BootImage* image)
|
|||||||
|
|
||||||
fixupVirtualThunks(t, image, code);
|
fixupVirtualThunks(t, image, code);
|
||||||
|
|
||||||
fixupMethods(t, root(t, Machine::ClassMap), image, code);
|
fixupMethods
|
||||||
|
(t, classLoaderMap(t, root(t, Machine::BootLoader)), image, code);
|
||||||
fixupMethods(t, classLoaderMap(t, root(t, Machine::AppLoader)), image, code);
|
fixupMethods(t, classLoaderMap(t, root(t, Machine::AppLoader)), image, code);
|
||||||
|
|
||||||
setRoot(t, Machine::BootstrapClassMap, makeHashMap(t, 0, 0));
|
setRoot(t, Machine::BootstrapClassMap, makeHashMap(t, 0, 0));
|
||||||
@ -8657,6 +8658,24 @@ compile(MyThread* t, Allocator* allocator, BootContext* bootContext,
|
|||||||
compile(t, &context);
|
compile(t, &context);
|
||||||
if (UNLIKELY(t->exception)) return;
|
if (UNLIKELY(t->exception)) return;
|
||||||
|
|
||||||
|
{ object ehTable = codeExceptionHandlerTable(t, methodCode(t, clone));
|
||||||
|
|
||||||
|
if (ehTable) {
|
||||||
|
PROTECT(t, ehTable);
|
||||||
|
|
||||||
|
// resolve all exception handler catch types before we acquire
|
||||||
|
// the class lock:
|
||||||
|
for (unsigned i = 0; i < exceptionHandlerTableLength(t, ehTable); ++i) {
|
||||||
|
ExceptionHandler* handler = exceptionHandlerTableBody(t, ehTable, i);
|
||||||
|
if (exceptionHandlerCatchType(handler)) {
|
||||||
|
resolveClassInPool
|
||||||
|
(t, clone, exceptionHandlerCatchType(handler) - 1);
|
||||||
|
if (UNLIKELY(t->exception)) return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ACQUIRE(t, t->m->classLock);
|
ACQUIRE(t, t->m->classLock);
|
||||||
|
|
||||||
if (methodAddress(t, method) != defaultThunk(t)) {
|
if (methodAddress(t, method) != defaultThunk(t)) {
|
||||||
|
108
src/machine.cpp
108
src/machine.cpp
@ -1791,9 +1791,9 @@ makeArrayClass(Thread* t, object loader, object spec, bool throw_)
|
|||||||
if (elementClass == 0) return 0;
|
if (elementClass == 0) return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
object class_ = hashMapFind
|
PROTECT(t, elementClass);
|
||||||
(t, getClassLoaderMap(t, classLoader(t, elementClass)), spec,
|
|
||||||
byteArrayHash, byteArrayEqual);
|
object class_ = findLoadedClass(t, classLoader(t, elementClass), spec);
|
||||||
|
|
||||||
return class_ ? class_ : makeArrayClass
|
return class_ ? class_ : makeArrayClass
|
||||||
(t, classLoader(t, elementClass), dimensions, spec, elementClass);
|
(t, classLoader(t, elementClass), dimensions, spec, elementClass);
|
||||||
@ -2002,12 +2002,18 @@ boot(Thread* t)
|
|||||||
set(t, type(t, Machine::DoubleArrayType), ClassStaticTable,
|
set(t, type(t, Machine::DoubleArrayType), ClassStaticTable,
|
||||||
type(t, Machine::JdoubleType));
|
type(t, Machine::JdoubleType));
|
||||||
|
|
||||||
setRoot(t, Machine::ClassMap, makeHashMap(t, 0, 0));
|
{ object map = makeHashMap(t, 0, 0);
|
||||||
|
set(t, root(t, Machine::BootLoader), ClassLoaderMap, map);
|
||||||
|
}
|
||||||
|
|
||||||
|
systemClassLoaderFinder(t, root(t, Machine::BootLoader)) = m->bootFinder;
|
||||||
|
|
||||||
{ object map = makeHashMap(t, 0, 0);
|
{ object map = makeHashMap(t, 0, 0);
|
||||||
set(t, root(t, Machine::AppLoader), ClassLoaderMap, map);
|
set(t, root(t, Machine::AppLoader), ClassLoaderMap, map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
systemClassLoaderFinder(t, root(t, Machine::AppLoader)) = m->appFinder;
|
||||||
|
|
||||||
set(t, root(t, Machine::AppLoader), ClassLoaderParent,
|
set(t, root(t, Machine::AppLoader), ClassLoaderParent,
|
||||||
root(t, Machine::BootLoader));
|
root(t, Machine::BootLoader));
|
||||||
|
|
||||||
@ -3127,7 +3133,7 @@ resolveSystemClass(Thread* t, object loader, object spec, bool throw_)
|
|||||||
ACQUIRE(t, t->m->classLock);
|
ACQUIRE(t, t->m->classLock);
|
||||||
|
|
||||||
object class_ = hashMapFind
|
object class_ = hashMapFind
|
||||||
(t, getClassLoaderMap(t, loader), spec, byteArrayHash, byteArrayEqual);
|
(t, classLoaderMap(t, loader), spec, byteArrayHash, byteArrayEqual);
|
||||||
|
|
||||||
if (class_ == 0) {
|
if (class_ == 0) {
|
||||||
if (classLoaderParent(t, loader)) {
|
if (classLoaderParent(t, loader)) {
|
||||||
@ -3149,7 +3155,8 @@ resolveSystemClass(Thread* t, object loader, object spec, bool throw_)
|
|||||||
".class",
|
".class",
|
||||||
7);
|
7);
|
||||||
|
|
||||||
System::Region* region = getFinder(t, loader)->find
|
System::Region* region = static_cast<Finder*>
|
||||||
|
(systemClassLoaderFinder(t, loader))->find
|
||||||
(RUNTIME_ARRAY_BODY(file));
|
(RUNTIME_ARRAY_BODY(file));
|
||||||
|
|
||||||
if (region) {
|
if (region) {
|
||||||
@ -3185,8 +3192,7 @@ resolveSystemClass(Thread* t, object loader, object spec, bool throw_)
|
|||||||
if (class_) {
|
if (class_) {
|
||||||
PROTECT(t, class_);
|
PROTECT(t, class_);
|
||||||
|
|
||||||
hashMapInsert
|
hashMapInsert(t, classLoaderMap(t, loader), spec, class_, byteArrayHash);
|
||||||
(t, getClassLoaderMap(t, loader), spec, class_, byteArrayHash);
|
|
||||||
} else if (throw_ and t->exception == 0) {
|
} else if (throw_ and t->exception == 0) {
|
||||||
object message = makeString(t, "%s", &byteArrayBody(t, spec, 0));
|
object message = makeString(t, "%s", &byteArrayBody(t, spec, 0));
|
||||||
t->exception = t->m->classpath->makeThrowable
|
t->exception = t->m->classpath->makeThrowable
|
||||||
@ -3200,48 +3206,34 @@ resolveSystemClass(Thread* t, object loader, object spec, bool throw_)
|
|||||||
object
|
object
|
||||||
findLoadedClass(Thread* t, object loader, object spec)
|
findLoadedClass(Thread* t, object loader, object spec)
|
||||||
{
|
{
|
||||||
|
PROTECT(t, loader);
|
||||||
PROTECT(t, spec);
|
PROTECT(t, spec);
|
||||||
|
|
||||||
ACQUIRE(t, t->m->classLock);
|
ACQUIRE(t, t->m->classLock);
|
||||||
|
|
||||||
object map = getClassLoaderMap(t, loader);
|
return classLoaderMap(t, loader) ? hashMapFind
|
||||||
if (map) {
|
(t, classLoaderMap(t, loader), spec, byteArrayHash, byteArrayEqual) : 0;
|
||||||
return hashMapFind(t, map, spec, byteArrayHash, byteArrayEqual);
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
resolveClass(Thread* t, object loader, object spec, bool throw_)
|
resolveClass(Thread* t, object loader, object spec, bool throw_)
|
||||||
{
|
{
|
||||||
if (loader == root(t, Machine::BootLoader)
|
if (objectClass(t, loader) == type(t, Machine::SystemClassLoaderType)) {
|
||||||
or loader == root(t, Machine::AppLoader))
|
|
||||||
{
|
|
||||||
return resolveSystemClass(t, loader, spec, throw_);
|
return resolveSystemClass(t, loader, spec, throw_);
|
||||||
} else {
|
} else {
|
||||||
expect(t, throw_);
|
expect(t, throw_);
|
||||||
|
|
||||||
|
{ object c = findLoadedClass(t, loader, spec);
|
||||||
|
if (c) {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PROTECT(t, loader);
|
PROTECT(t, loader);
|
||||||
PROTECT(t, spec);
|
PROTECT(t, spec);
|
||||||
|
|
||||||
{ ACQUIRE(t, t->m->classLock);
|
|
||||||
|
|
||||||
if (classLoaderMap(t, loader) == 0) {
|
|
||||||
object map = makeHashMap(t, 0, 0);
|
|
||||||
set(t, loader, ClassLoaderMap, map);
|
|
||||||
}
|
|
||||||
|
|
||||||
object class_ = hashMapFind
|
|
||||||
(t, classLoaderMap(t, loader), spec, byteArrayHash, byteArrayEqual);
|
|
||||||
|
|
||||||
if (class_) {
|
|
||||||
return class_;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
object class_;
|
|
||||||
if (byteArrayBody(t, spec, 0) == '[') {
|
if (byteArrayBody(t, spec, 0) == '[') {
|
||||||
class_ = resolveArrayClass(t, loader, spec, throw_);
|
return resolveArrayClass(t, loader, spec, throw_);
|
||||||
} else {
|
} else {
|
||||||
if (root(t, Machine::LoadClassMethod) == 0) {
|
if (root(t, Machine::LoadClassMethod) == 0) {
|
||||||
object m = resolveMethod
|
object m = resolveMethod
|
||||||
@ -3272,31 +3264,38 @@ resolveClass(Thread* t, object loader, object spec, bool throw_)
|
|||||||
replace('/', '.', RUNTIME_ARRAY_BODY(s), reinterpret_cast<char*>
|
replace('/', '.', RUNTIME_ARRAY_BODY(s), reinterpret_cast<char*>
|
||||||
(&byteArrayBody(t, spec, 0)));
|
(&byteArrayBody(t, spec, 0)));
|
||||||
|
|
||||||
object specString = makeString(t, "%s", s);
|
object specString = makeString(t, "%s", RUNTIME_ARRAY_BODY(s));
|
||||||
|
|
||||||
class_ = t->m->processor->invoke(t, method, loader, specString);
|
object c = t->m->processor->invoke(t, method, loader, specString);
|
||||||
|
|
||||||
if (LIKELY(class_ and t->exception == 0)) {
|
if (LIKELY(c and t->exception == 0)) {
|
||||||
class_ = jclassVmClass(t, class_);
|
PROTECT(t, c);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (class_) {
|
|
||||||
PROTECT(t, class_);
|
|
||||||
|
|
||||||
ACQUIRE(t, t->m->classLock);
|
ACQUIRE(t, t->m->classLock);
|
||||||
|
|
||||||
hashMapInsert(t, classLoaderMap(t, loader), spec, class_,
|
if (classLoaderMap(t, loader) == 0) {
|
||||||
byteArrayHash);
|
object map = makeHashMap(t, 0, 0);
|
||||||
} else if (throw_ and t->exception == 0) {
|
set(t, loader, ClassLoaderMap, map);
|
||||||
|
}
|
||||||
|
|
||||||
|
c = jclassVmClass(t, c);
|
||||||
|
|
||||||
|
hashMapInsert
|
||||||
|
(t, classLoaderMap(t, loader), spec, c, byteArrayHash);
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t->exception == 0) {
|
||||||
object message = makeString(t, "%s", &byteArrayBody(t, spec, 0));
|
object message = makeString(t, "%s", &byteArrayBody(t, spec, 0));
|
||||||
t->exception = t->m->classpath->makeThrowable
|
t->exception = t->m->classpath->makeThrowable
|
||||||
(t, Machine::ClassNotFoundExceptionType, message);
|
(t, Machine::ClassNotFoundExceptionType, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
return class_;
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3411,6 +3410,7 @@ preInitClass(Thread* t, object c)
|
|||||||
if (classVmFlags(t, c) & NeedInitFlag) {
|
if (classVmFlags(t, c) & NeedInitFlag) {
|
||||||
PROTECT(t, c);
|
PROTECT(t, c);
|
||||||
ACQUIRE(t, t->m->classLock);
|
ACQUIRE(t, t->m->classLock);
|
||||||
|
|
||||||
if (classVmFlags(t, c) & NeedInitFlag) {
|
if (classVmFlags(t, c) & NeedInitFlag) {
|
||||||
if (classVmFlags(t, c) & InitFlag) {
|
if (classVmFlags(t, c) & InitFlag) {
|
||||||
// If the class is currently being initialized and this the thread
|
// If the class is currently being initialized and this the thread
|
||||||
@ -3444,8 +3444,8 @@ void
|
|||||||
postInitClass(Thread* t, object c)
|
postInitClass(Thread* t, object c)
|
||||||
{
|
{
|
||||||
PROTECT(t, c);
|
PROTECT(t, c);
|
||||||
|
|
||||||
ACQUIRE(t, t->m->classLock);
|
ACQUIRE(t, t->m->classLock);
|
||||||
|
|
||||||
if (t->exception) {
|
if (t->exception) {
|
||||||
t->exception = t->m->classpath->makeThrowable
|
t->exception = t->m->classpath->makeThrowable
|
||||||
(t, Machine::ExceptionInInitializerErrorType, 0, 0, t->exception);
|
(t, Machine::ExceptionInInitializerErrorType, 0, 0, t->exception);
|
||||||
@ -3960,13 +3960,15 @@ defineClass(Thread* t, object loader, const uint8_t* buffer, unsigned length)
|
|||||||
|
|
||||||
if (c) {
|
if (c) {
|
||||||
PROTECT(t, c);
|
PROTECT(t, c);
|
||||||
if (getClassLoaderMap(t, loader) == 0) {
|
ACQUIRE(t, t->m->classLock);
|
||||||
|
|
||||||
|
if (classLoaderMap(t, loader) == 0) {
|
||||||
object map = makeHashMap(t, 0, 0);
|
object map = makeHashMap(t, 0, 0);
|
||||||
set(t, loader, ClassLoaderMap, map);
|
set(t, loader, ClassLoaderMap, map);
|
||||||
}
|
}
|
||||||
|
|
||||||
hashMapInsert(t, getClassLoaderMap(t, loader), className(t, c), c,
|
hashMapInsert
|
||||||
byteArrayHash);
|
(t, classLoaderMap(t, loader), className(t, c), c, byteArrayHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
|
@ -1188,9 +1188,9 @@ class Machine {
|
|||||||
enum Root {
|
enum Root {
|
||||||
BootLoader,
|
BootLoader,
|
||||||
AppLoader,
|
AppLoader,
|
||||||
ClassMap,
|
|
||||||
LoadClassMethod,
|
|
||||||
BootstrapClassMap,
|
BootstrapClassMap,
|
||||||
|
FindLoadedClassMethod,
|
||||||
|
LoadClassMethod,
|
||||||
MonitorMap,
|
MonitorMap,
|
||||||
StringMap,
|
StringMap,
|
||||||
ByteArrayMap,
|
ByteArrayMap,
|
||||||
@ -1777,28 +1777,6 @@ setType(Thread* t, Machine::Type type, object value)
|
|||||||
set(t, t->m->types, ArrayBody + (type * BytesPerWord), value);
|
set(t, t->m->types, ArrayBody + (type * BytesPerWord), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline object
|
|
||||||
getClassLoaderMap(Thread* t, object loader)
|
|
||||||
{
|
|
||||||
if (loader == root(t, Machine::BootLoader)) {
|
|
||||||
return root(t, Machine::ClassMap);
|
|
||||||
} else {
|
|
||||||
return classLoaderMap(t, loader);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Finder*
|
|
||||||
getFinder(Thread* t, object loader)
|
|
||||||
{
|
|
||||||
if (loader == root(t, Machine::BootLoader)) {
|
|
||||||
return t->m->bootFinder;
|
|
||||||
} else if (loader == root(t, Machine::AppLoader)) {
|
|
||||||
return t->m->appFinder;
|
|
||||||
} else {
|
|
||||||
abort(t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
objectFixed(Thread*, object o)
|
objectFixed(Thread*, object o)
|
||||||
{
|
{
|
||||||
|
@ -22,7 +22,8 @@
|
|||||||
(type classLoader java/lang/ClassLoader
|
(type classLoader java/lang/ClassLoader
|
||||||
(object map))
|
(object map))
|
||||||
|
|
||||||
(type systemClassLoader avian/SystemClassLoader)
|
(type systemClassLoader avian/SystemClassLoader
|
||||||
|
(void* finder))
|
||||||
|
|
||||||
(type field avian/VMField)
|
(type field avian/VMField)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user