20.4 系统类及其方法以符号形式存储在符号表
20.4.1 vmSymbolls.cpp/hpp
20.4.1.1 vmSymbols::initialize
这块实现中用到了很多宏定义,所以在讲解时,需要先宏展开,下面根据用到的顺序介绍各个宏定义及其宏展开结果
#define VM_SYMBOL_BODY(name, string) string "\0"
static const char* vm_symbol_bodies = VM_SYMBOLS_DO(VM_SYMBOL_BODY, VM_ALIAS_IGNORE);
// 下面这段宏由于篇幅问题,只列出了部分宏定义,但是不影响解读,要想知道更多,可以直接看源码
#define VM_SYMBOLS_DO(template, do_alias) \
/* commonly used class names */ \
template(java_lang_System, "java/lang/System") \
template(java_lang_Object, "java/lang/Object") \
template(java_lang_Class, "java/lang/Class") \
template(java_lang_String, "java/lang/String") \
template(java_lang_Thread, "java/lang/Thread") \
\
/* Java runtime version access */ \
template(sun_misc_Version, "sun/misc/Version") \
template(java_runtime_name_name, "java_runtime_name") \
template(java_runtime_version_name, "java_runtime_version") \
\
/* class file format tags */ \
template(tag_source_file, "SourceFile") \
template(tag_inner_classes, "InnerClasses") \
template(tag_constant_value, "ConstantValue") \
template(tag_code, "Code") \
\
/* exception klasses: at least all exceptions thrown by the VM have entries here */ \
template(java_lang_ArithmeticException, "java/lang/ArithmeticException") \
template(java_lang_ArrayIndexOutOfBoundsException, "java/lang/ArrayIndexOutOfBoundsException") \
template(java_lang_ArrayStoreException, "java/lang/ArrayStoreException") \
template(java_lang_ClassCastException, "java/lang/ClassCastException") \
template(java_lang_ClassNotFoundException, "java/lang/ClassNotFoundException") \
\
/* error klasses: at least all errors thrown by the VM have entries here */ \
template(java_lang_AbstractMethodError, "java/lang/AbstractMethodError") \
template(java_lang_ClassCircularityError, "java/lang/ClassCircularityError") \
template(java_lang_ClassFormatError, "java/lang/ClassFormatError") \
\
/* Concurrency support */ \
template(java_util_concurrent_locks_AbstractOwnableSynchronizer, "java/util/concurrent/locks/AbstractOwnableSynchronizer") \
template(java_util_concurrent_atomic_AtomicIntegerFieldUpdater_Impl, "java/util/concurrent/atomic/AtomicIntegerFieldUpdater$AtomicIntegerFieldUpdaterImpl") \
template(java_util_concurrent_atomic_AtomicLongFieldUpdater_CASUpdater, "java/util/concurrent/atomic/AtomicLongFieldUpdater$CASUpdater") \
template(java_util_concurrent_atomic_AtomicLongFieldUpdater_LockedUpdater, "java/util/concurrent/atomic/AtomicLongFieldUpdater$LockedUpdater") \
template(java_util_concurrent_atomic_AtomicReferenceFieldUpdater_Impl, "java/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl") \
template(sun_misc_Contended_signature, "Lsun/misc/Contended;") \
\
/* class symbols needed by intrinsics */ \
VM_INTRINSICS_DO(VM_INTRINSIC_IGNORE, template, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE) \
\
/* Support for reflection based on dynamic bytecode generation (JDK 1.4 and above) */ \
\
template(sun_reflect_FieldInfo, "sun/reflect/FieldInfo") \
template(sun_reflect_MethodInfo, "sun/reflect/MethodInfo") \
template(sun_reflect_MagicAccessorImpl, "sun/reflect/MagicAccessorImpl") \
template(sun_reflect_MethodAccessorImpl, "sun/reflect/MethodAccessorImpl") \
template(sun_reflect_ConstructorAccessorImpl, "sun/reflect/ConstructorAccessorImpl") \
template(newConstructor_signature, "(Lsun/reflect/MethodInfo;)Ljava/lang/reflect/Constructor;") \
template(newField_name, "newField") \
template(newField_signature, "(Lsun/reflect/FieldInfo;)Ljava/lang/reflect/Field;") \
template(newMethod_name, "newMethod") \
template(newMethod_signature, "(Lsun/reflect/MethodInfo;)Ljava/lang/reflect/Method;") \
template(invokeBasic_name, "invokeBasic") \
template(linkToVirtual_name, "linkToVirtual") \
template(linkToStatic_name, "linkToStatic") \
template(linkToSpecial_name, "linkToSpecial") \
template(linkToInterface_name, "linkToInterface") \
template(compiledLambdaForm_name, "<compiledLambdaForm>") /*fake name*/ \
template(star_name, "*") /*not really a name*/ \
template(invoke_name, "invoke") \
template(override_name, "override") \
template(parameterTypes_name, "parameterTypes") \
template(returnType_name, "returnType") \
template(signature_name, "signature") \
template(slot_name, "slot") \
\
/* Support for annotations (JDK 1.5 and above) */ \
\
template(annotations_name, "annotations") \
template(index_name, "index") \
template(executable_name, "executable") \
template(parameter_annotations_name, "parameterAnnotations") \
template(annotation_default_name, "annotationDefault") \
template(sun_reflect_ConstantPool, "sun/reflect/ConstantPool") \
template(ConstantPool_name, "constantPoolOop") \
template(sun_reflect_UnsafeStaticFieldAccessorImpl, "sun/reflect/UnsafeStaticFieldAccessorImpl")\
template(base_name, "base") \
/* Type Annotations (JDK 8 and above) */ \
template(type_annotations_name, "typeAnnotations") \
\
\
/* Support for JSR 292 & invokedynamic (JDK 1.7 and above) */ \
template(java_lang_invoke_CallSite, "java/lang/invoke/CallSite") \
template(java_lang_invoke_ConstantCallSite, "java/lang/invoke/ConstantCallSite") \
template(java_lang_invoke_DirectMethodHandle, "java/lang/invoke/DirectMethodHandle") \
template(java_lang_invoke_MutableCallSite, "java/lang/invoke/MutableCallSite") \
template(java_lang_invoke_VolatileCallSite, "java/lang/invoke/VolatileCallSite") \
template(java_lang_invoke_MethodHandle, "java/lang/invoke/MethodHandle") \
template(java_lang_invoke_MethodType, "java/lang/invoke/MethodType") \
template(java_lang_invoke_MethodType_signature, "Ljava/lang/invoke/MethodType;") \
template(java_lang_invoke_MemberName_signature, "Ljava/lang/invoke/MemberName;") \
template(java_lang_invoke_LambdaForm_signature, "Ljava/lang/invoke/LambdaForm;") \
template(java_lang_invoke_MethodHandle_signature, "Ljava/lang/invoke/MethodHandle;") \
/* internal classes known only to the JVM: */ \
template(java_lang_invoke_MemberName, "java/lang/invoke/MemberName") \
template(java_lang_invoke_MethodHandleNatives, "java/lang/invoke/MethodHandleNatives") \
template(java_lang_invoke_LambdaForm, "java/lang/invoke/LambdaForm") \
template(java_lang_invoke_ForceInline_signature, "Ljava/lang/invoke/ForceInline;") \
template(java_lang_invoke_DontInline_signature, "Ljava/lang/invoke/DontInline;") \
template(java_lang_invoke_InjectedProfile_signature, "Ljava/lang/invoke/InjectedProfile;") \
template(java_lang_invoke_Stable_signature, "Ljava/lang/invoke/Stable;") \
template(java_lang_invoke_LambdaForm_Compiled_signature, "Ljava/lang/invoke/LambdaForm$Compiled;") \
template(java_lang_invoke_LambdaForm_Hidden_signature, "Ljava/lang/invoke/LambdaForm$Hidden;") \
/* internal up-calls made only by the JVM, via class sun.invoke.MethodHandleNatives: */ \
template(findMethodHandleType_name, "findMethodHandleType") \
template(findMethodHandleType_signature, "(Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/invoke/MethodType;") \
template(linkMethodHandleConstant_name, "linkMethodHandleConstant") \
template(linkMethodHandleConstant_signature, "(Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/invoke/MethodHandle;") \
template(linkMethod_name, "linkMethod") \
template(linkMethod_signature, "(Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/String;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/invoke/MemberName;") \
template(linkCallSite_name, "linkCallSite") \
template(linkCallSite_signature, "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/invoke/MemberName;") \
template(setTargetNormal_name, "setTargetNormal") \
template(setTargetVolatile_name, "setTargetVolatile") \
template(setTarget_signature, "(Ljava/lang/invoke/MethodHandle;)V") \
NOT_LP64( do_alias(intptr_signature, int_signature) ) \
LP64_ONLY( do_alias(intptr_signature, long_signature) ) \
\
/* common method and field names */ \
template(object_initializer_name, "<init>") \
template(class_initializer_name, "<clinit>") \
template(println_name, "println") \
template(printStackTrace_name, "printStackTrace") \
template(main_name, "main") \
template(name_name, "name") \
template(priority_name, "priority") \
template(stillborn_name, "stillborn") \
template(group_name, "group") \
template(daemon_name, "daemon") \
template(eetop_name, "eetop") \
template(thread_status_name, "threadStatus") \
template(run_method_name, "run") \
template(exit_method_name, "exit") \
template(add_method_name, "add") \
template(remove_method_name, "remove") \
template(parent_name, "parent") \
template(threads_name, "threads") \
template(groups_name, "groups") \
template(maxPriority_name, "maxPriority") \
template(destroyed_name, "destroyed") \
template(vmAllowSuspension_name, "vmAllowSuspension") \
template(nthreads_name, "nthreads") \
template(ngroups_name, "ngroups") \
template(shutdown_method_name, "shutdown") \
template(finalize_method_name, "finalize") \
template(reference_lock_name, "lock") \
\
/* non-intrinsic name/signature pairs: */ \
template(register_method_name, "register") \
do_alias(register_method_signature, object_void_signature) \
\
/* name symbols needed by intrinsics */ \
VM_INTRINSICS_DO(VM_INTRINSIC_IGNORE, VM_SYMBOL_IGNORE, template, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE) \
\
/* common signatures names */ \
template(void_method_signature, "()V") \
template(void_boolean_signature, "()Z") \
template(void_byte_signature, "()B") \
template(void_char_signature, "()C") \
template(void_short_signature, "()S") \
template(byte_signature, "B") \
template(char_signature, "C") \
template(double_signature, "D") \
template(byte_array_signature, "[B") \
template(char_array_signature, "[C") \
template(int_array_signature, "[I") \
template(object_void_signature, "(Ljava/lang/Object;)V") \
template(object_int_signature, "(Ljava/lang/Object;)I") \
template(char_array_void_signature, "([C)V") \
template(int_int_void_signature, "(II)V") \
template(long_long_void_signature, "(JJ)V") \
/* signature symbols needed by intrinsics */ \
VM_INTRINSICS_DO(VM_INTRINSIC_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, template, VM_ALIAS_IGNORE) \
\
/* symbol aliases needed by intrinsics */ \
VM_INTRINSICS_DO(VM_INTRINSIC_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, do_alias) \
\
/* returned by the C1 compiler in case there's not enough memory to allocate a new symbol*/ \
template(dummy_symbol, "illegal symbol") \
\
/* used by ClassFormatError when class name is not known yet */ \
template(unknown_class_name, "<Unknown>") \
\
/* used to identify class loaders handling parallel class loading */ \
template(parallelCapable_name, "parallelLockMap") \
\
/* JVM monitoring and management support */ \
template(java_lang_StackTraceElement_array, "[Ljava/lang/StackTraceElement;") \
template(java_lang_management_ThreadState, "java/lang/management/ThreadState") \
template(java_lang_management_MemoryUsage, "java/lang/management/MemoryUsage") \
/* JVMTI/java.lang.instrument support and VM Attach mechanism */ \
template(sun_misc_VMSupport, "sun/misc/VMSupport") \
template(appendToClassPathForInstrumentation_name, "appendToClassPathForInstrumentation") \
do_alias(appendToClassPathForInstrumentation_signature, string_void_signature) \
template(serializePropertiesToByteArray_name, "serializePropertiesToByteArray") \
template(serializePropertiesToByteArray_signature, "()[B") \
template(serializeAgentPropertiesToByteArray_name, "serializeAgentPropertiesToByteArray") \
template(classRedefinedCount_name, "classRedefinedCount") \
template(classLoader_name, "classLoader") \
\
/* jfr signatures */ \
JFR_TEMPLATES(template) \
\
/*end*/
上面代码,存在三个宏定义,我们一个个来解开谜底
首先是
static const char* vm_symbol_bodies = VM_SYMBOLS_DO(VM_SYMBOL_BODY, VM_ALIAS_IGNORE);
这里用到了宏VM_SYMBOLS_DO(VM_SYMBOL_BODY, VM_ALIAS_IGNORE);定义如下:
#define VM_SYMBOLS_DO(template, do_alias)
/* commonly used class names */
template(java_lang_System, “java/lang/System”)
template(java_lang_Object, “java/lang/Object”) \
那么这一段展开后就是:
static const char* vm_symbol_bodies = VM_SYMBOL_BODY(java_lang_System, “java/lang/System”) \
VM_SYMBOL_BODY(java_lang_Object, “java/lang/Object”)\
…后面的依次排开就行
, VM_ALIAS_IGNORE; // 这个宏定义是一个空值,可以忽略
上面展开后,又用到了另一个宏定义:
#define VM_SYMBOL_BODY(name, string) string “\0”
继续展开后
static const char* vm_symbol_bodies = “java/lang/System” "\0"“java/lang/Object” “\0”…依此排开,后面还有好多
到此,全部宏展开后,得到 vm_symbol_bodies 的值,就是一个通过"\0"来分隔的字符串。好了,现在继续下面的解析
void vmSymbols::initialize(TRAPS) {
assert((int)SID_LIMIT <= (1<<log2_SID_LIMIT), "must fit in this bitfield");
assert((int)SID_LIMIT*5 > (1<<log2_SID_LIMIT), "make the bitfield smaller, please");
assert(vmIntrinsics::FLAG_LIMIT <= (1 << vmIntrinsics::log2_FLAG_LIMIT), "must fit in this bitfield");
if (!UseSharedSpaces) {
// 取出vm_symbol_bodies的首地址
const char* string = &vm_symbol_bodies[0];
// FIRST_SID 和 SID_LIMIT 都是 vmSymbols 类中的枚举 SID 的项,该枚举中也用到了宏定义 VM_SYMBOLS_DO,这里就不再做展开处理了,有兴趣的读者,根据我上面展开的方式,自行展开。总之,这一步就是遍历 FIRST_SID 到 SID_LIMIT,这里说明一下,枚举项最终都会转成整型存储,
for (int index = (int)FIRST_SID; index < (int)SID_LIMIT; index++) {
// 检查符号表,如果有该符号就取出,没有则创建,具体实现后面有描述
Symbol* sym = SymbolTable::new_permanent_symbol(string, CHECK);
_symbols[index] = sym;
string += strlen(string); // skip string body
string += 1; // skip trailing null
}
// 设置各类型的签名,签名的定义在vmSymbols.hpp文件中
_type_signatures[T_BYTE] = byte_signature(); // B
_type_signatures[T_CHAR] = char_signature(); // C 下面不列了,自己查吧
_type_signatures[T_DOUBLE] = double_signature();
_type_signatures[T_FLOAT] = float_signature();
_type_signatures[T_INT] = int_signature();
_type_signatures[T_LONG] = long_signature();
_type_signatures[T_SHORT] = short_signature();
_type_signatures[T_BOOLEAN] = bool_signature();
_type_signatures[T_VOID] = void_signature();
// no single signatures for T_OBJECT or T_ARRAY
}
#ifdef ASSERT
// 双层for循环,验证有没有重复的符号
for (int i1 = (int)FIRST_SID; i1 < (int)SID_LIMIT; i1++) {
Symbol* sym = symbol_at((SID)i1);
for (int i2 = (int)FIRST_SID; i2 < i1; i2++) {
if (symbol_at((SID)i2) == sym) {
tty->print("*** Duplicate VM symbol SIDs %s(%d) and %s(%d): \"",
vm_symbol_enum_name((SID)i2), i2,
vm_symbol_enum_name((SID)i1), i1);
sym->print_symbol_on(tty);
tty->print_cr("\"");
}
}
}
#endif //ASSERT
// 为了查找方便,为符号创建对应的索引
{
for (int index = (int)FIRST_SID; index < (int)SID_LIMIT; index++) {
vm_symbol_index[index] = (SID)index;
}
int num_sids = SID_LIMIT-FIRST_SID;
// 调用库函数qsort对数组vm_symbol_index按元素地址进行排序
qsort(&vm_symbol_index[FIRST_SID], num_sids, sizeof(vm_symbol_index[0]),
compare_vmsymbol_sid);
}
#ifdef ASSERT
{
// 最后,抽查字符串、符号和枚举之间的对应关系:
assert(_symbols[NO_SID] == NULL, "must be");
const char* str = "java/lang/Object";
TempNewSymbol jlo = SymbolTable::new_permanent_symbol(str, CHECK);
assert(strncmp(str, (char*)jlo->base(), jlo->utf8_length()) == 0, "");
assert(jlo == java_lang_Object(), "");
SID sid = VM_SYMBOL_ENUM_NAME(java_lang_Object);
assert(find_sid(jlo) == sid, "");
assert(symbol_at(sid) == jlo, "");
// Make sure find_sid produces the right answer in each case.
for (int index = (int)FIRST_SID; index < (int)SID_LIMIT; index++) {
Symbol* sym = symbol_at((SID)index);
sid = find_sid(sym);
assert(sid == (SID)index, "symbol index works");
// Note: If there are duplicates, this assert will fail.
// A "Duplicate VM symbol" message will have already been printed.
}
//尽管format是java.lang.String的方法名,但是它依然不是虚拟字符号,这里要加以验证
str = "format";
TempNewSymbol fmt = SymbolTable::new_permanent_symbol(str, CHECK);
sid = find_sid(fmt);
assert(sid == NO_SID, "symbol index works (negative test)");
}
#endif
}
new_permanent_symbol
Symbol* SymbolTable::new_permanent_symbol(const char* name, TRAPS) {
unsigned int hash;
// 先从符号表SymbolTable中根据hash和name来查找,这里参考Java的HashMap查找的方式
Symbol* result = SymbolTable::lookup_only((char*)name, (int)strlen(name), hash);
if (result != NULL) {
return result; // 查到了,就不会重复创建,直接取出来
}
// Grab SymbolTable_lock first.
MutexLocker ml(SymbolTable_lock, THREAD);
// 拿到符号表指针
SymbolTable* table = the_table();
// 计算hash对应的索引
int index = table->hash_to_index(hash);
// 将新的符号插入到符号表中,实现细节,看接下来的代码描述
return table->basic_add(index, (u1*)name, (int)strlen(name), hash, false, THREAD);
}
basic_add
Symbol* SymbolTable::basic_add(int index_arg, u1 *name, int len,
unsigned int hashValue_arg, bool c_heap, TRAPS) {
assert(!Universe::heap()->is_in_reserved(name),
"proposed name of symbol must be stable");
// 字符太长,不允许
if (len > Symbol::max_length()) {
THROW_MSG_0(vmSymbols::java_lang_InternalError(),
"name is too long to represent");
}
// Cannot hit a safepoint in this function because the "this" pointer can move.
No_Safepoint_Verifier nsv;
// Check if the symbol table has been rehashed, if so, need to recalculate
// the hash value and index.
unsigned int hashValue;
int index;
// 设置hash值和索引index
if (use_alternate_hashcode()) {
hashValue = hash_symbol((const char*)name, len);
index = hash_to_index(hashValue);
} else {
hashValue = hashValue_arg;
index = index_arg;
}
// 考虑多线程问题,需要再次尝试去符号表中查找一遍
Symbol* test = lookup(index, (char*)name, len, hashValue);
if (test != NULL) {
// A race occurred and another thread introduced the symbol.
assert(test->refcount() != 0, "lookup should have incremented the count");
return test;
}
// 创建一个新的字符,接下来再看看它在哪分配内存
Symbol* sym = allocate_symbol(name, len, c_heap, CHECK_NULL);
assert(sym->equals((char*)name, len), "symbol must be properly initialized");
// 封装成 HashtableEntry
HashtableEntry<Symbol*, mtSymbol>* entry = new_entry(hashValue, sym);
// 将 entry 添加到 hash table
add_entry(index, entry);
return sym; // 返回该字符
}
symbolTable.cpp -> SymbolTable::allocate_symbol
Symbol* SymbolTable::allocate_symbol(const u1* name, int len, bool c_heap, TRAPS) {
assert (len <= Symbol::max_length(), "should be checked by caller");
Symbol* sym;
if (DumpSharedSpaces) {
// Allocate all symbols to CLD shared metaspace
sym = new (len, ClassLoaderData::the_null_class_loader_data(), THREAD) Symbol(name, len, -1);
} else if (c_heap) {
// refcount starts as 1
sym = new (len, THREAD) Symbol(name, len, 1);
assert(sym != NULL, "new should call vm_exit_out_of_memory if C_HEAP is exhausted");
} else {
// 看这一行,继续往下看
sym = new (len, arena(), THREAD) Symbol(name, len, -1);
}
return sym;
}
symbol.cpp -> new
void* Symbol::operator new(size_t sz, int len, Arena* arena, TRAPS) throw() {
int alloc_size = size(len)*HeapWordSize; // 计算要分配内存的字节大小
// 在arena管辖的区域内分配,arena的初始化和定义的实现可以回头看`章节19.2`,怎么分配的呢,就把它理解成一个带刻度的水缸,往里面加水时,刻度值上升,就这么简单。接着往下看
address res = (address)arena->Amalloc(alloc_size);
return res;
}
arena.hpp -> Amalloc
void* Amalloc(size_t x) {
#ifdef _LP64
x = (x + (8-1)) & ((unsigned)(-8));
#else
x = (x + (4-1)) & ((unsigned)(-4));
#endif
if (_hwm + x > _max) {
return grow(x); // 该区域内存不够了,要扩容
} else {
char *old = _hwm;
_hwm += x; // 看这里,就是把_hwm往上升x的字节
return old;
}
}
后续将通过抖音视频/直播的形式分享技术,由于前期要做一些准备和规划,预计2024年6月开始,欢迎关注,如有需要或问题咨询,也可直接抖音沟通交流。