Top


定義場所(file name)

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

名前(function name)

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

本体部(body)

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

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

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

      // lookup method in this interface or its super, java.lang.Object
      lookup_instance_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, CHECK);

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

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

      if (resolved_method.is_null()) {
        // lookup method in all the super-interfaces
        lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK);
        if (resolved_method.is_null()) {
          // no method found
          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) check_access 引数が true の場合には, 以下のチェックを行う
      * SystemDictionary::check_signature_loaders() を呼んで, 
        ロード制約(loading constraints)違反が起こっていないかどうかチェックする.
        もし違反していたら, LinkageError.
      ---------------------------------------- -}

      if (check_access) {
        HandleMark hm(THREAD);
        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 "
              "interface 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.