--- old/src/java.base/share/classes/java/lang/Thread.java 2016-04-23 21:12:28.033228500 +0900 +++ new/src/java.base/share/classes/java/lang/Thread.java 2016-04-23 21:12:27.427228500 +0900 @@ -1226,7 +1226,8 @@ this.name = name; if (threadStatus != 0) { - setNativeName(name); + // Don't modify JNI-attached threads + setNativeName(name, false); } } @@ -2142,5 +2143,8 @@ private native void suspend0(); private native void resume0(); private native void interrupt0(); - private native void setNativeName(String name); + + // May be called directly via JNI or reflection (when permitted) to + // allow JNI-attached threads to set their native name + private native void setNativeName(String name, boolean allowAttachedThread); } --- old/src/java.base/share/native/include/jvm.h 2016-04-23 21:12:28.527228500 +0900 +++ new/src/java.base/share/native/include/jvm.h 2016-04-23 21:12:28.369228500 +0900 @@ -248,7 +248,7 @@ JVM_GetAllThreads(JNIEnv *env, jclass dummy); JNIEXPORT void JNICALL -JVM_SetNativeThreadName(JNIEnv *env, jobject jthread, jstring name); +JVM_SetNativeThreadName(JNIEnv *env, jobject jthread, jstring name, jboolean allowAttachedThread); /* getStackTrace() and getAllStackTraces() method */ JNIEXPORT jobjectArray JNICALL --- old/src/java.base/share/native/libjava/Thread.c 2016-04-23 21:12:28.838228500 +0900 +++ new/src/java.base/share/native/libjava/Thread.c 2016-04-23 21:12:28.733228500 +0900 @@ -56,7 +56,7 @@ {"holdsLock", "(" OBJ ")Z", (void *)&JVM_HoldsLock}, {"getThreads", "()[" THD, (void *)&JVM_GetAllThreads}, {"dumpThreads", "([" THD ")[[" STE, (void *)&JVM_DumpThreads}, - {"setNativeName", "(" STR ")V", (void *)&JVM_SetNativeThreadName}, + {"setNativeName", "(" STR "Z)V", (void *)&JVM_SetNativeThreadName}, }; #undef THD --- old/src/java.base/share/native/libjli/java.c 2016-04-23 21:12:29.145228500 +0900 +++ new/src/java.base/share/native/libjli/java.c 2016-04-23 21:12:29.050228500 +0900 @@ -125,6 +125,7 @@ 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 SetPaths(int argc, char **argv); @@ -325,6 +326,11 @@ * mainThread.isAlive() to work as expected. */ #define LEAVE() \ + SetNativeThreadName(env, "DestroyJavaVM"); \ + if ((*env)->ExceptionOccurred(env)) { \ + /* Clear non critical pending exceptions at this point. */ \ + (*env)->ExceptionClear(env); \ + } \ do { \ if ((*vm)->DetachCurrentThread(vm) != JNI_OK) { \ JLI_ReportErrorMessage(JVM_ERROR2); \ @@ -386,6 +392,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 +1698,29 @@ 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(cls = FindBootStrapClass(env, "java/lang/Thread")); + NULL_CHECK(currentThreadID = (*env)->GetStaticMethodID(env, cls, + "currentThread", "()Ljava/lang/Thread;")); + NULL_CHECK(currentThread = (*env)->CallStaticObjectMethod(env, cls, + currentThreadID)); + NULL_CHECK(setNativeNameID = (*env)->GetMethodID(env, cls, + "setNativeName", "(Ljava/lang/String;Z)V")); + NULL_CHECK(nameString = (*env)->NewStringUTF(env, name)); + (*env)->CallVoidMethod(env, currentThread, setNativeNameID, + nameString, JNI_TRUE); +} + /* * Prints default usage or the Xusage message, see sun.launcher.LauncherHelper.java */