20.5 字典表创建和基础类预加载
20.5.1 systemDictionary.cpp/hpp
20.5.1.1 SystemDictionary::initialize
void SystemDictionary::initialize(TRAPS) {
// Allocate arrays
assert(dictionary() == NULL,
"SystemDictionary should only be initialized once");
_sdgeneration = 0;
// 创建字典(就是Hash Table)
_dictionary = new Dictionary(calculate_systemdictionary_size(PredictedLoadedClassCount));
// 创建占位符表(就是Hash Table)
_placeholders = new PlaceholderTable(_nof_buckets);
_number_of_modifications = 0;
// 创建约束表(就是Hash Table)
_loader_constraints = new LoaderConstraintTable(_loader_constraint_size);
// 创建解析错误表(就是Hash Table)
_resolution_errors = new ResolutionErrorTable(_resolution_error_size);
// 创建调用方法符号表(就是Hash Table)
_invoke_method_table = new SymbolPropertyTable(_invoke_method_size);
// 分配一个数组来存放系统类加载锁
_system_loader_lock_obj = oopFactory::new_intArray(0, CHECK);
// 初始化基础类,细节继续看`章节20.5.1.2`
initialize_preloaded_classes(CHECK);
#if INCLUDE_JFR
jfr_event_handler_proxy = SymbolTable::new_permanent_symbol("jdk/jfr/proxy/internal/EventHandlerProxy", CHECK);
#endif // INCLUDE_JFR
}
20.5.1.2 initialize_preloaded_classes
这一部分也用到了很多宏定义,咱们先把宏展开后再来讲解
class SystemDictionary : AllStatic {
friend class VMStructs;
friend class SystemDictionaryHandles;
public:
enum WKID {
NO_WKID = 0,
#define WK_KLASS_ENUM(name, symbol, ignore_o) WK_KLASS_ENUM_NAME(name), WK_KLASS_ENUM_NAME(symbol) = WK_KLASS_ENUM_NAME(name),
WK_KLASSES_DO(WK_KLASS_ENUM)
#undef WK_KLASS_ENUM
WKID_LIMIT,
FIRST_WKID = NO_WKID + 1
};
}
// ==============第1块宏:枚举=================
// 宏展开前
#define WK_KLASS_ENUM(name, symbol, ignore_o) WK_KLASS_ENUM_NAME(name), WK_KLASS_ENUM_NAME(symbol) = WK_KLASS_ENUM_NAME(name),
WK_KLASSES_DO(WK_KLASS_ENUM)
// 宏展开后
// 第1步
WK_KLASS_ENUM(String_klass,java_lang_String,Pre)
WK_KLASS_ENUM_NAME(String_klass), WK_KLASS_ENUM_NAME(java_lang_String) = WK_KLASS_ENUM_NAME(String_klass),
// 第2步
// 前置宏定义
#define WK_KLASS_ENUM_NAME(kname) kname##_knum
String_klass_knum,java_lang_String_knum=String_klass_knum
// 最终 enum WKID 宏展开后
enum WKID {
NO_WKID = 0,
Object_klass_knum, java_lang_Object_knum = Object_klass_knum, \
String_klass_knum, java_lang_String_knum = String_klass_knum, \
Class_klass_knum, java_lang_Class_knum = Class_klass_knum, \
Cloneable_klass_knum, java_lang_Cloneable_knum = Cloneable_klass_knum, \
ClassLoader_klass_knum, java_lang_ClassLoader_knum = ClassLoader_klass_knum, \
Serializable_klass_knum, java_io_Serializable_knum = Serializable_klass_knum, \
System_klass_knum, java_lang_System_knum = System_klass_knum, \
...
WKID_LIMIT,
FIRST_WKID = NO_WKID + 1
};
// ==============第2块宏:函数=================
// 方法的宏展开前
#define WK_KLASS_DECLARE(name, symbol, option) \
static Klass* name() { return check_klass_##option(_well_known_klasses[WK_KLASS_ENUM_NAME(name)]); } \
static Klass** name##_addr() { \
return &SystemDictionary::_well_known_klasses[SystemDictionary::WK_KLASS_ENUM_NAME(name)]; \
}
WK_KLASSES_DO(WK_KLASS_DECLARE);
#undef WK_KLASS_DECLARE
// 方法的宏展开后,这里以 Object_klass为例,其他的类推
static Klass* Object_klass() {
return check_klass_pre(_well_known_klasses[Object_klass_knum]);
}
static Klass** Object_klass_addr() {
return &SystemDictionary::_well_known_klasses[SystemDictionary::Object_klass_knum];
}
// ==============第3块宏:wk_init_info数组=================
// 宏展开前
static const short wk_init_info[] = {
#define WK_KLASS_INIT_INFO(name, symbol, option) \
( ((int)vmSymbols::VM_SYMBOL_ENUM_NAME(symbol) \
<< SystemDictionary::CEIL_LG_OPTION_LIMIT) \
| (int)SystemDictionary::option ),
WK_KLASSES_DO(WK_KLASS_INIT_INFO)
#undef WK_KLASS_INIT_INFO
0
};
// 宏展开后,这里还是以 Object_klass 为例,其他的类推
static const short wk_init_info[] = {
( ((int)vmSymbols::java_lang_Object_enum << SystemDictionary::CEIL_LG_OPTION_LIMIT)
| (int)SystemDictionary::Pre ),
0
};
要使用的宏已经展开了,下面接着讲正题
void SystemDictionary::initialize_preloaded_classes(TRAPS) {
assert(WK_KLASS(Object_klass) == NULL, "preloaded classes should only be initialized once");
// Preload commonly used klasses
WKID scan = FIRST_WKID;
// first do Object, then String, Class
if (UseSharedSpaces) {
initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(Object_klass), scan, CHECK);
// Initialize the constant pool for the Object_class
InstanceKlass* ik = InstanceKlass::cast(Object_klass());
ik->constants()->restore_unshareable_info(CHECK);
initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(Class_klass), scan, CHECK);
} else {
// 直接看这一步,这个的实现往后看,完成后,那些基础的类就被加载进来了,现在知道为啥我们在Java代码时,基础类(Object/Class/String等)都是不需要额外加载和import进来的,原因就在这
initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(Class_klass), scan, CHECK);
}
// 计算String 和 Class 类的字段偏移
java_lang_String::compute_offsets();
java_lang_Class::compute_offsets();
// 给8个基础类型创建它们的Class类型对象(在虚拟机中就是InstanceMirrorKlass)
Universe::initialize_basic_type_mirrors(CHECK);
// 修正mirror
Universe::fixup_mirrors(CHECK);
// 接下来都是继续加载基础类
initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(Reference_klass), scan, CHECK);
// Preload ref klasses and set reference types
InstanceKlass::cast(WK_KLASS(Reference_klass))->set_reference_type(REF_OTHER);
InstanceRefKlass::update_nonstatic_oop_maps(WK_KLASS(Reference_klass));
initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(Cleaner_klass), scan, CHECK);
InstanceKlass::cast(WK_KLASS(SoftReference_klass))->set_reference_type(REF_SOFT);
InstanceKlass::cast(WK_KLASS(WeakReference_klass))->set_reference_type(REF_WEAK);
InstanceKlass::cast(WK_KLASS(FinalReference_klass))->set_reference_type(REF_FINAL);
InstanceKlass::cast(WK_KLASS(PhantomReference_klass))->set_reference_type(REF_PHANTOM);
InstanceKlass::cast(WK_KLASS(Cleaner_klass))->set_reference_type(REF_CLEANER);
initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(ReferenceQueue_klass), scan, CHECK);
// JSR 292 classes
WKID jsr292_group_start = WK_KLASS_ENUM_NAME(MethodHandle_klass);
WKID jsr292_group_end = WK_KLASS_ENUM_NAME(VolatileCallSite_klass);
initialize_wk_klasses_until(jsr292_group_start, scan, CHECK);
if (EnableInvokeDynamic) {
initialize_wk_klasses_through(jsr292_group_end, scan, CHECK);
} else {
// Skip the JSR 292 classes, if not enabled.
scan = WKID(jsr292_group_end + 1);
}
initialize_wk_klasses_until(WKID_LIMIT, scan, CHECK);
// 基础类型的包装类的Klass
_box_klasses[T_BOOLEAN] = WK_KLASS(Boolean_klass);
_box_klasses[T_CHAR] = WK_KLASS(Character_klass);
_box_klasses[T_FLOAT] = WK_KLASS(Float_klass);
_box_klasses[T_DOUBLE] = WK_KLASS(Double_klass);
_box_klasses[T_BYTE] = WK_KLASS(Byte_klass);
_box_klasses[T_SHORT] = WK_KLASS(Short_klass);
_box_klasses[T_INT] = WK_KLASS(Integer_klass);
_box_klasses[T_LONG] = WK_KLASS(Long_klass);
//_box_klasses[T_OBJECT] = WK_KLASS(object_klass);
//_box_klasses[T_ARRAY] = WK_KLASS(object_klass);
{
// 计算加载类时应该使用 loadClass 还是 loadClassInternal
Method* method = InstanceKlass::cast(ClassLoader_klass())->find_method(vmSymbols::loadClassInternal_name(), vmSymbols::string_class_signature());
_has_loadClassInternal = (method != NULL);
}
{
// 计算要不要用 checkPackageAccess 方法
Method* method = InstanceKlass::cast(ClassLoader_klass())->find_method(vmSymbols::checkPackageAccess_name(), vmSymbols::class_protectiondomain_signature());
_has_checkPackageAccess = (method != NULL);
}
}
SystemDictionary::initialize_wk_klasses_until文章来源:https://www.toymoban.com/news/detail-803495.html
void SystemDictionary::initialize_wk_klasses_until(WKID limit_id, WKID &start_id, TRAPS) {
assert((int)start_id <= (int)limit_id, "IDs are out of order!");
// 这里就是遍历 WKID 枚举,把基础类都加载一遍,看本章节前面对宏展开的那块
for (int id = (int)start_id; id < (int)limit_id; id++) {
assert(id >= (int)FIRST_WKID && id < (int)WKID_LIMIT, "oob");
int info = wk_init_info[id - FIRST_WKID];
int sid = (info >> CEIL_LG_OPTION_LIMIT);
int opt = (info & right_n_bits(CEIL_LG_OPTION_LIMIT));
// 直接看这,这一步完成后,就对基础加载完成了,继续往后看
initialize_wk_klass((WKID)id, opt, CHECK);
}
// 下一次开始的位置换到本次limit的位置
start_id = limit_id;
}
SystemDictionary::initialize_wk_klass文章来源地址https://www.toymoban.com/news/detail-803495.html
bool SystemDictionary::initialize_wk_klass(WKID id, int init_opt, TRAPS) {
assert(id >= (int)FIRST_WKID && id < (int)WKID_LIMIT, "oob");
int info = wk_init_info[id - FIRST_WKID];
int sid = (info >> CEIL_LG_OPTION_LIMIT);
// 拿到对应的符号
Symbol* symbol = vmSymbols::symbol_at((vmSymbols::SID)sid);
// 从数组 _well_known_klasses 中拿到已加载的类
Klass** klassp = &_well_known_klasses[id];
bool must_load = (init_opt < SystemDictionary::Opt);
if ((*klassp) == NULL) { // 初始klassp肯定是null
// 下面就是真正类加载的环节了,这个先不讲,留待后续类加载一章来讲
if (must_load) {
(*klassp) = resolve_or_fail(symbol, true, CHECK_0); // 加载必须的类
} else {
(*klassp) = resolve_or_null(symbol, CHECK_0); // 加载可选的类
}
}
return ((*klassp) != NULL);
}
到了这里,关于Hotspot源码解析-第二十章-字典表创建和基础类预加载(四)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!