Top


定義場所(file name)

hotspot/src/share/vm/prims/jvmtiEnv.cpp

説明(description)

// class_count - pre-checked to be greater than or equal to 0
// classes - pre-checked for NULL

名前(function name)

jvmtiError
JvmtiEnv::RetransformClasses(jint class_count, const jclass* classes) {

本体部(body)

  {- -------------------------------------------
  (1) 
      ---------------------------------------- -}

    //TODO: add locking

  {- -------------------------------------------
  (1) (変数宣言など)
      ---------------------------------------- -}

      int index;
      JavaThread* current_thread = JavaThread::current();
      ResourceMark rm(current_thread);

  {- -------------------------------------------
  (1) 集めたクラス情報を入れておくための配列を確保する. 
      (確保に失敗したら JVMTI_ERROR_OUT_OF_MEMORY エラーをリターン)
      ---------------------------------------- -}

      jvmtiClassDefinition* class_definitions =
                                NEW_RESOURCE_ARRAY(jvmtiClassDefinition, class_count);
      NULL_CHECK(class_definitions, JVMTI_ERROR_OUT_OF_MEMORY);

  {- -------------------------------------------
  (1) (以下の for ループで指定されたクラス数分だけループし, クラス情報を集めていく)
      ---------------------------------------- -}

      for (index = 0; index < class_count; index++) {

  {- -------------------------------------------
  (1) 
      ---------------------------------------- -}

        HandleMark hm(current_thread);

        jclass jcls = classes[index];
        oop k_mirror = JNIHandles::resolve_external_guard(jcls);
        if (k_mirror == NULL) {
          return JVMTI_ERROR_INVALID_CLASS;
        }
        if (!k_mirror->is_a(SystemDictionary::Class_klass())) {
          return JVMTI_ERROR_INVALID_CLASS;
        }

        if (java_lang_Class::is_primitive(k_mirror)) {
          return JVMTI_ERROR_UNMODIFIABLE_CLASS;
        }

        klassOop k_oop = java_lang_Class::as_klassOop(k_mirror);
        KlassHandle klass(current_thread, k_oop);

        jint status = klass->jvmti_class_status();
        if (status & (JVMTI_CLASS_STATUS_ERROR)) {
          return JVMTI_ERROR_INVALID_CLASS;
        }
        if (status & (JVMTI_CLASS_STATUS_ARRAY)) {
          return JVMTI_ERROR_UNMODIFIABLE_CLASS;
        }

        instanceKlassHandle ikh(current_thread, k_oop);

    {- -------------------------------------------
  (1.1) キャッシュしている内容がなければ, JvmtiClassFileReconstituter でクラス情報を復元する.

        (VM_RedefineClasses 内でもキャッシュがセットされているので, 同じクラスについては最大でも一回しか Reconstitute されない?? #TODO)
        ---------------------------------------- -}

        if (ikh->get_cached_class_file_bytes() == NULL) {
          // not cached, we need to reconstitute the class file from VM representation
          constantPoolHandle  constants(current_thread, ikh->constants());
          ObjectLocker ol(constants, current_thread);    // lock constant pool while we query it

      {- -------------------------------------------
  (1.1.1) JvmtiClassFileReconstituter オブジェクトを生成し (生成に失敗したらエラー), 
          JvmtiClassFileReconstituter::class_file_size() と
          JvmtiClassFileReconstituter::class_file_bytes() を呼んで, 
          クラスファイル情報を取得する.
          ---------------------------------------- -}

          JvmtiClassFileReconstituter reconstituter(ikh);
          if (reconstituter.get_error() != JVMTI_ERROR_NONE) {
            return reconstituter.get_error();
          }

          class_definitions[index].class_byte_count = (jint)reconstituter.class_file_size();
          class_definitions[index].class_bytes      = (unsigned char*)
                                                           reconstituter.class_file_bytes();

    {- -------------------------------------------
  (1.1) もしキャッシュしている内容があれば, それを使う.
        ---------------------------------------- -}

        } else {
          // it is cached, get it from the cache
          class_definitions[index].class_byte_count = ikh->get_cached_class_file_len();
          class_definitions[index].class_bytes      = ikh->get_cached_class_file_bytes();
        }

  {- -------------------------------------------
  (1) 
      ---------------------------------------- -}

        class_definitions[index].klass              = jcls;
      }

  {- -------------------------------------------
  (1) 集めた情報を VM_RedefineClasses に引き渡して RedefineClasses の処理に引き継ぐ.
      ---------------------------------------- -}

      VM_RedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_retransform);
      VMThread::execute(&op);

  {- -------------------------------------------
  (1) リターン
      ---------------------------------------- -}

      return (op.check_error());
    } /* end RetransformClasses */

This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.