目录
2、LatestMethodCache / NarrowPtrStruct
6、initialize_basic_type_mirrors
在《Hotspot Java对象创建和TLAB源码解析》讲解Java对象创建和分配TLAB时,在《Hotspot 内存管理之MemoryService 源码解析》讲解MemoryService的set_universe_heap方法的调用时都频繁碰到Universe类,本篇博客就详细探讨Universe类的初始化和对外提供的接口。
1、定义
Universe的定义位于hotspot src/shared/vm/memory/universe.hpp中,Universe类用来保存JVM中重要的系统类及其实例,如基础类型数组的Klass,用来提供对分配Java对象的CollectedHeap的访问入口,提供多种对象分配的方法。Universe定义的属性和对外提供的方法都是static的,除预先初始化好的重要的Klass或者oop外,关键的属性如下:
- LatestMethodCache* _finalizer_register_cache; //对应java_lang_ref_Finalizer类的register(Object finalizee)方法,该类是java_lang_ref包级私有的
- LatestMethodCache* _loader_addClass_cache; //对应sun_reflect_DelegatingClassLoader类的addClass方法,DelegatingClassLoader是sun_reflect_ClassDefiner中定义的,包级访问,直接继承自java.lang.ClassLoader类
- LatestMethodCache* _pd_implies_cache; //对应java_security_ProtectionDomain类的impliesCreateAccessControlContext方法
- LatestMethodCache* _throw_illegal_access_error_cache; //对应 Unsafe类的throwIllegalAccessError() 方法
- CollectedHeap* _collectedHeap; //负责Java对象分配的CollectedHeap引用
- intptr_t _non_oop_bits; //用来标识某块内存不是一个合法的oop,在oop遍历时使用
- NarrowPtrStruct _narrow_oop;//开启UseCompressedOops时,保存用来记录计算真实oop地址的base地址等属性
- NarrowPtrStruct _narrow_klass; //开启UseCompressedClassPointers时,保存用来记录计算真实klass地址的base地址等属性
- address _narrow_ptrs_base; //使用narrow_ptrs时的基地址
- int _base_vtable_size; //Klass中虚函数表占用内存的最小值,实际就是Object类Klass的虚函数表的大小
- size_t _heap_capacity_at_last_gc; //上一次GC时的堆内存的容量
- size_t _heap_used_at_last_gc; //上一次GC时的堆内存的已使用的内存量
Universe定义的方法大部分是读写属性的相关方法,重点关注Universe的初始化和下列方法的实现即可。因为Universe没有定义实例属性,都是静态属性和静态方法,所以Universe没有定义构造方法,初始化时也不需要new一个Universe,而是通过三个友元方法完成Universe的各静态属性的初始化,这三个友元方法的定义如下:
这三个方法都是在JVM启动时在init_globals()方法中依次调用的。
2、LatestMethodCache / NarrowPtrStruct
LatestMethodCache用来缓存Method*,调用方通过get_method方法获取的永远是该方法的最新版本,LatestMethodCache内部屏蔽了类重定义(Class Redefinition)时方法实现发生变更的问题。LatestMethodCache定义的属性如下:
_klass就是该方法所属的类的Klass,_method_idnum是该方法在Klass中的方法ID,实际是该方法在Klass方法数组中的序号,当类重定义时该方法对应的Method*可能发生改变,_method_idnum可能以为增加了新的方法也发生改变,但是_method_idnum会保证永远对应着原来的那个方法,从保证get_method方法返回的用于是该方法的最新版本。get_method方法的实现如下图:
LatestMethodCache的init方法的实现如下图:
NarrowPtrStruct是一个结构体,用来保存开启指针压缩时计算压缩指针真实地址的base地址等属性信息,其定义如下图:
base和shift属性的用法可以参考用于计算压缩指针真实地址oopDesc::decode_heap_oop_not_null方法的实现,如下图:
3、universe_init
universe_init方法的执行依赖于codeCache_init 和stubRoutines_init 方法的成功执行,是最新被调用的universe初始化方法,主要用来初始化collectedHeap,Metaspace和TLAB等组件,其源码实现如下:
jint universe_init() {
assert(!Universe::_fully_initialized, "called after initialize_vtables");
//校验参数的合法
guarantee(1 << LogHeapWordSize == sizeof(HeapWord),
"LogHeapWordSize is incorrect.");
//sizeof(oop)和sizeof(HeapWord)实际都是一个指针的大小
guarantee(sizeof(oop) >= sizeof(HeapWord), "HeapWord larger than oop?");
guarantee(sizeof(oop) % sizeof(HeapWord) == 0,
"oop size is not not a multiple of HeapWord size");
TraceTime timer("Genesis", TraceStartupTime);
//计算部分重要的系统类的关键属性在oop中的偏移量,方便快速根据内存偏移读取属性值
JavaClasses::compute_hard_coded_offsets();
//初始化collectedHeap和TLABA
jint status = Universe::initialize_heap();
if (status != JNI_OK) {
return status;
}
//初始化负责元空间内存管理的Metaspace
Metaspace::global_initialize();
// 初始化ClassLoaderData的_the_null_class_loader_data属性
ClassLoaderData::init_null_class_loader_data();
// 初始化属性
Universe::_finalizer_register_cache = new LatestMethodCache();
Universe::_loader_addClass_cache = new LatestMethodCache();
Universe::_pd_implies_cache = new LatestMethodCache();
Universe::_throw_illegal_access_error_cache = new LatestMethodCache();
//UseSharedSpaces默认为true,表示为元数据使用共享空间
if (UseSharedSpaces) {
//初始化共享空间
MetaspaceShared::initialize_shared_spaces();
StringTable::create_table();
} else {
//不使用共享空间时,分别初始化各个组件,SymbolTable表示符号表,StringTable表示字符串表
SymbolTable::create_table();
StringTable::create_table();
ClassLoader::create_package_info_table();
if (DumpSharedSpaces) {
MetaspaceShared::prepare_for_dumping();
}
}
if (strlen(VerifySubSet) > 0) {
Universe::initialize_verify_flags();
}
return JNI_OK;
}
jint Universe::initialize_heap() {
//如果使用ParallelGC
if (UseParallelGC) {
Universe::_collectedHeap = new ParallelScavengeHeap();
} else if (UseG1GC) {
//如果使用G1GC
G1CollectorPolicyExt* g1p = new G1CollectorPolicyExt();
g1p->initialize_all();
G1CollectedHeap* g1h = new G1CollectedHeap(g1p);
Universe::_collectedHeap = g1h;
} else {
//如果使用分代回收
GenCollectorPolicy *gc_policy;
//不同的回收策略
if (UseSerialGC) {
gc_policy = new MarkSweepPolicy();
} else if (UseConcMarkSweepGC) {
if (UseAdaptiveSizePolicy) {
gc_policy = new ASConcurrentMarkSweepPolicy();
} else {
gc_policy = new ConcurrentMarkSweepPolicy();
}
} else { // default old generation
gc_policy = new MarkSweepPolicy();
}
gc_policy->initialize_all();
Universe::_collectedHeap = new GenCollectedHeap(gc_policy);
}
//设置TLAB的最大值
ThreadLocalAllocBuffer::set_max_size(Universe::heap()->max_tlab_size());
//初始化collectedHeap
jint status = Universe::heap()->initialize();
if (status != JNI_OK) {
return status;
}
#ifdef _LP64
if (UseCompressedOops) {
//根据不同的堆内存大小设置narrow_oop_shift
if (((uint64_t)Universe::heap()->reserved_region().end() > OopEncodingHeapMax)) {
// Can't reserve heap below 32Gb.
// keep the Universe::narrow_oop_base() set in Universe::reserve_heap()
Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes);
} else {
Universe::set_narrow_oop_base(0);
if((uint64_t)Universe::heap()->reserved_region().end() > UnscaledOopHeapMax) {
// Can't reserve heap below 4Gb.
Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes);
} else {
Universe::set_narrow_oop_shift(0);
}
}
Universe::set_narrow_ptrs_base(Universe::narrow_oop_base());
//打印日志
if (PrintCompressedOopsMode || (PrintMiscellaneous && Verbose)) {
Universe::print_compressed_oops_mode(tty);
}
}
//校验Universe初始化是否正确
assert((intptr_t)Universe::narrow_oop_base() <= (intptr_t)(Universe::heap()->base() -
os::vm_page_size()) ||
Universe::narrow_oop_base() == NULL, "invalid value");
assert(Universe::narrow_oop_shift() == LogMinObjAlignmentInBytes ||
Universe::narrow_oop_shift() == 0, "invalid value");
#endif
if (UseTLAB) {
assert(Universe::heap()->supports_tlab_allocation(),
"Should support thread-local allocation buffers");
//TLAB的初始化
ThreadLocalAllocBuffer::startup_initialization();
}
return JNI_OK;
}
4、universe2_init
universe2_init方法是在universe_init方法执行完成后调用的,用来初始化基本类型的数组Klass,vmSymbols,SystemDictionary,JDK_Version等组件,其源码实现如下:
void universe2_init() {
EXCEPTION_MARK;
Universe::genesis(CATCH);
}
//用于检查当前线程是否存在待处理异常
#define EXCEPTION_MARK Thread* THREAD = NULL; ExceptionMark __em(THREAD);
ExceptionMark::ExceptionMark(Thread*& thread) {
//thread赋值
thread = Thread::current();
_thread = thread;
//检查当前线程是否存在异常
if (_thread->has_pending_exception()) {
//如果存在异常则清除
oop exception = _thread->pending_exception();
_thread->clear_pending_exception(); // Needed to avoid infinite recursion
//打印异常
exception->print();
//报告致命错误
fatal("ExceptionMark constructor expects no pending exceptions");
}
}
//用来检查某个方法是否抛出了异常,通常是在该方法的调用方中使用此宏,且已经明确目标方法不会抛出异常
#define CATCH \
THREAD); if (HAS_PENDING_EXCEPTION) { \
oop ex = PENDING_EXCEPTION; \
CLEAR_PENDING_EXCEPTION; \
ex->print(); \
ShouldNotReachHere(); \
} (void)(0
#define PENDING_EXCEPTION (((ThreadShadow*)THREAD)->pending_exception())
#define HAS_PENDING_EXCEPTION (((ThreadShadow*)THREAD)->has_pending_exception())
#define CLEAR_PENDING_EXCEPTION (((ThreadShadow*)THREAD)->clear_pending_exception())
void Universe::genesis(TRAPS) {
ResourceMark rm;
//FlagSetting通过构造函数临时将某个bool属性设置为指定值,在析构函数中将其恢复成原来的值
{ FlagSetting fs(_bootstrapping, true);
//获取锁Compile_lock
{ MutexLocker mc(Compile_lock);
//设置_base_vtable_size属性,实际就是取Object类的虚函数表的大小
compute_base_vtable_size();
//UseSharedSpaces表示为元数据使用共享空间,默认为true
if (!UseSharedSpaces) {
_boolArrayKlassObj = TypeArrayKlass::create_klass(T_BOOLEAN, sizeof(jboolean), CHECK);
_charArrayKlassObj = TypeArrayKlass::create_klass(T_CHAR, sizeof(jchar), CHECK);
_singleArrayKlassObj = TypeArrayKlass::create_klass(T_FLOAT, sizeof(jfloat), CHECK);
_doubleArrayKlassObj = TypeArrayKlass::create_klass(T_DOUBLE, sizeof(jdouble), CHECK);
_byteArrayKlassObj = TypeArrayKlass::create_klass(T_BYTE, sizeof(jbyte), CHECK);
_shortArrayKlassObj = TypeArrayKlass::create_klass(T_SHORT, sizeof(jshort), CHECK);
_intArrayKlassObj = TypeArrayKlass::create_klass(T_INT, sizeof(jint), CHECK);
_longArrayKlassObj = TypeArrayKlass::create_klass(T_LONG, sizeof(jlong), CHECK);
_typeArrayKlassObjs[T_BOOLEAN] = _boolArrayKlassObj;
_typeArrayKlassObjs[T_CHAR] = _charArrayKlassObj;
_typeArrayKlassObjs[T_FLOAT] = _singleArrayKlassObj;
_typeArrayKlassObjs[T_DOUBLE] = _doubleArrayKlassObj;
_typeArrayKlassObjs[T_BYTE] = _byteArrayKlassObj;
_typeArrayKlassObjs[T_SHORT] = _shortArrayKlassObj;
_typeArrayKlassObjs[T_INT] = _intArrayKlassObj;
_typeArrayKlassObjs[T_LONG] = _longArrayKlassObj;
ClassLoaderData* null_cld = ClassLoaderData::the_null_class_loader_data();
_the_array_interfaces_array = MetadataFactory::new_array<Klass*>(null_cld, 2, NULL, CHECK);
_the_empty_int_array = MetadataFactory::new_array<int>(null_cld, 0, CHECK);
_the_empty_short_array = MetadataFactory::new_array<u2>(null_cld, 0, CHECK);
_the_empty_method_array = MetadataFactory::new_array<Method*>(null_cld, 0, CHECK);
_the_empty_klass_array = MetadataFactory::new_array<Klass*>(null_cld, 0, CHECK);
}
}
//初始化符号表
vmSymbols::initialize(CHECK);
//初始化系统字典类
SystemDictionary::initialize(CHECK);
Klass* ok = SystemDictionary::Object_klass();
_the_null_string = StringTable::intern("null", CHECK);
_the_min_jint_string = StringTable::intern("-2147483648", CHECK);
if (UseSharedSpaces) {
//_the_array_interfaces_array表示数组对应的类默认实现的接口类,即Cloneable和Serializable接口
assert(_the_array_interfaces_array->at(0) ==
SystemDictionary::Cloneable_klass(), "u3");
assert(_the_array_interfaces_array->at(1) ==
SystemDictionary::Serializable_klass(), "u3");
} else {
// Set up shared interfaces array. (Do this before supers are set up.)
_the_array_interfaces_array->at_put(0, SystemDictionary::Cloneable_klass());
_the_array_interfaces_array->at_put(1, SystemDictionary::Serializable_klass());
}
//boolArrayKlassObj方法返回_boolArrayKlassObj属性,initialize_basic_type_klass用来初始化Klass部分属性
initialize_basic_type_klass(boolArrayKlassObj(), CHECK);
initialize_basic_type_klass(charArrayKlassObj(), CHECK);
initialize_basic_type_klass(singleArrayKlassObj(), CHECK);
initialize_basic_type_klass(doubleArrayKlassObj(), CHECK);
initialize_basic_type_klass(byteArrayKlassObj(), CHECK);
initialize_basic_type_klass(shortArrayKlassObj(), CHECK);
initialize_basic_type_klass(intArrayKlassObj(), CHECK);
initialize_basic_type_klass(longArrayKlassObj(), CHECK);
} // end of core bootstrapping
//初始化_objectArrayKlassObj
_objectArrayKlassObj = InstanceKlass::
cast(SystemDictionary::Object_klass())->array_klass(1, CHECK);
_objectArrayKlassObj->append_to_sibling_list();
// 根据某些类是否存在来初步判断JDK的版本
if (JDK_Version::is_partially_initialized()) {
uint8_t jdk_version;
Klass* k = SystemDictionary::resolve_or_null(
vmSymbols::java_lang_management_MemoryUsage(), THREAD);
CLEAR_PENDING_EXCEPTION; // ignore exceptions
if (k == NULL) {
k = SystemDictionary::resolve_or_null(
vmSymbols::java_lang_CharSequence(), THREAD);
CLEAR_PENDING_EXCEPTION; // ignore exceptions
if (k == NULL) {
k = SystemDictionary::resolve_or_null(
vmSymbols::java_lang_Shutdown(), THREAD);
CLEAR_PENDING_EXCEPTION; // ignore exceptions
if (k == NULL) {
jdk_version = 2;
} else {
jdk_version = 3;
}
} else {
jdk_version = 4;
}
} else {
jdk_version = 5;
}
//初始化JDK_Version
JDK_Version::fully_initialize(jdk_version);
}
//初始化ClassLoaderData的_dependencies属性
ClassLoaderData::the_null_class_loader_data()->init_dependencies(CHECK);
}
class FlagSetting {
bool val;
bool* flag;
public:
//flag指向目标属性,val是该属性原来的值,newValue是新值
FlagSetting(bool& fl, bool newValue) { flag = &fl; val = fl; fl = newValue; }
~FlagSetting() { *flag = val; }
};
void Universe::compute_base_vtable_size() {
_base_vtable_size = ClassLoader::compute_Object_vtable();
}
int ClassLoader::compute_Object_vtable() {
// hardwired for JDK1.2 -- would need to duplicate class file parsing
// code to determine actual value from file
// Would be value '11' if finals were in vtable
int JDK_1_2_Object_vtable_size = 5;
return JDK_1_2_Object_vtable_size * vtableEntry::size();
}
void initialize_basic_type_klass(Klass* k, TRAPS) {
Klass* ok = SystemDictionary::Object_klass();
if (UseSharedSpaces) {
ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
//检查k的超类是否是Object
assert(k->super() == ok, "u3");
//设置Klass的_class_loader_data,_java_mirror等属性
k->restore_unshareable_info(loader_data, Handle(), CHECK);
} else {
//将k的超类设置为Object
k->initialize_supers(ok, CHECK);
}
//将k加入到其父类Object的子类链表上
k->append_to_sibling_list();
}
static Klass* boolArrayKlassObj() { return _boolArrayKlassObj; }
5、universe_post_init
universe_post_init是在编译器等JVM主要组件都初始化完成后调用的,主要用来初始化Universe中定义的各种异常oop,CollectedHeap的再初始化,添加MemoryPool等,其源码实现如下:
bool universe_post_init() {
//is_init_completed是指JVM是否完成初始化
assert(!is_init_completed(), "Error: initialization not yet completed!");
Universe::_fully_initialized = true;
EXCEPTION_MARK;
{ ResourceMark rm;
//确保解释器初始化完成,实际解释器会在此方法之前通过interpreter_init方法完成初始化
Interpreter::initialize(); // needed for interpreter entry points
//UseSharedSpaces默认为true,表示元数据是否使用共享空间
if (!UseSharedSpaces) {
HandleMark hm(THREAD);
KlassHandle ok_h(THREAD, SystemDictionary::Object_klass());
Universe::reinitialize_vtable_of(ok_h, CHECK_false);
Universe::reinitialize_itables(CHECK_false);
}
}
HandleMark hm(THREAD);
Klass* k;
instanceKlassHandle k_h;
//初始化java.lang.Class 对应的klass数组
Universe::_the_empty_class_klass_array = oopFactory::new_objArray(SystemDictionary::Class_klass(), 0, CHECK_false);
//初始化不同场景下OutOfMemoryError对应的oop,实际都是一个类java_lang_OutOfMemoryError的实例
k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_OutOfMemoryError(), true, CHECK_false);
k_h = instanceKlassHandle(THREAD, k);
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);
//初始化java_lang_NullPointerException
// (this is currently used for a cheap & dirty solution in compiler exception handling)
k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_NullPointerException(), true, CHECK_false);
Universe::_null_ptr_exception_instance = InstanceKlass::cast(k)->allocate_instance(CHECK_false);
//初始化java_lang_ArithmeticException
// (this is currently used for a cheap & dirty solution in compiler exception handling)
k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_ArithmeticException(), true, CHECK_false);
Universe::_arithmetic_exception_instance = InstanceKlass::cast(k)->allocate_instance(CHECK_false);
//初始化java_lang_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);
//DumpSharedSpaces默认为false,如果为true,表示JVM会将加载的类Dump到一个文件上给其他的JVM使用
if (!DumpSharedSpaces) {
//设置不同类型的OutOfMemoryError的异常提示
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);
//初始化_preallocated_out_of_memory_error_array,PreallocatedOutOfMemoryErrorCount默认值为4
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_register_cache属性,对应java_lang_ref_Finalizer类的register(Object finalizee)方法
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);
//初始化_throw_illegal_access_error_cache属性,对应 Unsafe类的throwIllegalAccessError() 方法
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()) {
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);
//初始化属性_loader_addClass_cache,对应sun_reflect_DelegatingClassLoader类的addClass方法
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);
//初始化属性_pd_implies_cache,对应java_security_ProtectionDomain类的impliesCreateAccessControlContext方法
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()) {
tty->print_cr("ProtectionDomain.impliesCreateAccessControlContext() has the wrong linkage");
return false; // initialization failed
}
Universe::_pd_implies_cache->init(
SystemDictionary::ProtectionDomain_klass(), m);
}
//初始化jvm.cpp中定义的基类类型间的转换方法,如IntBitsToFloatFn,实际取的是包装类的方法,对应java/lang/Float类的intBitsToFloat方法
initialize_converter_functions();
//保证在第一次GC前调用,获取当前堆的容量和已使用内存,保存到_heap_capacity_at_last_gc和_heap_used_at_last_gc属性中
{
MutexLocker x(Heap_lock);
Universe::update_heap_info_at_gc();
}
//Java堆的初始化
Universe::heap()->post_initialize();
//初始化元空间的性能统计,开启UsePerfData时才有效,默认是false
MetaspaceCounters::initialize_performance_counters();
CompressedClassSpaceCounters::initialize_performance_counters();
//添加元空间对应的memory_pool
MemoryService::add_metaspace_memory_pools();
//添加Java堆对应的memory_pool
MemoryService::set_universe_heap(Universe::_collectedHeap);
#
return true;
}
void Universe::update_heap_info_at_gc() {
_heap_capacity_at_last_gc = heap()->capacity();
_heap_used_at_last_gc = heap()->used();
}
6、initialize_basic_type_mirrors
上述三个方法把Universe定义的静态属性基本都初始化了,除了基本类型对应的mirror_klass属性,如_int_mirror,_float_mirror等,这些属性都在initialize_basic_type_mirrors方法中完成,其实现如下:
该方法的调用链如下:
即执行universe2_init方法时会初始化上述属性。
7、reserve_heap
reserve_heap方法用于给Java堆申请一段连续的内存空间,同时计算在开启指针压缩时的指针基地址,所有的垃圾回收器在初始化的时候都会调用此方法,该方法的调用链如下图:
参考universe2_init方法中Java堆的初始化可知,Java堆就只有上图中的三种类型。
ReservedSpace Universe::reserve_heap(size_t heap_size, size_t alignment) {
//校验参数
assert(alignment <= Arguments::conservative_max_heap_alignment(),
err_msg("actual alignment " SIZE_FORMAT " must be within maximum heap alignment " SIZE_FORMAT,
alignment, Arguments::conservative_max_heap_alignment()));
//heap_size取整
size_t total_reserved = align_size_up(heap_size, alignment);
//使用指针压缩时堆空间不能超过OopEncodingHeapMax,是计算出来的,32G
assert(!UseCompressedOops || (total_reserved <= (OopEncodingHeapMax - os::vm_page_size())),
"heap size is too big for compressed oops");
//是否使用大内存页,UseLargePages默认是false
bool use_large_pages = UseLargePages && is_size_aligned(alignment, os::large_page_size());
assert(!UseLargePages
|| UseParallelGC
|| use_large_pages, "Wrong alignment to use large pages");
//计算Java堆的基地址
char* addr = Universe::preferred_heap_base(total_reserved, alignment, Universe::UnscaledNarrowOop);
//在执行构造方法的时候会向操作系统申请一段连续的内存空间
ReservedHeapSpace total_rs(total_reserved, alignment, use_large_pages, addr);
if (UseCompressedOops) {
//如果申请失败,即该地址已经被分配了,则重试重新申请,每次重试时使用的NARROW_OOP_MODE不同
if (addr != NULL && !total_rs.is_reserved()) {
addr = Universe::preferred_heap_base(total_reserved, alignment, Universe::ZeroBasedNarrowOop);
ReservedHeapSpace total_rs0(total_reserved, alignment,
use_large_pages, addr);
if (addr != NULL && !total_rs0.is_reserved()) {
//继续重试
addr = Universe::preferred_heap_base(total_reserved, alignment, Universe::HeapBasedNarrowOop);
assert(addr == NULL, "");
ReservedHeapSpace total_rs1(total_reserved, alignment,
use_large_pages, addr);
total_rs = total_rs1;
} else {
total_rs = total_rs0;
}
}
}
//重试依然失败,抛出异常
if (!total_rs.is_reserved()) {
vm_exit_during_initialization(err_msg("Could not reserve enough space for " SIZE_FORMAT "KB object heap", total_reserved/K));
return total_rs;
}
if (UseCompressedOops) {
//设置压缩指针的基地址
address base = (address)(total_rs.base() - os::vm_page_size());
Universe::set_narrow_oop_base(base);
}
return total_rs;
}
char* Universe::preferred_heap_base(size_t heap_size, size_t alignment, NARROW_OOP_MODE mode) {
//校验这些参数已经是取整过了
assert(is_size_aligned((size_t)OopEncodingHeapMax, alignment), "Must be");
assert(is_size_aligned((size_t)UnscaledOopHeapMax, alignment), "Must be");
assert(is_size_aligned(heap_size, alignment), "Must be");
//HeapBaseMinAddress表示Java堆的内存基地址,x86下默认是2G,将HeapBaseMinAddress按照alignment取整
uintx heap_base_min_address_aligned = align_size_up(HeapBaseMinAddress, alignment);
size_t base = 0;
//如果是64位系统
#ifdef _LP64
//如果开启指针压缩,64位下默认为true
if (UseCompressedOops) {
//校验mode合法
assert(mode == UnscaledNarrowOop ||
mode == ZeroBasedNarrowOop ||
mode == HeapBasedNarrowOop, "mode is invalid");
const size_t total_size = heap_size + heap_base_min_address_aligned;
//根据不同的NARROW_OOP_MODE分别计算
if (!FLAG_IS_DEFAULT(HeapBaseMinAddress) && (mode == UnscaledNarrowOop)) {
base = heap_base_min_address_aligned;
// If the total size is small enough to allow UnscaledNarrowOop then
// just use UnscaledNarrowOop.
} else if ((total_size <= OopEncodingHeapMax) && (mode != HeapBasedNarrowOop)) {
if ((total_size <= UnscaledOopHeapMax) && (mode == UnscaledNarrowOop) &&
(Universe::narrow_oop_shift() == 0)) {
// Use 32-bits oops without encoding and
// place heap's top on the 4Gb boundary
base = (UnscaledOopHeapMax - heap_size);
} else {
// Can't reserve with NarrowOopShift == 0
Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes);
if (mode == UnscaledNarrowOop ||
mode == ZeroBasedNarrowOop && total_size <= UnscaledOopHeapMax) {
// Use zero based compressed oops with encoding and
// place heap's top on the 32Gb boundary in case
// total_size > 4Gb or failed to reserve below 4Gb.
uint64_t heap_top = OopEncodingHeapMax;
// For small heaps, save some space for compressed class pointer
// space so it can be decoded with no base.
if (UseCompressedClassPointers && !UseSharedSpaces &&
OopEncodingHeapMax <= 32*G) {
uint64_t class_space = align_size_up(CompressedClassSpaceSize, alignment);
assert(is_size_aligned((size_t)OopEncodingHeapMax-class_space,
alignment), "difference must be aligned too");
uint64_t new_top = OopEncodingHeapMax-class_space;
if (total_size <= new_top) {
heap_top = new_top;
}
}
// Align base to the adjusted top of the heap
base = heap_top - heap_size;
}
}
} else {
// UnscaledNarrowOop encoding didn't work, and no base was found for ZeroBasedOops or
// HeapBasedNarrowOop encoding was requested. So, can't reserve below 32Gb.
Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes);
}
// Set narrow_oop_base and narrow_oop_use_implicit_null_checks
// used in ReservedHeapSpace() constructors.
// The final values will be set in initialize_heap() below.
if ((base != 0) && ((base + heap_size) <= OopEncodingHeapMax)) {
// Use zero based compressed oops
Universe::set_narrow_oop_base(NULL);
// Don't need guard page for implicit checks in indexed
// addressing mode with zero based Compressed Oops.
Universe::set_narrow_oop_use_implicit_null_checks(true);
} else {
// Set to a non-NULL value so the ReservedSpace ctor computes
// the correct no-access prefix.
// The final value will be set in initialize_heap() below.
Universe::set_narrow_oop_base((address)UnscaledOopHeapMax);
}
}
#endif
assert(is_ptr_aligned((char*)base, alignment), "Must be");
return (char*)base; // also return NULL (don't care) for 32-bit VM
}
上述方法中用到的NARROW_OOP_MODE的定义如下:
ReservedSpace类和ReservedHeapSpace类的说明参考《Hotspot 内存管理之CodeCache 源码解析》 中的讲解。
8、oops_do
oops_do用于以Universe定义的各种oop作为根节点遍历引用该oop的对象,垃圾回收时调用,该方法的实现如下图:
该方法的调用链如下: