这个函数的调用流程是
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;
}
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);
}
}
}
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));
}
}