Top


定義場所(file name)

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

名前(function name)

void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle resolved_klass,
                                  Symbol* method_name, Symbol* method_signature,
                                  KlassHandle current_klass, bool check_access, TRAPS) {

本体部(body)

  {- -------------------------------------------
  (1) もし (クラスではなく) インターフェースだった場合は IncompatibleClassChangeError
      ---------------------------------------- -}

      // 1. check if klass is not interface
      if (resolved_klass->is_interface()) {
        ResourceMark rm(THREAD);
        char buf[200];
        jio_snprintf(buf, sizeof(buf), "Found interface %s, but class was expected", Klass::cast(resolved_klass())->external_name());
        THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
      }

  {- -------------------------------------------
  (1) まず LinkResolver::lookup_method_in_klasses() を呼んで, 
      resolved_klass クラス内, あるいはそのスーパークラス内からメソッドを探す.
      ---------------------------------------- -}

      // 2. lookup method in resolved klass and its super klasses
      lookup_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, CHECK);

  {- -------------------------------------------
  (1) もしメソッドが見つかっていなければ, 
      LinkResolver::lookup_method_in_interfaces() を呼んで
      インターフェース内からメソッドを探す.

      それでも見つからなければ, LinkResolver::lookup_implicit_method() を呼んで, 

      (もしそれでも見つからなければ NoSuchMethodError)
      ---------------------------------------- -}

      if (resolved_method.is_null()) { // not found in the class hierarchy
        // 3. lookup method in all the interfaces implemented by the resolved klass
        lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK);

        if (resolved_method.is_null()) {
          // JSR 292:  see if this is an implicitly generated method MethodHandle.invoke(*...)
          lookup_implicit_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, CHECK);
        }

        if (resolved_method.is_null()) {
          // 4. method lookup failed
          ResourceMark rm(THREAD);
          THROW_MSG(vmSymbols::java_lang_NoSuchMethodError(),
                    methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()),
                                                            method_name,
                                                            method_signature));
        }
      }

  {- -------------------------------------------
  (1) もし解決結果が abstract method だったら, AbstractMethodError.
      ---------------------------------------- -}

      // 5. check if method is concrete
      if (resolved_method->is_abstract() && !resolved_klass->is_abstract()) {
        ResourceMark rm(THREAD);
        THROW_MSG(vmSymbols::java_lang_AbstractMethodError(),
                  methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()),
                                                          method_name,
                                                          method_signature));
      }

  {- -------------------------------------------
  (1) check_access 引数が true の場合には, 以下のチェックを行う
      * LinkResolver::check_method_accessability() を呼んで, アクセス権をチェックする.
        (アクセス権違反なら, この中で IllegalAccessError が出る)
      * SystemDictionary::check_signature_loaders() を呼んで, 
        ロード制約(loading constraints)違反が起こっていないかどうかチェックする.
        もし違反していたら, LinkageError.
      ---------------------------------------- -}

      // 6. access checks, access checking may be turned off when calling from within the VM.
      if (check_access) {
        assert(current_klass.not_null() , "current_klass should not be null");

        // check if method can be accessed by the referring class
        check_method_accessability(current_klass,
                                   resolved_klass,
                                   KlassHandle(THREAD, resolved_method->method_holder()),
                                   resolved_method,
                                   CHECK);

        // check loader constraints
        Handle loader (THREAD, instanceKlass::cast(current_klass())->class_loader());
        Handle class_loader (THREAD, instanceKlass::cast(resolved_method->method_holder())->class_loader());
        {
          ResourceMark rm(THREAD);
          char* failed_type_name =
            SystemDictionary::check_signature_loaders(method_signature, loader,
                                                      class_loader, true, CHECK);
          if (failed_type_name != NULL) {
            const char* msg = "loader constraint violation: when resolving method"
              " \"%s\" the class loader (instance of %s) of the current class, %s,"
              " and the class loader (instance of %s) for resolved class, %s, have"
              " different Class objects for the type %s used in the signature";
            char* sig = methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()),method_name,method_signature);
            const char* loader1 = SystemDictionary::loader_name(loader());
            char* current = instanceKlass::cast(current_klass())->name()->as_C_string();
            const char* loader2 = SystemDictionary::loader_name(class_loader());
            char* resolved = instanceKlass::cast(resolved_klass())->name()->as_C_string();
            size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) +
              strlen(current) + strlen(loader2) + strlen(resolved) +
              strlen(failed_type_name);
            char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen);
            jio_snprintf(buf, buflen, msg, sig, loader1, current, loader2,
                         resolved, failed_type_name);
            THROW_MSG(vmSymbols::java_lang_LinkageError(), buf);
          }
        }
      }
    }

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