Top


定義場所(file name)

hotspot/src/share/vm/services/management.cpp

説明(description)

この関数は ThreadInfo オブジェクトの配列を返す. 各 ThreadInfo オブジェクトは, 引数の配列内に入っていた各スレッド ID に 対応するスレッドの情報を格納している.

なお, 対応するスレッドが存在しない(あるいは対応するスレッドが終了済みの)無効な ID が含まれていた場合は, それに対応する ThreadInfo オブジェクトとして null を返す.

引数の意味は以下の通り.

(なおコメントによると, 「この関数の返値の型はどうして 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?

名前(function name)

JVM_ENTRY(jint, jmm_GetThreadInfo(JNIEnv *env, jlongArray ids, jint maxDepth, jobjectArray infoArray))

本体部(body)

  {- -------------------------------------------
  (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.