Java Thread

Java除了可以通过实现java.lang.Runnable接口创建线程,还可以继承java.lang.Thread类。和实现java.lang.Runnable接口创建线程需要实现run方法一样,通过继承java.lang.Thread类来创建线程也需要重写run方法。

官方的一个例子:

class PrimeThread extends Thread {

long minPrime;

PrimeThread(long minPrime) {

this.minPrime = minPrime;

}

 

public void run() {

// compute primes larger than minPrime

. . .

}

}

启动这个线程也很简单:

Thread t = new PrimeThread();

t.start();

Threadjava.lang.Thread)在jdk\src\share\classes\java\lang目录下。提供了很多和线程相关的方法,其中有部分方法是本地方法,本地方法部分实现Thread.cjdk\src\share\native\java\lang目录下。

 

方法

Threadjava.lang.Thread)提供了很多和线程相关的方法。runstart方法是经常用到的方法,run方法用于实现一个线程运行的具体逻辑,start用于启动一个线程,其他常用的方法如currentThreadyieldsleepexitstopinterruptinterruptedisInterrupteddestroyisAlivesuspendresumesetPrioritygetPriorityjoinsetDaemonisDaemon,不过有些方法已经被@Deprecated掉了,不建议使用这些@Deprecated掉了的方法。

 

普通方法

nextThreadNum

nextThreadID

blockedOn

sleep

init

init

clone

start

run

exit

stop

stop

stop1

interrupt

interrupted

isInterrupted

destroy

suspend

resume

setPriority

getPriority

setName

getName

getThreadGroup

activeCount

enumerate

join

join

join

dumpStack

setDaemon

isDaemon

checkAccess

toString

getContextClassLoader

setContextClassLoader

getStackTrace

getAllStackTraces

isCCLOverridden

auditSubclass

getId

getState

setDefaultUncaughtExceptionHandler

getDefaultUncaughtExceptionHandler

getUncaughtExceptionHandler

setUncaughtExceptionHandler

dispatchUncaughtException

 

 

 

 

 

本地方法

一般来说,本地方法实现采用jni方式,比如registerNatives方法,在Java中,在jdk\src\share\classes\java\lang目录下,声明如下:

/* Make sure registerNatives is the first thing <clinit> does. */

private static native void registerNatives();

在实现Thread.c中,在jdk\src\share\native\java\lang目录下,有类似实现:

JNIEXPORT void JNICALL

Java_java_lang_Thread_registerNatives(JNIEnv *env, jclass cls)

{

    (*env)->RegisterNatives(env, cls, methods, ARRAY_LENGTH(methods));

}

Thread,除了registerNatives方法,其他本地方法有些不一样,其他本地方法都是通过registerNatives方法进行注册。

registerNatives

currentThread

yield

sleep

start0

isInterrupted

isAlive

countStackFrames

holdsLock

dumpThreads

getThreads

setPriority0

stop0

suspend0

resume0

interrupt0

 

本地方法解释

registerNatives

Java中的声明如下:

/* Make sure registerNatives is the first thing <clinit> does. */

private static native void registerNatives();

实际的实现:

JNIEXPORT void JNICALL

Java_java_lang_Thread_registerNatives(JNIEnv *env, jclass cls)

{

    (*env)->RegisterNatives(env, cls, methods, ARRAY_LENGTH(methods));

}

这里通过jni的方式对其他的本地方法进行了注册

static JNINativeMethod methods[] = {

    {"start0",           "()V",        (void *)&JVM_StartThread},

    {"stop0",            "(" OBJ ")V", (void *)&JVM_StopThread},

    {"isAlive",          "()Z",        (void *)&JVM_IsThreadAlive},

    {"suspend0",         "()V",        (void *)&JVM_SuspendThread},

    {"resume0",          "()V",        (void *)&JVM_ResumeThread},

    {"setPriority0",     "(I)V",       (void *)&JVM_SetThreadPriority},

    {"yield",            "()V",        (void *)&JVM_Yield},

    {"sleep",            "(J)V",       (void *)&JVM_Sleep},

    {"currentThread",    "()" THD,     (void *)&JVM_CurrentThread},

    {"countStackFrames", "()I",        (void *)&JVM_CountStackFrames},

    {"interrupt0",       "()V",        (void *)&JVM_Interrupt},

    {"isInterrupted",    "(Z)Z",       (void *)&JVM_IsInterrupted},

    {"holdsLock",        "(" OBJ ")Z", (void *)&JVM_HoldsLock},

    {"getThreads",        "()[" THD,   (void *)&JVM_GetAllThreads},

    {"dumpThreads",      "([" THD ")[[" STE, (void *)&JVM_DumpThreads},

};

 

currentThread

Java中的声明如下:

public static native Thread currentThread();

从上面的本地方法注册可以看出,对应的实现为:

JVM_CurrentThread

具体的实现在\hotspot\src\share\vm\prims目录下的jvm.cpp。实现如下:

JVM_ENTRY(jobject, JVM_CurrentThread(JNIEnv* env, jclass threadClass))

  JVMWrapper("JVM_CurrentThread");

  oop jthread = thread->threadObj();

  assert (thread != NULL, "no current thread!");

  return JNIHandles::make_local(env, jthread);

JVM_END

 

yield

Java中的声明如下:

public static native void yield();

从上面的本地方法注册可以看出,对应的实现为:

JVM_Yield

具体的实现在\hotspot\src\share\vm\prims目录下的jvm.cpp。实现如下:

JVM_ENTRY(void, JVM_Yield(JNIEnv *env, jclass threadClass))

  JVMWrapper("JVM_Yield");

  if (os::dont_yield()) return;

#ifndef USDT2

  HS_DTRACE_PROBE0(hotspot, thread__yield);

#else /* USDT2 */

  HOTSPOT_THREAD_YIELD();

#endif /* USDT2 */

  // When ConvertYieldToSleep is off (default), this matches the classic VM use of yield.

  // Critical for similar threading behaviour

  if (ConvertYieldToSleep) {

    os::sleep(thread, MinSleepInterval, false);

  } else {

    os::yield();

  }

JVM_END

 

sleep

Java中的声明如下:

public static native void sleep(long millis) throws InterruptedException;

从上面的本地方法注册可以看出,对应的实现为:

JVM_Sleep

具体的实现在\hotspot\src\share\vm\prims目录下的jvm.cpp。实现如下:

JVM_ENTRY(void, JVM_Sleep(JNIEnv* env, jclass threadClass, jlong millis))

  JVMWrapper("JVM_Sleep");

 

  if (millis < 0) {

    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative");

  }

 

  if (Thread::is_interrupted (THREAD, true) && !HAS_PENDING_EXCEPTION) {

    THROW_MSG(vmSymbols::java_lang_InterruptedException(), "sleep interrupted");

  }

 

  // Save current thread state and restore it at the end of this block.

  // And set new thread state to SLEEPING.

  JavaThreadSleepState jtss(thread);

 

#ifndef USDT2

  HS_DTRACE_PROBE1(hotspot, thread__sleep__begin, millis);

#else /* USDT2 */

  HOTSPOT_THREAD_SLEEP_BEGIN(

                             millis);

#endif /* USDT2 */

 

  if (millis == 0) {

    // When ConvertSleepToYield is on, this matches the classic VM implementation of

    // JVM_Sleep. Critical for similar threading behaviour (Win32)

    // It appears that in certain GUI contexts, it may be beneficial to do a short sleep

    // for SOLARIS

    if (ConvertSleepToYield) {

      os::yield();

    } else {

      ThreadState old_state = thread->osthread()->get_state();

      thread->osthread()->set_state(SLEEPING);

      os::sleep(thread, MinSleepInterval, false);

      thread->osthread()->set_state(old_state);

    }

  } else {

    ThreadState old_state = thread->osthread()->get_state();

    thread->osthread()->set_state(SLEEPING);

    if (os::sleep(thread, millis, true) == OS_INTRPT) {

      // An asynchronous exception (e.g., ThreadDeathException) could have been thrown on

      // us while we were sleeping. We do not overwrite those.

      if (!HAS_PENDING_EXCEPTION) {

#ifndef USDT2

        HS_DTRACE_PROBE1(hotspot, thread__sleep__end,1);

#else /* USDT2 */

        HOTSPOT_THREAD_SLEEP_END(

                                 1);

#endif /* USDT2 */

        // TODO-FIXME: THROW_MSG returns which means we will not call set_state()

        // to properly restore the thread state.  That's likely wrong.

        THROW_MSG(vmSymbols::java_lang_InterruptedException(), "sleep interrupted");

      }

    }

    thread->osthread()->set_state(old_state);

  }

#ifndef USDT2

  HS_DTRACE_PROBE1(hotspot, thread__sleep__end,0);

#else /* USDT2 */

  HOTSPOT_THREAD_SLEEP_END(

                           0);

#endif /* USDT2 */

JVM_END

 

start0

Java中的声明如下:

private native void start0();

从上面的本地方法注册可以看出,对应的实现为:

JVM_StartThread

具体的实现在\hotspot\src\share\vm\prims目录下的jvm.cpp。实现如下:

JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread))

  JVMWrapper("JVM_StartThread");

  JavaThread *native_thread = NULL;

 

  // We cannot hold the Threads_lock when we throw an exception,

  // due to rank ordering issues. Example:  we might need to grab the

  // Heap_lock while we construct the exception.

  bool throw_illegal_thread_state = false;

 

  // We must release the Threads_lock before we can post a jvmti event

  // in Thread::start.

  {

    // Ensure that the C++ Thread and OSThread structures aren't freed before

    // we operate.

    MutexLocker mu(Threads_lock);

 

    // Since JDK 5 the java.lang.Thread threadStatus is used to prevent

    // re-starting an already started thread, so we should usually find

    // that the JavaThread is null. However for a JNI attached thread

    // there is a small window between the Thread object being created

    // (with its JavaThread set) and the update to its threadStatus, so we

    // have to check for this

    if (java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread)) != NULL) {

      throw_illegal_thread_state = true;

    } else {

      // We could also check the stillborn flag to see if this thread was already stopped, but

      // for historical reasons we let the thread detect that itself when it starts running

 

      jlong size =

             java_lang_Thread::stackSize(JNIHandles::resolve_non_null(jthread));

      // Allocate the C++ Thread structure and create the native thread.  The

      // stack size retrieved from java is signed, but the constructor takes

      // size_t (an unsigned type), so avoid passing negative values which would

      // result in really large stacks.

      size_t sz = size > 0 ? (size_t) size : 0;

      native_thread = new JavaThread(&thread_entry, sz);

 

      // At this point it may be possible that no osthread was created for the

      // JavaThread due to lack of memory. Check for this situation and throw

      // an exception if necessary. Eventually we may want to change this so

      // that we only grab the lock if the thread was created successfully -

      // then we can also do this check and throw the exception in the

      // JavaThread constructor.

      if (native_thread->osthread() != NULL) {

        // Note: the current thread is not being used within "prepare".

        native_thread->prepare(jthread);

      }

    }

  }

 

  if (throw_illegal_thread_state) {

    THROW(vmSymbols::java_lang_IllegalThreadStateException());

  }

 

  assert(native_thread != NULL, "Starting null thread?");

 

  if (native_thread->osthread() == NULL) {

    // No one should hold a reference to the 'native_thread'.

    delete native_thread;

    if (JvmtiExport::should_post_resource_exhausted()) {

      JvmtiExport::post_resource_exhausted(

        JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR | JVMTI_RESOURCE_EXHAUSTED_THREADS,

        "unable to create new native thread");

    }

    THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(),

              "unable to create new native thread");

  }

 

  Thread::start(native_thread);

 

JVM_END

 

isInterrupted

Java中的声明如下:

private native boolean isInterrupted(boolean ClearInterrupted);

从上面的本地方法注册可以看出,对应的实现为:

JVM_IsInterrupted

具体的实现在\hotspot\src\share\vm\prims目录下的jvm.cpp。实现如下:

JVM_QUICK_ENTRY(jboolean, JVM_IsInterrupted(JNIEnv* env, jobject jthread, jboolean clear_interrupted))

  JVMWrapper("JVM_IsInterrupted");

 

  // Ensure that the C++ Thread and OSThread structures aren't freed before we operate

  oop java_thread = JNIHandles::resolve_non_null(jthread);

  MutexLockerEx ml(thread->threadObj() == java_thread ? NULL : Threads_lock);

  // We need to re-resolve the java_thread, since a GC might have happened during the

  // acquire of the lock

  JavaThread* thr = java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread));

  if (thr == NULL) {

    return JNI_FALSE;

  } else {

    return (jboolean) Thread::is_interrupted(thr, clear_interrupted != 0);

  }

JVM_END

 

isAlive

Java中的声明如下:

public final native boolean isAlive();

从上面的本地方法注册可以看出,对应的实现为:

JVM_IsThreadAlive

具体的实现在\hotspot\src\share\vm\prims目录下的jvm.cpp。实现如下:

JVM_ENTRY(jboolean, JVM_IsThreadAlive(JNIEnv* env, jobject jthread))

  JVMWrapper("JVM_IsThreadAlive");

 

  oop thread_oop = JNIHandles::resolve_non_null(jthread);

  return java_lang_Thread::is_alive(thread_oop);

JVM_END

 

countStackFrames

Java中的声明如下:

@Deprecated

public native int countStackFrames();

从上面的本地方法注册可以看出,对应的实现为:

JVM_CountStackFrames

具体的实现在\hotspot\src\share\vm\prims目录下的jvm.cpp。实现如下:

JVM_ENTRY(jint, JVM_CountStackFrames(JNIEnv* env, jobject jthread))

  JVMWrapper("JVM_CountStackFrames");

 

  // Ensure that the C++ Thread and OSThread structures aren't freed before we operate

  oop java_thread = JNIHandles::resolve_non_null(jthread);

  bool throw_illegal_thread_state = false;

  int count = 0;

 

  {

    MutexLockerEx ml(thread->threadObj() == java_thread ? NULL : Threads_lock);

    // We need to re-resolve the java_thread, since a GC might have happened during the

    // acquire of the lock

    JavaThread* thr = java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread));

 

    if (thr == NULL) {

      // do nothing

    } else if(! thr->is_external_suspend() || ! thr->frame_anchor()->walkable()) {

      // Check whether this java thread has been suspended already. If not, throws

      // IllegalThreadStateException. We defer to throw that exception until

      // Threads_lock is released since loading exception class has to leave VM.

      // The correct way to test a thread is actually suspended is

      // wait_for_ext_suspend_completion(), but we can't call that while holding

      // the Threads_lock. The above tests are sufficient for our purposes

      // provided the walkability of the stack is stable - which it isn't

      // 100% but close enough for most practical purposes.

      throw_illegal_thread_state = true;

    } else {

      // Count all java activation, i.e., number of vframes

      for(vframeStream vfst(thr); !vfst.at_end(); vfst.next()) {

        // Native frames are not counted

        if (!vfst.method()->is_native()) count++;

       }

    }

  }

 

  if (throw_illegal_thread_state) {

    THROW_MSG_0(vmSymbols::java_lang_IllegalThreadStateException(),

                "this thread is not suspended");

  }

  return count;

JVM_END

 

holdsLock

Java中的声明如下:

public static native boolean holdsLock(Object obj);

从上面的本地方法注册可以看出,对应的实现为:

JVM_HoldsLock

具体的实现在\hotspot\src\share\vm\prims目录下的jvm.cpp。实现如下:

JVM_ENTRY(jboolean, JVM_HoldsLock(JNIEnv* env, jclass threadClass, jobject obj))

  JVMWrapper("JVM_HoldsLock");

  assert(THREAD->is_Java_thread(), "sanity check");

  if (obj == NULL) {

    THROW_(vmSymbols::java_lang_NullPointerException(), JNI_FALSE);

  }

  Handle h_obj(THREAD, JNIHandles::resolve(obj));

  return ObjectSynchronizer::current_thread_holds_lock((JavaThread*)THREAD, h_obj);

JVM_END

 

dumpThreads

Java中的声明如下:

private native static StackTraceElement[][] dumpThreads(Thread[] threads);

从上面的本地方法注册可以看出,对应的实现为:

JVM_DumpThreads

具体的实现在\hotspot\src\share\vm\prims目录下的jvm.cpp。实现如下:

JVM_ENTRY(jobjectArray, JVM_DumpThreads(JNIEnv *env, jclass threadClass, jobjectArray threads))

  JVMWrapper("JVM_DumpThreads");

  JvmtiVMObjectAllocEventCollector oam;

 

  // Check if threads is null

  if (threads == NULL) {

    THROW_(vmSymbols::java_lang_NullPointerException(), 0);

  }

 

  objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(threads));

  objArrayHandle ah(THREAD, a);

  int num_threads = ah->length();

  // check if threads is non-empty array

  if (num_threads == 0) {

    THROW_(vmSymbols::java_lang_IllegalArgumentException(), 0);

  }

 

  // check if threads is not an array of objects of Thread class

  klassOop k = objArrayKlass::cast(ah->klass())->element_klass();

  if (k != SystemDictionary::Thread_klass()) {

    THROW_(vmSymbols::java_lang_IllegalArgumentException(), 0);

  }

 

  ResourceMark rm(THREAD);

 

  GrowableArray<instanceHandle>* thread_handle_array = new GrowableArray<instanceHandle>(num_threads);

  for (int i = 0; i < num_threads; i++) {

    oop thread_obj = ah->obj_at(i);

    instanceHandle h(THREAD, (instanceOop) thread_obj);

    thread_handle_array->append(h);

  }

 

  Handle stacktraces = ThreadService::dump_stack_traces(thread_handle_array, num_threads, CHECK_NULL);

  return (jobjectArray)JNIHandles::make_local(env, stacktraces());

 

JVM_END

 

getThreads

Java中的声明如下:

private native static Thread[] getThreads();

从上面的本地方法注册可以看出,对应的实现为:

JVM_GetAllThreads

具体的实现在\hotspot\src\share\vm\prims目录下的jvm.cpp。实现如下:

JVM_ENTRY(jobjectArray, JVM_GetAllThreads(JNIEnv *env, jclass dummy))

  ResourceMark rm(THREAD);

  ThreadsListEnumerator tle(THREAD, false, false);

  JvmtiVMObjectAllocEventCollector oam;

 

  int num_threads = tle.num_threads();

  objArrayOop r = oopFactory::new_objArray(SystemDictionary::Thread_klass(), num_threads, CHECK_NULL);

  objArrayHandle threads_ah(THREAD, r);

 

  for (int i = 0; i < num_threads; i++) {

    Handle h = tle.get_threadObj(i);

    threads_ah->obj_at_put(i, h());

  }

 

  return (jobjectArray) JNIHandles::make_local(env, threads_ah());

JVM_END

 

setPriority0

Java中的声明如下:

private native void setPriority0(int newPriority);

从上面的本地方法注册可以看出,对应的实现为:

JVM_SetThreadPriority

具体的实现在\hotspot\src\share\vm\prims目录下的jvm.cpp。实现如下:

JVM_ENTRY(void, JVM_SetThreadPriority(JNIEnv* env, jobject jthread, jint prio))

  JVMWrapper("JVM_SetThreadPriority");

  // Ensure that the C++ Thread and OSThread structures aren't freed before we operate

  MutexLocker ml(Threads_lock);

  oop java_thread = JNIHandles::resolve_non_null(jthread);

  java_lang_Thread::set_priority(java_thread, (ThreadPriority)prio);

  JavaThread* thr = java_lang_Thread::thread(java_thread);

  if (thr != NULL) {                  // Thread not yet started; priority pushed down when it is

    Thread::set_priority(thr, (ThreadPriority)prio);

  }

JVM_END

 

stop0

Java中的声明如下:

private native void stop0(Object o);

从上面的本地方法注册可以看出,对应的实现为:

JVM_StopThread

具体的实现在\hotspot\src\share\vm\prims目录下的jvm.cpp。实现如下:

JVM_ENTRY(void, JVM_StopThread(JNIEnv* env, jobject jthread, jobject throwable))

  JVMWrapper("JVM_StopThread");

 

  oop java_throwable = JNIHandles::resolve(throwable);

  if (java_throwable == NULL) {

    THROW(vmSymbols::java_lang_NullPointerException());

  }

  oop java_thread = JNIHandles::resolve_non_null(jthread);

  JavaThread* receiver = java_lang_Thread::thread(java_thread);

  Events::log_exception(JavaThread::current(),

                        "JVM_StopThread thread JavaThread " INTPTR_FORMAT " as oop " INTPTR_FORMAT " [exception " INTPTR_FORMAT "]",

                        receiver, (address)java_thread, throwable);

  // First check if thread is alive

  if (receiver != NULL) {

    // Check if exception is getting thrown at self (use oop equality, since the

    // target object might exit)

    if (java_thread == thread->threadObj()) {

      THROW_OOP(java_throwable);

    } else {

      // Enques a VM_Operation to stop all threads and then deliver the exception...

      Thread::send_async_exception(java_thread, JNIHandles::resolve(throwable));

    }

  }

  else {

    // Either:

    // - target thread has not been started before being stopped, or

    // - target thread already terminated

    // We could read the threadStatus to determine which case it is

    // but that is overkill as it doesn't matter. We must set the

    // stillborn flag for the first case, and if the thread has already

    // exited setting this flag has no affect

    java_lang_Thread::set_stillborn(java_thread);

  }

JVM_END

 

suspend0

Java中的声明如下:

private native void suspend0();

从上面的本地方法注册可以看出,对应的实现为:

JVM_SuspendThread

具体的实现在\hotspot\src\share\vm\prims目录下的jvm.cpp。实现如下:

JVM_ENTRY(void, JVM_SuspendThread(JNIEnv* env, jobject jthread))

  JVMWrapper("JVM_SuspendThread");

  oop java_thread = JNIHandles::resolve_non_null(jthread);

  JavaThread* receiver = java_lang_Thread::thread(java_thread);

 

  if (receiver != NULL) {

    // thread has run and has not exited (still on threads list)

 

    {

      MutexLockerEx ml(receiver->SR_lock(), Mutex::_no_safepoint_check_flag);

      if (receiver->is_external_suspend()) {

        // Don't allow nested external suspend requests. We can't return

        // an error from this interface so just ignore the problem.

        return;

      }

      if (receiver->is_exiting()) { // thread is in the process of exiting

        return;

      }

      receiver->set_external_suspend();

    }

 

    // java_suspend() will catch threads in the process of exiting

    // and will ignore them.

    receiver->java_suspend();

 

    // It would be nice to have the following assertion in all the

    // time, but it is possible for a racing resume request to have

    // resumed this thread right after we suspended it. Temporarily

    // enable this assertion if you are chasing a different kind of

    // bug.

    //

    // assert(java_lang_Thread::thread(receiver->threadObj()) == NULL ||

    //   receiver->is_being_ext_suspended(), "thread is not suspended");

  }

JVM_END

 

resume0

Java中的声明如下:

private native void resume0();

从上面的本地方法注册可以看出,对应的实现为:

JVM_ResumeThread

具体的实现在\hotspot\src\share\vm\prims目录下的jvm.cpp。实现如下:

JVM_ENTRY(void, JVM_ResumeThread(JNIEnv* env, jobject jthread))

  JVMWrapper("JVM_ResumeThread");

  // Ensure that the C++ Thread and OSThread structures aren't freed before we operate.

  // We need to *always* get the threads lock here, since this operation cannot be allowed during

  // a safepoint. The safepoint code relies on suspending a thread to examine its state. If other

  // threads randomly resumes threads, then a thread might not be suspended when the safepoint code

  // looks at it.

  MutexLocker ml(Threads_lock);

  JavaThread* thr = java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread));

  if (thr != NULL) {

    // the thread has run and is not in the process of exiting

    thr->java_resume();

  }

JVM_END

 

interrupt0

Java中的声明如下:

private native void interrupt0();

从上面的本地方法注册可以看出,对应的实现为:

JVM_Interrupt

具体的实现在\hotspot\src\share\vm\prims目录下的jvm.cpp。实现如下:

JVM_ENTRY(void, JVM_Interrupt(JNIEnv* env, jobject jthread))

  JVMWrapper("JVM_Interrupt");

 

  // Ensure that the C++ Thread and OSThread structures aren't freed before we operate

  oop java_thread = JNIHandles::resolve_non_null(jthread);

  MutexLockerEx ml(thread->threadObj() == java_thread ? NULL : Threads_lock);

  // We need to re-resolve the java_thread, since a GC might have happened during the

  // acquire of the lock

  JavaThread* thr = java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread));

  if (thr != NULL) {

    Thread::interrupt(thr);

  }

JVM_END

 

猜你喜欢

转载自lobin.iteye.com/blog/2327713