hotspot/src/share/vm/prims/jvm.cpp
// JVM_Stop is implemented using a VM_Operation, so threads are forced to safepoints
// before the quasi-asynchronous exception is delivered. This is a little obtrusive,
// but is thought to be reliable and simple. In the case, where the receiver is the
// same thread as the sender, no safepoint is needed.
JVM_ENTRY(void, JVM_StopThread(JNIEnv* env, jobject jthread, jobject throwable))
{- -------------------------------------------
(1) (トレース出力) (See: JVMWrapper)
---------------------------------------- -}
JVMWrapper("JVM_StopThread");
{- -------------------------------------------
(1) 引数が NULL だった場合は, NullPointerException
---------------------------------------- -}
oop java_throwable = JNIHandles::resolve(throwable);
if (java_throwable == NULL) {
THROW(vmSymbols::java_lang_NullPointerException());
}
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
oop java_thread = JNIHandles::resolve_non_null(jthread);
JavaThread* receiver = java_lang_Thread::thread(java_thread);
{- -------------------------------------------
(1) (デバッグ用の処理) (See: Events)
---------------------------------------- -}
Events::log("JVM_StopThread thread JavaThread " INTPTR_FORMAT " as oop " INTPTR_FORMAT " [exception " INTPTR_FORMAT "]", receiver, (address)java_thread, throwable);
{- -------------------------------------------
(1) 以下のようにして処理対象を停止させる(処理対象のスレッド内で例外を引き起こす).
* 処理対象がいない場合 (まだ開始していない or もう死んでいる)
まだ開始していないケースのために, java_lang_Thread::set_stillborn() を呼んでおく.
(これを呼ばれたスレッドは, java.lang.Thread.run() メソッドの中身を実行することなく終了する.
See: JavaThread::thread_main_inner())
(当たり前だけど, もう死んでいるケースについては何も対処することはない.)
* 処理対象が自分自身の場合
THROW_OOP() マクロで, 引数で指定された例外(java_throwable)を投げるだけ.
* 処理対象が自分以外の場合
Thread::send_async_exception() を呼んで, 対象のスレッド内に
引数で指定された例外(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
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.