--- old/src/java.base/share/native/libjli/java.c 2016-04-26 18:16:18.614107571 +0900 +++ new/src/java.base/share/native/libjli/java.c 2016-04-26 18:16:18.346822492 +0900 @@ -125,6 +125,8 @@ static void PrintUsage(JNIEnv* env, jboolean doXUsage); static void ShowSettings(JNIEnv* env, char *optString); static void ListModules(JNIEnv* env, char *optString); +static void SetNativeThreadName(JNIEnv* env, char *name); +static void DispatchUncaughtException(JNIEnv* env, jthrowable throwable); static void SetPaths(int argc, char **argv); @@ -326,6 +328,19 @@ */ #define LEAVE() \ do { \ + jthrowable orig_throwable = (*env)->ExceptionOccurred(env); \ + if (orig_throwable != NULL) { \ + DispatchUncaughtException(env, orig_throwable); \ + if ((*env)->ExceptionOccurred(env)) { \ + JLI_ReportErrorMessage(EXCEPTION_ERROR); \ + JLI_ReportExceptionDescription(env); \ + } \ + } \ + SetNativeThreadName(env, "DestroyJavaVM"); \ + if ((*env)->ExceptionOccurred(env)) { \ + /* Clear non critical pending exceptions at this point. */ \ + (*env)->ExceptionClear(env); \ + } \ if ((*vm)->DetachCurrentThread(vm) != JNI_OK) { \ JLI_ReportErrorMessage(JVM_ERROR2); \ ret = 1; \ @@ -386,6 +401,12 @@ exit(1); } + SetNativeThreadName(env, "main"); + if ((*env)->ExceptionOccurred(env)) { + /* Clear non critical pending exceptions at this point. */ + (*env)->ExceptionClear(env); + } + if (showSettings != NULL) { ShowSettings(env, showSettings); CHECK_EXCEPTION_LEAVE(1); @@ -1686,6 +1707,60 @@ joptString); } +/** + * Set native thread name if possible. + */ +static void +SetNativeThreadName(JNIEnv *env, char *name) +{ + jmethodID currentThreadID, setNativeNameID; + jobject currentThread; + jstring nameString; + jclass cls; + + NULL_CHECK_WITHOUT_EXCEPTION_CHECK(cls = FindBootStrapClass( + env, "java/lang/Thread")); + NULL_CHECK_WITHOUT_EXCEPTION_CHECK( + currentThreadID = (*env)->GetStaticMethodID(env, cls, + "currentThread", "()Ljava/lang/Thread;")); + NULL_CHECK_WITHOUT_EXCEPTION_CHECK( + currentThread = (*env)->CallStaticObjectMethod( + env, cls, currentThreadID)); + NULL_CHECK_WITHOUT_EXCEPTION_CHECK( + setNativeNameID = (*env)->GetMethodID(env, cls, + "setNativeName", "(Ljava/lang/String;Z)V")); + NULL_CHECK_WITHOUT_EXCEPTION_CHECK( + nameString = (*env)->NewStringUTF(env, name)); + (*env)->CallVoidMethod(env, currentThread, setNativeNameID, + nameString, JNI_TRUE); +} + +/** + * Dispatch uncaught exception in main thread. + */ +static void DispatchUncaughtException(JNIEnv* env, jthrowable throwable) +{ + jmethodID currentThreadID, dispatchUncaughtExceptionID; + jobject currentThread; + jclass cls; + + (*env)->ExceptionClear(env); + + NULL_CHECK_WITHOUT_EXCEPTION_CHECK(cls = FindBootStrapClass( + env, "java/lang/Thread")); + NULL_CHECK_WITHOUT_EXCEPTION_CHECK( + currentThreadID = (*env)->GetStaticMethodID(env, cls, + "currentThread", "()Ljava/lang/Thread;")); + NULL_CHECK_WITHOUT_EXCEPTION_CHECK( + currentThread = (*env)->CallStaticObjectMethod( + env, cls, currentThreadID)); + NULL_CHECK_WITHOUT_EXCEPTION_CHECK( + dispatchUncaughtExceptionID = (*env)->GetMethodID(env, cls, + "dispatchUncaughtException", "(Ljava/lang/Throwable;)V")); + (*env)->CallVoidMethod(env, currentThread, + dispatchUncaughtExceptionID, throwable); +} + /* * Prints default usage or the Xusage message, see sun.launcher.LauncherHelper.java */