Top


定義場所(file name)

hotspot/src/share/vm/oops/klassVtable.cpp

名前(function name)

void klassItable::initialize_itable_for_interface(int method_table_offset, KlassHandle interf_h, bool checkconstraints, TRAPS) {

本体部(body)

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

      objArrayHandle methods(THREAD, instanceKlass::cast(interf_h())->methods());
      int nof_methods = methods()->length();
      HandleMark hm;
      KlassHandle klass = _klass;
      assert(nof_methods > 0, "at least one method must exist for interface to be in vtable");
      Handle interface_loader (THREAD, instanceKlass::cast(interf_h())->class_loader());
      int ime_num = 0;

  {- -------------------------------------------
  (1) static 初期化子(<clinit>) はスキップして開始する.
      ---------------------------------------- -}

      // Skip first methodOop if it is a class initializer
      int i = ((methodOop)methods()->obj_at(0))->is_static_initializer() ? 1 : 0;

  {- -------------------------------------------
  (1) 以下のループで定義されているメソッドを全て辿り, itable の初期化を行う.
      ---------------------------------------- -}

      // m, method_name, method_signature, klass reset each loop so they
      // don't need preserving across check_signature_loaders call
      // methods needs a handle in case of gc from check_signature_loaders
      for(; i < nof_methods; i++) {

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

        methodOop m = (methodOop)methods()->obj_at(i);
        Symbol* method_name = m->name();
        Symbol* method_signature = m->signature();

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

        // This is same code as in Linkresolver::lookup_instance_method_in_klasses
        methodOop target = klass->uncached_lookup_method(method_name, method_signature);
        while (target != NULL && target->is_static()) {
          // continue with recursive lookup through the superclass
          klassOop super = Klass::cast(target->method_holder())->super();
          target = (super == NULL) ? methodOop(NULL) : Klass::cast(super)->uncached_lookup_method(method_name, method_signature);
        }

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

        if (target == NULL || !target->is_public() || target->is_abstract()) {
          // Entry do not resolve. Leave it empty
        } else {

    {- -------------------------------------------
  (1.1) もし, 引数で loader constraints をチェックするよう指定されていれば, 
        SystemDictionary::check_signature_loaders() を呼んでチェックを行う.
        (チェックが失敗したら LinkageError)
        ---------------------------------------- -}

          // Entry did resolve, check loader constraints before initializing
          // if checkconstraints requested
          methodHandle  target_h (THREAD, target); // preserve across gc
          if (checkconstraints) {
            Handle method_holder_loader (THREAD, instanceKlass::cast(target->method_holder())->class_loader());
            if (method_holder_loader() != interface_loader()) {
              ResourceMark rm(THREAD);
              char* failed_type_name =
                SystemDictionary::check_signature_loaders(method_signature,
                                                          method_holder_loader,
                                                          interface_loader,
                                                          true, CHECK);
              if (failed_type_name != NULL) {
                const char* msg = "loader constraint violation in interface "
                  "itable initialization: when resolving method \"%s\" the class"
                  " loader (instance of %s) of the current class, %s, "
                  "and the class loader (instance of %s) for interface "
                  "%s have different Class objects for the type %s "
                  "used in the signature";
                char* sig = target_h()->name_and_sig_as_C_string();
                const char* loader1 = SystemDictionary::loader_name(method_holder_loader());
                char* current = klass->name()->as_C_string();
                const char* loader2 = SystemDictionary::loader_name(interface_loader());
                char* iface = instanceKlass::cast(interf_h())->name()->as_C_string();
                size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) +
                  strlen(current) + strlen(loader2) + strlen(iface) +
                  strlen(failed_type_name);
                char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen);
                jio_snprintf(buf, buflen, msg, sig, loader1, current, loader2,
                             iface, failed_type_name);
                THROW_MSG(vmSymbols::java_lang_LinkageError(), buf);
              }
            }
          }

    {- -------------------------------------------
  (1.1) itableOffsetEntry::method_entry() で対応する itableMethodEntry を取得し, 
        itableMethodEntry::initialize() で itable 中の該当箇所にメソッドを登録する.
        ---------------------------------------- -}

          // ime may have moved during GC so recalculate address
          itableOffsetEntry::method_entry(_klass(), method_table_offset)[ime_num].initialize(target_h());
        }

    {- -------------------------------------------
  (1.1) ループの次の周へ進む
        ---------------------------------------- -}

        // Progress to next entry
        ime_num++;
      }
    }

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