From 4dc76a50a25f88bbb9681d68ad5648ccf04cf29b Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 23 Jun 2014 17:17:13 -0600 Subject: [PATCH] fix case of JNIEnv::FindClass called from JNI_OnLoad If an JNI_OnLoad implementation calls FindClass when using the OpenJDK class library, the calling method on the Java stack will be ClassLoader.loadLibrary. However, we must use the class loader of the class attempting to load the library in this case, not the system classloader. Therefore, we now maintain a stack such that the latest class to load a library in the current thread is at the top, and we use that class whenever FindClass is called by ClassLoader.loadLibrary (via JNI_OnLoad). Note that this patch does not attempt to address the same problem for the Avian or Android class libraries, but the same strategy should work for them as well. --- src/avian/machine.h | 25 ++++++++++++++++ src/avian/target-fields.h | 60 +++++++++++++++++++-------------------- src/classpath-openjdk.cpp | 3 ++ src/continuations-x86.S | 16 +++++------ src/jnienv.cpp | 18 +++++++++--- src/machine.cpp | 1 + 6 files changed, 81 insertions(+), 42 deletions(-) diff --git a/src/avian/machine.h b/src/avian/machine.h index bfa222549e..0184d08f61 100644 --- a/src/avian/machine.h +++ b/src/avian/machine.h @@ -1421,6 +1421,30 @@ class Thread { SingleProtector protector; }; + class LibraryLoadStack: public AutoResource { + public: + LibraryLoadStack(Thread* t, object class_): + AutoResource(t), + next(t->libraryLoadStack), + class_(class_), + protector(t, &(this->class_)) + { + t->libraryLoadStack = this; + } + + ~LibraryLoadStack() { + t->libraryLoadStack = next; + } + + virtual void release() { + this->LibraryLoadStack::~LibraryLoadStack(); + } + + LibraryLoadStack* next; + object class_; + SingleProtector protector; + }; + class Checkpoint { public: Checkpoint(Thread* t): @@ -1516,6 +1540,7 @@ class Thread { unsigned heapOffset; Protector* protector; ClassInitStack* classInitStack; + LibraryLoadStack* libraryLoadStack; Resource* resource; Checkpoint* checkpoint; Runnable runnable; diff --git a/src/avian/target-fields.h b/src/avian/target-fields.h index 60e4c48c49..9efc1212e8 100644 --- a/src/avian/target-fields.h +++ b/src/avian/target-fields.h @@ -16,42 +16,42 @@ # if (TARGET_BYTES_PER_WORD == 8) #define TARGET_THREAD_EXCEPTION 80 -#define TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT 2256 -#define TARGET_THREAD_EXCEPTIONOFFSET 2264 -#define TARGET_THREAD_EXCEPTIONHANDLER 2272 +#define TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT 2264 +#define TARGET_THREAD_EXCEPTIONOFFSET 2272 +#define TARGET_THREAD_EXCEPTIONHANDLER 2280 -#define TARGET_THREAD_IP 2216 -#define TARGET_THREAD_STACK 2224 -#define TARGET_THREAD_NEWSTACK 2232 -#define TARGET_THREAD_SCRATCH 2240 -#define TARGET_THREAD_CONTINUATION 2248 -#define TARGET_THREAD_TAILADDRESS 2280 -#define TARGET_THREAD_VIRTUALCALLTARGET 2288 -#define TARGET_THREAD_VIRTUALCALLINDEX 2296 -#define TARGET_THREAD_HEAPIMAGE 2304 -#define TARGET_THREAD_CODEIMAGE 2312 -#define TARGET_THREAD_THUNKTABLE 2320 -#define TARGET_THREAD_STACKLIMIT 2368 +#define TARGET_THREAD_IP 2224 +#define TARGET_THREAD_STACK 2232 +#define TARGET_THREAD_NEWSTACK 2240 +#define TARGET_THREAD_SCRATCH 2248 +#define TARGET_THREAD_CONTINUATION 2256 +#define TARGET_THREAD_TAILADDRESS 2288 +#define TARGET_THREAD_VIRTUALCALLTARGET 2296 +#define TARGET_THREAD_VIRTUALCALLINDEX 2304 +#define TARGET_THREAD_HEAPIMAGE 2312 +#define TARGET_THREAD_CODEIMAGE 2320 +#define TARGET_THREAD_THUNKTABLE 2328 +#define TARGET_THREAD_STACKLIMIT 2376 # elif (TARGET_BYTES_PER_WORD == 4) #define TARGET_THREAD_EXCEPTION 44 -#define TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT 2164 -#define TARGET_THREAD_EXCEPTIONOFFSET 2168 -#define TARGET_THREAD_EXCEPTIONHANDLER 2172 +#define TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT 2168 +#define TARGET_THREAD_EXCEPTIONOFFSET 2172 +#define TARGET_THREAD_EXCEPTIONHANDLER 2176 -#define TARGET_THREAD_IP 2144 -#define TARGET_THREAD_STACK 2148 -#define TARGET_THREAD_NEWSTACK 2152 -#define TARGET_THREAD_SCRATCH 2156 -#define TARGET_THREAD_CONTINUATION 2160 -#define TARGET_THREAD_TAILADDRESS 2176 -#define TARGET_THREAD_VIRTUALCALLTARGET 2180 -#define TARGET_THREAD_VIRTUALCALLINDEX 2184 -#define TARGET_THREAD_HEAPIMAGE 2188 -#define TARGET_THREAD_CODEIMAGE 2192 -#define TARGET_THREAD_THUNKTABLE 2196 -#define TARGET_THREAD_STACKLIMIT 2220 +#define TARGET_THREAD_IP 2148 +#define TARGET_THREAD_STACK 2152 +#define TARGET_THREAD_NEWSTACK 2156 +#define TARGET_THREAD_SCRATCH 2160 +#define TARGET_THREAD_CONTINUATION 2164 +#define TARGET_THREAD_TAILADDRESS 2180 +#define TARGET_THREAD_VIRTUALCALLTARGET 2184 +#define TARGET_THREAD_VIRTUALCALLINDEX 2188 +#define TARGET_THREAD_HEAPIMAGE 2192 +#define TARGET_THREAD_CODEIMAGE 2196 +#define TARGET_THREAD_THUNKTABLE 2200 +#define TARGET_THREAD_STACKLIMIT 2224 # else # error diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index aa65c445a1..5eb5671f17 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -1845,6 +1845,9 @@ management_JNI_OnLoad(JavaVM*, void*); void JNICALL loadLibrary(Thread* t, object, uintptr_t* arguments) { + Thread::LibraryLoadStack stack + (t, jclassVmClass(t, reinterpret_cast(arguments[0]))); + object name = reinterpret_cast(arguments[1]); THREAD_RUNTIME_ARRAY(t, char, n, stringLength(t, name) + 1); stringChars(t, name, RUNTIME_ARRAY_BODY(n)); diff --git a/src/continuations-x86.S b/src/continuations-x86.S index 071e4e7123..d088bdaf72 100644 --- a/src/continuations-x86.S +++ b/src/continuations-x86.S @@ -10,11 +10,11 @@ #ifdef __x86_64__ -#define THREAD_CONTINUATION 2248 +#define THREAD_CONTINUATION 2256 #define THREAD_EXCEPTION 80 -#define THREAD_EXCEPTION_STACK_ADJUSTMENT 2256 -#define THREAD_EXCEPTION_OFFSET 2264 -#define THREAD_EXCEPTION_HANDLER 2272 +#define THREAD_EXCEPTION_STACK_ADJUSTMENT 2264 +#define THREAD_EXCEPTION_OFFSET 2272 +#define THREAD_EXCEPTION_HANDLER 2280 #define CONTINUATION_NEXT 8 #define CONTINUATION_ADDRESS 32 @@ -91,11 +91,11 @@ LOCAL(vmInvoke_exit): #elif defined __i386__ -#define THREAD_CONTINUATION 2160 +#define THREAD_CONTINUATION 2164 #define THREAD_EXCEPTION 44 -#define THREAD_EXCEPTION_STACK_ADJUSTMENT 2164 -#define THREAD_EXCEPTION_OFFSET 2168 -#define THREAD_EXCEPTION_HANDLER 2172 +#define THREAD_EXCEPTION_STACK_ADJUSTMENT 2168 +#define THREAD_EXCEPTION_OFFSET 2172 +#define THREAD_EXCEPTION_HANDLER 2176 #define CONTINUATION_NEXT 4 #define CONTINUATION_ADDRESS 16 diff --git a/src/jnienv.cpp b/src/jnienv.cpp index be88848935..9f8e7c3fb8 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -349,10 +349,20 @@ findClass(Thread* t, uintptr_t* arguments) object caller = getCaller(t, 0); - object c = resolveClass(t, - caller ? classLoader(t, methodClass(t, caller)) - : root(t, Machine::AppLoader), - n); + object loader; + if (caller) { + if (methodClass(t, caller) == type(t, Machine::ClassLoaderType) + and t->libraryLoadStack) + { + loader = classLoader(t, t->libraryLoadStack->class_); + } else { + loader = classLoader(t, methodClass(t, caller)); + } + } else { + loader = root(t, Machine::AppLoader); + } + + object c = resolveClass(t, loader, n); if (t->m->classpath->mayInitClasses()) { PROTECT(t, c); diff --git a/src/machine.cpp b/src/machine.cpp index 93ddf5d5bc..33356f3ea5 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -3337,6 +3337,7 @@ Thread::Thread(Machine* m, object javaThread, Thread* parent): heapOffset(0), protector(0), classInitStack(0), + libraryLoadStack(0), runnable(this), defaultHeap(static_cast (m->heap->allocate(ThreadHeapSizeInBytes))),