hotspot/src/share/vm/services/management.cpp
この関数は ThreadInfo オブジェクトの配列を返す. 各 ThreadInfo オブジェクトは, 引数の配列内に入っていた各スレッド ID に 対応するスレッドの情報を格納している.
なお, 対応するスレッドが存在しない(あるいは対応するスレッドが終了済みの)無効な ID が含まれていた場合は, それに対応する ThreadInfo オブジェクトとして null を返す.
引数の意味は以下の通り.
ids
array of thread IDs
maxDepth
the maximum depth of stack traces to be dumped: maxDepth == -1 requests to dump entire stack trace. maxDepth == 0 requests no stack trace.
infoArray
array of ThreadInfo objects
(なおコメントによると, 「この関数の返値の型はどうして void ではなく int なんだろう??」 とのこと.)
// Gets an array of ThreadInfo objects. Each element is the ThreadInfo
// for the thread ID specified in the corresponding entry in
// the given array of thread IDs; or NULL if the thread does not exist
// or has terminated.
//
// Input parameters:
// ids - array of thread IDs
// maxDepth - the maximum depth of stack traces to be dumped:
// maxDepth == -1 requests to dump entire stack trace.
// maxDepth == 0 requests no stack trace.
// infoArray - array of ThreadInfo objects
//
// QQQ - Why does this method return a value instead of void?
JVM_ENTRY(jint, jmm_GetThreadInfo(JNIEnv *env, jlongArray ids, jint maxDepth, jobjectArray infoArray))
{- -------------------------------------------
(1) もし, 配列であるべき引数が実は NULL だった場合, NullPointerException.
---------------------------------------- -}
// Check if threads is null
if (ids == NULL || infoArray == NULL) {
THROW_(vmSymbols::java_lang_NullPointerException(), -1);
}
{- -------------------------------------------
(1) 引数の maxDepth をチェックする.
値が不正(-1 未満)であれば, IllegalArgumentException.
---------------------------------------- -}
if (maxDepth < -1) {
THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
"Invalid maxDepth", -1);
}
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
ResourceMark rm(THREAD);
typeArrayOop ta = typeArrayOop(JNIHandles::resolve_non_null(ids));
typeArrayHandle ids_ah(THREAD, ta);
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
oop infoArray_obj = JNIHandles::resolve_non_null(infoArray);
objArrayOop oa = objArrayOop(infoArray_obj);
objArrayHandle infoArray_h(THREAD, oa);
{- -------------------------------------------
(1) 引数の配列(ids_ah 及び infoArray_h)をチェックする.
もし不正な値であれば IllegalArgumentException を出す.
---------------------------------------- -}
// validate the thread id array
validate_thread_id_array(ids_ah, CHECK_0);
// validate the ThreadInfo[] parameters
validate_thread_info_array(infoArray_h, CHECK_0);
{- -------------------------------------------
(1) もし引数で渡されていた配列(= 返値を入れるべき配列. 以下の ids_ah)の長さが
スレッド数と異なっていれば, IllegalArgumentException.
---------------------------------------- -}
// infoArray must be of the same length as the given array of thread IDs
int num_threads = ids_ah->length();
if (num_threads != infoArray_h->length()) {
THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
"The length of the given ThreadInfo array does not match the length of the given array of thread IDs", -1);
}
{- -------------------------------------------
(1) JDK のバージョンが 1.6 以上の場合には
java.util.concurrent.locks.AbstractOwnableSynchronizer クラスを使用するので,
もしまだロードしていなければロードしておく.
---------------------------------------- -}
if (JDK_Version::is_gte_jdk16x_version()) {
// make sure the AbstractOwnableSynchronizer klass is loaded before taking thread snapshots
java_util_concurrent_locks_AbstractOwnableSynchronizer::initialize(CHECK_0);
}
{- -------------------------------------------
(1) 引数で指定された全てのスレッドについて,
その状態を示す ThreadSnapshot オブジェクトを取得する.
(取得した結果は ThreadDumpResult オブジェクト (以下の dump_result) に格納される)
なお, 取得方法は引数に応じて 2通りある.
* 各スレッドのスタックダンプは不要な場合:
ThreadSnapshot::ThreadSnapshot() で取得.
* 各スレッドのスタックダンプまで必要な場合:
do_thread_dump() で取得.
---------------------------------------- -}
// Must use ThreadDumpResult to store the ThreadSnapshot.
// GC may occur after the thread snapshots are taken but before
// this function returns. The threadObj and other oops kept
// in the ThreadSnapshot are marked and adjusted during GC.
ThreadDumpResult dump_result(num_threads);
if (maxDepth == 0) {
// no stack trace dumped - do not need to stop the world
{
MutexLockerEx ml(Threads_lock);
for (int i = 0; i < num_threads; i++) {
jlong tid = ids_ah->long_at(i);
JavaThread* jt = find_java_thread_from_id(tid);
ThreadSnapshot* ts;
if (jt == NULL) {
// if the thread does not exist or now it is terminated,
// create dummy snapshot
ts = new ThreadSnapshot();
} else {
ts = new ThreadSnapshot(jt);
}
dump_result.add_thread_snapshot(ts);
}
}
} else {
// obtain thread dump with the specific list of threads with stack trace
do_thread_dump(&dump_result,
ids_ah,
num_threads,
maxDepth,
false, /* no locked monitor */
false, /* no locked synchronizers */
CHECK_0);
}
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
int num_snapshots = dump_result.num_snapshots();
assert(num_snapshots == num_threads, "Must match the number of thread snapshots");
{- -------------------------------------------
(1) Management::create_thread_info_instance() で
生成した ThreadSnapshot オブジェクトから ThreadInfo オブジェクトを生成し,
引数で渡された配列に詰めていく.
---------------------------------------- -}
int index = 0;
for (ThreadSnapshot* ts = dump_result.snapshots(); ts != NULL; index++, ts = ts->next()) {
// For each thread, create an java/lang/management/ThreadInfo object
// and fill with the thread information
if (ts->threadObj() == NULL) {
// if the thread does not exist or now it is terminated, set threadinfo to NULL
infoArray_h->obj_at_put(index, NULL);
continue;
}
// Create java.lang.management.ThreadInfo object
instanceOop info_obj = Management::create_thread_info_instance(ts, CHECK_0);
infoArray_h->obj_at_put(index, info_obj);
}
{- -------------------------------------------
(1) リターン
---------------------------------------- -}
return 0;
JVM_END
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.