Hotspot源码解析-第22章-vtable和itable的重新初始化

发布时间:2024年01月23日

第22章-vtable和itable的重新初始化

这个函数的调用流程是

init.cpp->init_globals()

universe.cpp->universe_post_init()

bool universe_post_init() {
  // 防止二次初始化
  assert(!is_init_completed(), "Error: initialization not yet completed!");
  Universe::_fully_initialized = true;
  EXCEPTION_MARK;
  { ResourceMark rm;
    // 解释器初始化
    Interpreter::initialize();      // needed for interpreter entry points
    if (!UseSharedSpaces) {
      HandleMark hm(THREAD);
      // 获取Object klass的句柄
      KlassHandle ok_h(THREAD, SystemDictionary::Object_klass());
      // 对vtable进行重新初始化,细节看`章节22.1`
      Universe::reinitialize_vtable_of(ok_h, CHECK_false);
      // 对itable重新进行初始化:vtable我们在`章节20.1 20.2`中已经讲过,itable就是针对Java接口方法的实现方法,只有普通类才有,Interface本身没有itable
      Universe::reinitialize_itables(CHECK_false);
    }
  }
  HandleMark hm(THREAD);
  Klass* k;
  instanceKlassHandle k_h;
    // 创建一个空 java.lang.Class 数组
    Universe::_the_empty_class_klass_array = oopFactory::new_objArray(SystemDictionary::Class_klass(), 0, CHECK_false);

    // 解析 OutOfMemoryError 类
    k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_OutOfMemoryError(), true, CHECK_false);
    // 生成句柄
    k_h = instanceKlassHandle(THREAD, k);
    // 分配空间存放 OutOfMemoryError 内存溢出时各对应属性字段
    Universe::_out_of_memory_error_java_heap = k_h->allocate_instance(CHECK_false);
    Universe::_out_of_memory_error_metaspace = k_h->allocate_instance(CHECK_false);
    Universe::_out_of_memory_error_class_metaspace = k_h->allocate_instance(CHECK_false);
    Universe::_out_of_memory_error_array_size = k_h->allocate_instance(CHECK_false);
    Universe::_out_of_memory_error_gc_overhead_limit =
      k_h->allocate_instance(CHECK_false);
    Universe::_out_of_memory_error_realloc_objects = k_h->allocate_instance(CHECK_false);

    // 解析 NullPointerException 类及设置对应属性字段
    k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_NullPointerException(), true, CHECK_false);
    Universe::_null_ptr_exception_instance = InstanceKlass::cast(k)->allocate_instance(CHECK_false);
    // 解析 ArithmeticException 类及设置对应属性字段
    k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_ArithmeticException(), true, CHECK_false);
    Universe::_arithmetic_exception_instance = InstanceKlass::cast(k)->allocate_instance(CHECK_false);
    //  解析虚拟机错误 VirtualMachineError 类及设置对应属性字段
    k = SystemDictionary::resolve_or_fail(
      vmSymbols::java_lang_VirtualMachineError(), true, CHECK_false);
    bool linked = InstanceKlass::cast(k)->link_class_or_fail(CHECK_false);
     if (!linked) {
      tty->print_cr("Unable to link/verify VirtualMachineError class");
      return false; // initialization failed
    }
    Universe::_virtual_machine_error_instance =
      InstanceKlass::cast(k)->allocate_instance(CHECK_false);

    Universe::_vm_exception = InstanceKlass::cast(k)->allocate_instance(CHECK_false);

  if (!DumpSharedSpaces) {
    // 创建各错误/异常抛出时需要设置的 msg 信息
    Handle msg = java_lang_String::create_from_str("Java heap space", CHECK_false);
    java_lang_Throwable::set_message(Universe::_out_of_memory_error_java_heap, msg());

    msg = java_lang_String::create_from_str("Metaspace", CHECK_false);
    java_lang_Throwable::set_message(Universe::_out_of_memory_error_metaspace, msg());
    msg = java_lang_String::create_from_str("Compressed class space", CHECK_false);
    java_lang_Throwable::set_message(Universe::_out_of_memory_error_class_metaspace, msg());

    msg = java_lang_String::create_from_str("Requested array size exceeds VM limit", CHECK_false);
    java_lang_Throwable::set_message(Universe::_out_of_memory_error_array_size, msg());

    msg = java_lang_String::create_from_str("GC overhead limit exceeded", CHECK_false);
    java_lang_Throwable::set_message(Universe::_out_of_memory_error_gc_overhead_limit, msg());

    msg = java_lang_String::create_from_str("Java heap space: failed reallocation of scalar replaced objects", CHECK_false);
    java_lang_Throwable::set_message(Universe::_out_of_memory_error_realloc_objects, msg());

    msg = java_lang_String::create_from_str("/ by zero", CHECK_false);
    java_lang_Throwable::set_message(Universe::_arithmetic_exception_instance, msg());

    // Setup the array of errors that have preallocated backtrace
    k = Universe::_out_of_memory_error_java_heap->klass();
    assert(k->name() == vmSymbols::java_lang_OutOfMemoryError(), "should be out of memory error");
    k_h = instanceKlassHandle(THREAD, k);

    int len = (StackTraceInThrowable) ? (int)PreallocatedOutOfMemoryErrorCount : 0;
    Universe::_preallocated_out_of_memory_error_array = oopFactory::new_objArray(k_h(), len, CHECK_false);
    for (int i=0; i<len; i++) {
      oop err = k_h->allocate_instance(CHECK_false);
      Handle err_h = Handle(THREAD, err);
      java_lang_Throwable::allocate_backtrace(err_h, CHECK_false);
      Universe::preallocated_out_of_memory_errors()->obj_at_put(i, err_h());
    }
    Universe::_preallocated_out_of_memory_error_avail_count = (jint)len;
  }


  // 对 Finalizer 类的处理
  InstanceKlass::cast(SystemDictionary::Finalizer_klass())->link_class(CHECK_false);
  Method* m = InstanceKlass::cast(SystemDictionary::Finalizer_klass())->find_method(
                                  vmSymbols::register_method_name(),
                                  vmSymbols::register_method_signature());
  if (m == NULL || !m->is_static()) {
    tty->print_cr("Unable to link/verify Finalizer.register method");
    return false; // initialization failed (cannot throw exception yet)
  }
  Universe::_finalizer_register_cache->init(
    SystemDictionary::Finalizer_klass(), m);
 
  // 对 Unsafe 类的处理
  InstanceKlass::cast(SystemDictionary::misc_Unsafe_klass())->link_class(CHECK_false);
  m = InstanceKlass::cast(SystemDictionary::misc_Unsafe_klass())->find_method(
                                  vmSymbols::throwIllegalAccessError_name(),
                                  vmSymbols::void_method_signature());
  if (m != NULL && !m->is_static()) {
    // Note null is okay; this method is used in itables, and if it is null,
    // then AbstractMethodError is thrown instead.
    tty->print_cr("Unable to link/verify Unsafe.throwIllegalAccessError method");
    return false; // initialization failed (cannot throw exception yet)
  }
  Universe::_throw_illegal_access_error_cache->init(
    SystemDictionary::misc_Unsafe_klass(), m);

  // 对 ClassLoader 类的处理
  InstanceKlass::cast(SystemDictionary::ClassLoader_klass())->link_class(CHECK_false);
  m = InstanceKlass::cast(SystemDictionary::ClassLoader_klass())->find_method(vmSymbols::addClass_name(), vmSymbols::class_void_signature());
  if (m == NULL || m->is_static()) {
    tty->print_cr("Unable to link/verify ClassLoader.addClass method");
    return false; // initialization failed (cannot throw exception yet)
  }
  Universe::_loader_addClass_cache->init(
    SystemDictionary::ClassLoader_klass(), m);

  // 对 ProtectionDomain 类的处理
  InstanceKlass::cast(SystemDictionary::ProtectionDomain_klass())->link_class(CHECK_false);
  m = InstanceKlass::cast(SystemDictionary::ProtectionDomain_klass())->
            find_method(vmSymbols::impliesCreateAccessControlContext_name(),
                        vmSymbols::void_boolean_signature());
  // Allow NULL which should only happen with bootstrapping.
  if (m != NULL) {
    if (m->is_static()) {
      // NoSuchMethodException doesn't actually work because it tries to run the
      // <init> function before java_lang_Class is linked. Print error and exit.
      tty->print_cr("ProtectionDomain.impliesCreateAccessControlContext() has the wrong linkage");
      return false; // initialization failed
    }
    Universe::_pd_implies_cache->init(
      SystemDictionary::ProtectionDomain_klass(), m);
  }

  // The folowing is initializing converter functions for serialization in
  // JVM.cpp. If we clean up the StrictMath code above we may want to find
  // a better solution for this as well.
  initialize_converter_functions();

  // This needs to be done before the first scavenge/gc, since
  // it's an input to soft ref clearing policy.
  {
    MutexLocker x(Heap_lock);
    Universe::update_heap_info_at_gc();
  }

  // ("weak") refs processing infrastructure initialization
  Universe::heap()->post_initialize();

  // Initialize performance counters for metaspaces
  MetaspaceCounters::initialize_performance_counters();
  CompressedClassSpaceCounters::initialize_performance_counters();

  MemoryService::add_metaspace_memory_pools();

  MemoryService::set_universe_heap(Universe::_collectedHeap);
#if INCLUDE_CDS
  if (UseSharedSpaces) {
    SharedClassUtil::initialize(CHECK_false);
  }
#endif
  return true;
}

22.1 vtable重新初始化

22.1.1 universe.cpp

22.1.1.1 reinitialize_vtable_of
void Universe::reinitialize_vtable_of(KlassHandle k_h, TRAPS) {
  // 从句柄中取出Object Klass
  Klass* ko = k_h();
  // 从Object Klass 中取出vtable
  klassVtable* vt = ko->vtable();
  // 对 Object klass 本身vtable重新初始化,继续看`章节22.1.2.1`
  if (vt) vt->initialize_vtable(false, CHECK);
  // 如果是普通对象实例,那就继续处理子类的vtable
  if (ko->oop_is_instance()) {
    InstanceKlass* ik = (InstanceKlass*)ko;
    // 拿到子类
    for (KlassHandle s_h(THREAD, ik->subklass());
         s_h() != NULL;
         // next_sibling() 沿着兄弟子类继续找
         s_h = KlassHandle(THREAD, s_h()->next_sibling())) {
      // 层层子类 vtable 重新初始化,递归
      reinitialize_vtable_of(s_h, CHECK);
    }
  }
}

22.1.2 klassVtable.cpp

22.1.2.1 initialize_vtable
void klassVtable::initialize_vtable(bool checkconstraints, TRAPS) {

  // Java的super类,那还是Object,也就是说,这里还是取的Object Klass句柄
  KlassHandle super (THREAD, klass()->java_super());
  int nofNewEntries = 0;
  // 判断是否共享
  bool is_shared = _klass->is_shared();

  if (PrintVtables && !klass()->oop_is_array()) {
    ResourceMark rm(THREAD);
    tty->print_cr("Initializing: %s", _klass->name()->as_C_string());
  }

#ifdef ASSERT
  // 对象的限制地址
  oop* end_of_obj = (oop*)_klass() + _klass()->size();
  // vtable的限制地址
  oop* end_of_vtable = (oop*)&table()[_length];
  // vtable的限制地址 必须小于等于  对象的限制地址,`章节20.1`中有画图描述
  assert(end_of_vtable <= end_of_obj, "vtable extends beyond end");
#endif
  // 当上面的_klass 是Object klass的时候,这里就是 true
  if (Universe::is_bootstrapping()) {
    assert(!is_shared, "sanity");
    // 遍历清空vtable的值
    for (int i = 0; i < _length; i++) table()[i].clear();
    return;
  }
  // 当上面的_klass 不是Object Klass,是其他普通类的 klass时,走下面的逻辑
  // 这一步是取出超类的vtable的长度
  int super_vtable_len = initialize_from_super(super);
  // klass不能是数组类型的,因为数组没有函数
  if (klass()->oop_is_array()) {
    assert(super_vtable_len == _length, "arrays shouldn't introduce new methods");
  } else {
    
    assert(_klass->oop_is_instance(), "must be InstanceKlass");
    // 当前 klass的方法数组
    Array<Method*>* methods = ik()->methods();
    // 当前 klass的方法数组的长度
    int len = methods->length();
    // 超类的vtable长度
    int initialized = super_vtable_len;

    // Check each of this class's methods against super;
    // if override, replace in copy of super vtable, otherwise append to end
    // 对照超类的vtable中的方法,比较当前 klass 的方法,看看有没有覆盖(重写),如果有覆盖的,那么就要在super vtable的副本中替换,否则追加到末尾
    for (int i = 0; i < len; i++) {
      // update_inherited_vtable can stop for gc - ensure using handles
      HandleMark hm(THREAD);
      assert(methods->at(i)->is_method(), "must be a Method*");
      methodHandle mh(THREAD, methods->at(i));
      // 这里就是判断有没有覆盖(重写),返回true,就是要新建,并追加到末尾
      bool needs_new_entry = update_inherited_vtable(ik(), mh, super_vtable_len, -1, checkconstraints, CHECK);

      if (needs_new_entry) {
        // 放到数组末尾
        put_method_at(mh(), initialized);
        // 设置当前vtable index
        mh()->set_vtable_index(initialized); // set primary vtable index
        initialized++;
      }
    }

    // 用默认的方法更新vtable,逻辑跟上面的一样,也是遍历并比较覆盖,默认方法的讲解,在后续类加载时会具体讲
    Array<Method*>* default_methods = ik()->default_methods();
    if (default_methods != NULL) {
      len = default_methods->length();
      if (len > 0) {
        Array<int>* def_vtable_indices = NULL;
        if ((def_vtable_indices = ik()->default_vtable_indices()) == NULL) {
          assert(!is_shared, "shared class def_vtable_indices does not exist");
          def_vtable_indices = ik()->create_new_default_vtable_indices(len, CHECK);
        } else {
          assert(def_vtable_indices->length() == len, "reinit vtable len?");
        }
        for (int i = 0; i < len; i++) {
          HandleMark hm(THREAD);
          assert(default_methods->at(i)->is_method(), "must be a Method*");
          methodHandle mh(THREAD, default_methods->at(i));

          bool needs_new_entry = update_inherited_vtable(ik(), mh, super_vtable_len, i, checkconstraints, CHECK);

          // needs new entry
          if (needs_new_entry) {
            put_method_at(mh(), initialized);
            if (is_preinitialized_vtable()) {
              // At runtime initialize_vtable is rerun for a shared class
              // (loaded by the non-boot loader) as part of link_class_impl().
              // The dumptime vtable index should be the same as the runtime index.
              assert(def_vtable_indices->at(i) == initialized,
                     "dump time vtable index is different from runtime index");
            } else {
              def_vtable_indices->at_put(i, initialized); //set vtable index
            }
            initialized++;
          }
        }
      }
    }
      
    // 所谓 miranda methods 就是 Java Interface/abstract 接口方法,这一步就是把接口类方法添加进去
    if (!ik()->is_interface()) {
      initialized = fill_in_mirandas(initialized);
    }

    assert(initialized <= _length, "vtable initialization failed");
    // vtable数组长度默认最大是256,这里如果实际存在的函数不足_length,那剩下的坑位就设置为NULL
    for(;initialized < _length; initialized++) {
      put_method_at(NULL, initialized);
    }
    NOT_PRODUCT(verify(tty, true));
  }
}

文章来源:https://blog.csdn.net/zhang527294844/article/details/135778307
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。