mirror of
https://github.com/corda/corda.git
synced 2025-01-03 19:54:13 +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);
|
||||
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);
|
||||
|
||||
|
@ -176,7 +176,7 @@ loadLibrary(Thread* t, const char* name)
|
||||
}
|
||||
|
||||
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);
|
||||
return lib;
|
||||
} else {
|
||||
|
@ -1602,6 +1602,7 @@ JVM_FindLoadedClass(Thread* t, jobject loader, jstring name)
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
object spec = makeByteArray(t, stringLength(t, *name) + 1);
|
||||
|
||||
{ char* s = reinterpret_cast<char*>(&byteArrayBody(t, spec, 0));
|
||||
stringChars(t, *name, s);
|
||||
replace('.', '/', s);
|
||||
|
@ -8226,8 +8226,8 @@ boot(MyThread* t, BootImage* image)
|
||||
|
||||
syncInstructionCache(code, image->codeSize);
|
||||
|
||||
setRoot(t, Machine::ClassMap, makeClassMap
|
||||
(t, bootClassTable, image->bootClassCount, heap));
|
||||
set(t, root(t, Machine::BootLoader), ClassLoaderMap, makeClassMap
|
||||
(t, bootClassTable, image->bootClassCount, heap));
|
||||
|
||||
set(t, root(t, Machine::AppLoader), ClassLoaderMap, makeClassMap
|
||||
(t, appClassTable, image->appClassCount, heap));
|
||||
@ -8249,7 +8249,8 @@ boot(MyThread* t, BootImage* image)
|
||||
|
||||
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);
|
||||
|
||||
setRoot(t, Machine::BootstrapClassMap, makeHashMap(t, 0, 0));
|
||||
@ -8657,6 +8658,24 @@ compile(MyThread* t, Allocator* allocator, BootContext* bootContext,
|
||||
compile(t, &context);
|
||||
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);
|
||||
|
||||
if (methodAddress(t, method) != defaultThunk(t)) {
|
||||
|
118
src/machine.cpp
118
src/machine.cpp
@ -1785,15 +1785,15 @@ makeArrayClass(Thread* t, object loader, object spec, bool throw_)
|
||||
object elementClass = hashMapFind
|
||||
(t, root(t, Machine::BootstrapClassMap), elementSpec, byteArrayHash,
|
||||
byteArrayEqual);
|
||||
|
||||
|
||||
if (elementClass == 0) {
|
||||
elementClass = resolveClass(t, loader, elementSpec, throw_);
|
||||
if (elementClass == 0) return 0;
|
||||
}
|
||||
|
||||
object class_ = hashMapFind
|
||||
(t, getClassLoaderMap(t, classLoader(t, elementClass)), spec,
|
||||
byteArrayHash, byteArrayEqual);
|
||||
PROTECT(t, elementClass);
|
||||
|
||||
object class_ = findLoadedClass(t, classLoader(t, elementClass), spec);
|
||||
|
||||
return class_ ? class_ : makeArrayClass
|
||||
(t, classLoader(t, elementClass), dimensions, spec, elementClass);
|
||||
@ -2002,12 +2002,18 @@ boot(Thread* t)
|
||||
set(t, type(t, Machine::DoubleArrayType), ClassStaticTable,
|
||||
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);
|
||||
set(t, root(t, Machine::AppLoader), ClassLoaderMap, map);
|
||||
}
|
||||
|
||||
systemClassLoaderFinder(t, root(t, Machine::AppLoader)) = m->appFinder;
|
||||
|
||||
set(t, root(t, Machine::AppLoader), ClassLoaderParent,
|
||||
root(t, Machine::BootLoader));
|
||||
|
||||
@ -3127,7 +3133,7 @@ resolveSystemClass(Thread* t, object loader, object spec, bool throw_)
|
||||
ACQUIRE(t, t->m->classLock);
|
||||
|
||||
object class_ = hashMapFind
|
||||
(t, getClassLoaderMap(t, loader), spec, byteArrayHash, byteArrayEqual);
|
||||
(t, classLoaderMap(t, loader), spec, byteArrayHash, byteArrayEqual);
|
||||
|
||||
if (class_ == 0) {
|
||||
if (classLoaderParent(t, loader)) {
|
||||
@ -3149,7 +3155,8 @@ resolveSystemClass(Thread* t, object loader, object spec, bool throw_)
|
||||
".class",
|
||||
7);
|
||||
|
||||
System::Region* region = getFinder(t, loader)->find
|
||||
System::Region* region = static_cast<Finder*>
|
||||
(systemClassLoaderFinder(t, loader))->find
|
||||
(RUNTIME_ARRAY_BODY(file));
|
||||
|
||||
if (region) {
|
||||
@ -3185,8 +3192,7 @@ resolveSystemClass(Thread* t, object loader, object spec, bool throw_)
|
||||
if (class_) {
|
||||
PROTECT(t, class_);
|
||||
|
||||
hashMapInsert
|
||||
(t, getClassLoaderMap(t, loader), spec, class_, byteArrayHash);
|
||||
hashMapInsert(t, classLoaderMap(t, loader), spec, class_, byteArrayHash);
|
||||
} else if (throw_ and t->exception == 0) {
|
||||
object message = makeString(t, "%s", &byteArrayBody(t, spec, 0));
|
||||
t->exception = t->m->classpath->makeThrowable
|
||||
@ -3200,48 +3206,34 @@ resolveSystemClass(Thread* t, object loader, object spec, bool throw_)
|
||||
object
|
||||
findLoadedClass(Thread* t, object loader, object spec)
|
||||
{
|
||||
PROTECT(t, loader);
|
||||
PROTECT(t, spec);
|
||||
|
||||
ACQUIRE(t, t->m->classLock);
|
||||
|
||||
object map = getClassLoaderMap(t, loader);
|
||||
if (map) {
|
||||
return hashMapFind(t, map, spec, byteArrayHash, byteArrayEqual);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return classLoaderMap(t, loader) ? hashMapFind
|
||||
(t, classLoaderMap(t, loader), spec, byteArrayHash, byteArrayEqual) : 0;
|
||||
}
|
||||
|
||||
object
|
||||
resolveClass(Thread* t, object loader, object spec, bool throw_)
|
||||
{
|
||||
if (loader == root(t, Machine::BootLoader)
|
||||
or loader == root(t, Machine::AppLoader))
|
||||
{
|
||||
if (objectClass(t, loader) == type(t, Machine::SystemClassLoaderType)) {
|
||||
return resolveSystemClass(t, loader, spec, throw_);
|
||||
} else {
|
||||
expect(t, throw_);
|
||||
|
||||
PROTECT(t, loader);
|
||||
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 c = findLoadedClass(t, loader, spec);
|
||||
if (c) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
object class_;
|
||||
PROTECT(t, loader);
|
||||
PROTECT(t, spec);
|
||||
|
||||
if (byteArrayBody(t, spec, 0) == '[') {
|
||||
class_ = resolveArrayClass(t, loader, spec, throw_);
|
||||
return resolveArrayClass(t, loader, spec, throw_);
|
||||
} else {
|
||||
if (root(t, Machine::LoadClassMethod) == 0) {
|
||||
object m = resolveMethod
|
||||
@ -3272,31 +3264,38 @@ resolveClass(Thread* t, object loader, object spec, bool throw_)
|
||||
replace('/', '.', RUNTIME_ARRAY_BODY(s), reinterpret_cast<char*>
|
||||
(&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)) {
|
||||
class_ = jclassVmClass(t, class_);
|
||||
if (LIKELY(c and t->exception == 0)) {
|
||||
PROTECT(t, c);
|
||||
|
||||
ACQUIRE(t, t->m->classLock);
|
||||
|
||||
if (classLoaderMap(t, loader) == 0) {
|
||||
object map = makeHashMap(t, 0, 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));
|
||||
t->exception = t->m->classpath->makeThrowable
|
||||
(t, Machine::ClassNotFoundExceptionType, message);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (class_) {
|
||||
PROTECT(t, class_);
|
||||
|
||||
ACQUIRE(t, t->m->classLock);
|
||||
|
||||
hashMapInsert(t, classLoaderMap(t, loader), spec, class_,
|
||||
byteArrayHash);
|
||||
} else if (throw_ and t->exception == 0) {
|
||||
object message = makeString(t, "%s", &byteArrayBody(t, spec, 0));
|
||||
t->exception = t->m->classpath->makeThrowable
|
||||
(t, Machine::ClassNotFoundExceptionType, message);
|
||||
}
|
||||
|
||||
return class_;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3411,6 +3410,7 @@ preInitClass(Thread* t, object c)
|
||||
if (classVmFlags(t, c) & NeedInitFlag) {
|
||||
PROTECT(t, c);
|
||||
ACQUIRE(t, t->m->classLock);
|
||||
|
||||
if (classVmFlags(t, c) & NeedInitFlag) {
|
||||
if (classVmFlags(t, c) & InitFlag) {
|
||||
// If the class is currently being initialized and this the thread
|
||||
@ -3444,8 +3444,8 @@ void
|
||||
postInitClass(Thread* t, object c)
|
||||
{
|
||||
PROTECT(t, c);
|
||||
|
||||
ACQUIRE(t, t->m->classLock);
|
||||
|
||||
if (t->exception) {
|
||||
t->exception = t->m->classpath->makeThrowable
|
||||
(t, Machine::ExceptionInInitializerErrorType, 0, 0, t->exception);
|
||||
@ -3960,13 +3960,15 @@ defineClass(Thread* t, object loader, const uint8_t* buffer, unsigned length)
|
||||
|
||||
if (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);
|
||||
set(t, loader, ClassLoaderMap, map);
|
||||
}
|
||||
|
||||
hashMapInsert(t, getClassLoaderMap(t, loader), className(t, c), c,
|
||||
byteArrayHash);
|
||||
hashMapInsert
|
||||
(t, classLoaderMap(t, loader), className(t, c), c, byteArrayHash);
|
||||
}
|
||||
|
||||
return c;
|
||||
|
@ -1188,9 +1188,9 @@ class Machine {
|
||||
enum Root {
|
||||
BootLoader,
|
||||
AppLoader,
|
||||
ClassMap,
|
||||
LoadClassMethod,
|
||||
BootstrapClassMap,
|
||||
FindLoadedClassMethod,
|
||||
LoadClassMethod,
|
||||
MonitorMap,
|
||||
StringMap,
|
||||
ByteArrayMap,
|
||||
@ -1777,28 +1777,6 @@ setType(Thread* t, Machine::Type type, object 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
|
||||
objectFixed(Thread*, object o)
|
||||
{
|
||||
|
@ -22,7 +22,8 @@
|
||||
(type classLoader java/lang/ClassLoader
|
||||
(object map))
|
||||
|
||||
(type systemClassLoader avian/SystemClassLoader)
|
||||
(type systemClassLoader avian/SystemClassLoader
|
||||
(void* finder))
|
||||
|
||||
(type field avian/VMField)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user