Top


定義場所(file name)

hotspot/src/share/vm/interpreter/linkResolver.cpp

名前(function name)

void LinkResolver::resolve_field(FieldAccessInfo& result, constantPoolHandle pool, int index, Bytecodes::Code byte, bool check_only, bool update_pool, TRAPS) {

本体部(body)

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

      assert(byte == Bytecodes::_getstatic || byte == Bytecodes::_putstatic ||
             byte == Bytecodes::_getfield  || byte == Bytecodes::_putfield, "bad bytecode");

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

      bool is_static = (byte == Bytecodes::_getstatic || byte == Bytecodes::_putstatic);
      bool is_put    = (byte == Bytecodes::_putfield  || byte == Bytecodes::_putstatic);

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

      // resolve specified klass
      KlassHandle resolved_klass;

  {- -------------------------------------------
  (1) LinkResolver::resolve_klass() を呼んで, 対象フィールドが属しているクラスを取得する
      (resolved_klass 局所変数にセットされる).
      (この際, 対象クラスが constantPoolOopDesc 中でまだ解決されてなければ解決も行われる)

      (ただし, update_pool 引数が false の場合には
       代わりに LinkResolver::resolve_klass_no_update() で取得する.
       この場合, 対象クラスが constantPoolOopDesc 中でまだ解決されていなくても, 解決は行われない)
      ---------------------------------------- -}

      if (update_pool) {
        resolve_klass(resolved_klass, pool, index, CHECK);
      } else {
        resolve_klass_no_update(resolved_klass, pool, index, CHECK);
      }

  {- -------------------------------------------
  (1) (変数宣言など)
      (ここで... #TODO)
      ---------------------------------------- -}

      // Load these early in case the resolve of the containing klass fails
      Symbol* field = pool->name_ref_at(index);
      Symbol* sig   = pool->signature_ref_at(index);

  {- -------------------------------------------
  (1) (そもそも, そのフィールドを含んでいるはずのクラス自体が見つからなければ, NoSuchFieldError)
      ---------------------------------------- -}

      // Check if there's a resolved klass containing the field
      if( resolved_klass.is_null() ) {
        ResourceMark rm(THREAD);
        THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), field->as_C_string());
      }

  {- -------------------------------------------
  (1) instanceKlass::find_field() を呼んで, 対象フィールドの情報を取得する.
      (fd 局所変数と sel_klass 局所変数にセットされる. sel_klass は, そのフィールドを定義しているクラス.
       (定義しているのは, resolved_klass 自体とは限らず, スーパークラスやスーパーインターフェースの可能性もある))
      (もし定義しているクラスが見つからなければ, NoSuchFieldError)
      ---------------------------------------- -}

      // Resolve instance field
      fieldDescriptor fd; // find_field initializes fd if found
      KlassHandle sel_klass(THREAD, instanceKlass::cast(resolved_klass())->find_field(field, sig, &fd));
      // check if field exists; i.e., if a klass containing the field def has been selected
      if (sel_klass.is_null()){
        ResourceMark rm(THREAD);
        THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), field->as_C_string());
      }

  {- -------------------------------------------
  (1) LinkResolver::check_field_accessability() を呼んで, アクセス権をチェックする.
      (アクセス権違反なら, この中で IllegalAccessError が出る)
      ---------------------------------------- -}

      // check access
      KlassHandle ref_klass(THREAD, pool->pool_holder());
      check_field_accessability(ref_klass, resolved_klass, sel_klass, fd, CHECK);

  {- -------------------------------------------
  (1) もし対象フィールドの ACC_STATIC 属性(static かどうかを示す属性) が
      引数で指定された内容(is_static)と食い違っていれば, IncompatibleClassChangeError.
      ---------------------------------------- -}

      // check for errors
      if (is_static != fd.is_static()) {
        ResourceMark rm(THREAD);
        char msg[200];
        jio_snprintf(msg, sizeof(msg), "Expected %s field %s.%s", is_static ? "static" : "non-static", Klass::cast(resolved_klass())->external_name(), fd.name()->as_C_string());
        THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), msg);
      }

  {- -------------------------------------------
  (1) もし final field がその定義クラス以外から変更されようとしていたら, IllegalAccessError.
      ---------------------------------------- -}

      // Final fields can only be accessed from its own class.
      if (is_put && fd.access_flags().is_final() && sel_klass() != pool->pool_holder()) {
        THROW(vmSymbols::java_lang_IllegalAccessError());
      }

  {- -------------------------------------------
  (1) 必要があれば, Klass::initialize() を呼んで定義クラスを初期化しておく
      ---------------------------------------- -}

      // initialize resolved_klass if necessary
      // note 1: the klass which declared the field must be initialized (i.e, sel_klass)
      //         according to the newest JVM spec (5.5, p.170) - was bug (gri 7/28/99)
      //
      // note 2: we don't want to force initialization if we are just checking
      //         if the field access is legal; e.g., during compilation
      if (is_static && !check_only) {
        sel_klass->initialize(CHECK);
      }

  {- -------------------------------------------
  (1) SystemDictionary::check_signature_loaders() を呼んで, 
      ロード制約(loading constraints)違反が起こっていないかどうかチェックする.
      もし違反していたら, LinkageError.
      ---------------------------------------- -}

      {
        HandleMark hm(THREAD);
        Handle ref_loader (THREAD, instanceKlass::cast(ref_klass())->class_loader());
        Handle sel_loader (THREAD, instanceKlass::cast(sel_klass())->class_loader());
        Symbol*  signature_ref  = pool->signature_ref_at(index);
        {
          ResourceMark rm(THREAD);
          char* failed_type_name =
            SystemDictionary::check_signature_loaders(signature_ref,
                                                      ref_loader, sel_loader,
                                                      false,
                                                      CHECK);
          if (failed_type_name != NULL) {
            const char* msg = "loader constraint violation: when resolving field"
              " \"%s\" the class loader (instance of %s) of the referring class, "
              "%s, and the class loader (instance of %s) for the field's resolved "
              "type, %s, have different Class objects for that type";
            char* field_name = field->as_C_string();
            const char* loader1 = SystemDictionary::loader_name(ref_loader());
            char* sel = instanceKlass::cast(sel_klass())->name()->as_C_string();
            const char* loader2 = SystemDictionary::loader_name(sel_loader());
            size_t buflen = strlen(msg) + strlen(field_name) + strlen(loader1) +
              strlen(sel) + strlen(loader2) + strlen(failed_type_name);
            char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen);
            jio_snprintf(buf, buflen, msg, field_name, loader1, sel, loader2,
                         failed_type_name);
            THROW_MSG(vmSymbols::java_lang_LinkageError(), buf);
          }
        }
      }

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

      // return information. note that the klass is set to the actual klass containing the
      // field, otherwise access of static fields in superclasses will not work.
      KlassHandle holder (THREAD, fd.field_holder());
      Symbol*  name   = fd.name();

  {- -------------------------------------------
  (1) FieldAccessInfo::set() を呼んで, 
      引数で渡された FieldAccessInfo オブジェクト内に
      解決結果をセットする
      ---------------------------------------- -}

      result.set(holder, name, fd.index(), fd.offset(), fd.field_type(), fd.access_flags());
    }

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