目录
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_s