fix various classloading deadlocks and races

This commit is contained in:
Joel Dice 2010-09-22 13:58:46 -06:00
parent efd3ccb04f
commit 89f6adc93c
7 changed files with 90 additions and 88 deletions

View File

@ -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);

View File

@ -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 {

View File

@ -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);

View File

@ -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)) {

View File

@ -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;

View File

@ -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)
{

View File

@ -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)