static void wrapClassNotFoundException(Env* env, const char* className) { Object* exception = rvmExceptionOccurred(env); if (exception && exception->clazz == java_lang_ClassNotFoundException) { // If ClassNotFoundException is thrown we have to wrap it in a NoClassDefFoundError exception = rvmExceptionClear(env); Method* constructor = rvmGetInstanceMethod(env, java_lang_NoClassDefFoundError, "<init>", "(Ljava/lang/String;)V"); if (!constructor) return; Object* message = rvmNewStringUTF(env, className, -1); if (!message) return; Object* wrappedException = rvmNewObject(env, java_lang_NoClassDefFoundError, constructor, message); if (!wrappedException) return; Class* java_lang_StackTraceElement = rvmFindClassUsingLoader(env, "java/lang/StackTraceElement", NULL); if (!java_lang_StackTraceElement) return; ObjectArray* stackTrace = rvmNewObjectArray(env, 0, java_lang_StackTraceElement, NULL, NULL); if (!stackTrace) return; Method* setStackTrace = rvmGetInstanceMethod(env, java_lang_Throwable, "setStackTrace", "([Ljava/lang/StackTraceElement;)V"); if (!setStackTrace) return; rvmCallVoidInstanceMethod(env, wrappedException, setStackTrace, stackTrace); if (rvmExceptionCheck(env)) return; Method* initCause = rvmGetInstanceMethod(env, java_lang_NoClassDefFoundError, "initCause", "(Ljava/lang/Throwable;)Ljava/lang/Throwable;"); if (!initCause) return; rvmCallObjectInstanceMethod(env, wrappedException, initCause, exception); if (!rvmExceptionCheck(env)) rvmThrow(env, wrappedException); } }
static void threadExitUncaughtException(Env* env, Thread* thread) { Object* throwable = rvmExceptionClear(env); Object* handler = rvmCallObjectInstanceMethod(env, (Object*) thread->threadObj, getUncaughtExceptionHandlerMethod); // Ignore exception thrown by getUncaughtException() rvmExceptionClear(env); if (!handler) { handler = thread->threadObj->group; } if (handler) { rvmCallVoidInstanceMethod(env, handler, uncaughtExceptionMethod, (Object*) thread->threadObj, throwable); } else { rvmPrintStackTrace(env, throwable); } // Ignore exception thrown by uncaughtException() or rvmPrintStackTrace() rvmExceptionClear(env); }
static jint detachThread(Env* env, jboolean ignoreAttachCount) { env->attachCount--; if (!ignoreAttachCount && env->attachCount > 0) { return JNI_OK; } if (env->gatewayFrames) { rvmAbort("Cannot detach thread when there are non native frames on the call stack"); } // TODO: Release all monitors still held by this thread (should only be monitors acquired from JNI code) Thread* thread = env->currentThread; if (rvmExceptionOccurred(env)) { threadExitUncaughtException(env, thread); } if (thread->threadObj->group) { rvmCallVoidInstanceMethod(env, thread->threadObj->group, removeThreadMethod, thread->threadObj); rvmExceptionClear(env); } // Set threadPtr to null rvmAtomicStoreLong(&thread->threadObj->threadPtr, 0); // Notify anyone waiting on this thread (using Thread.join()) rvmLockObject(env, thread->threadObj->lock); rvmObjectNotifyAll(env, thread->threadObj->lock); rvmUnlockObject(env, thread->threadObj->lock); rvmLockThreadsList(); thread->status = THREAD_ZOMBIE; DL_DELETE(threads, thread); pthread_cond_broadcast(&threadsChangedCond); rvmTearDownSignals(env); env->currentThread = NULL; pthread_setspecific(tlsEnvKey, NULL); rvmUnlockThreadsList(); return JNI_OK; }