Hotspot源码解析-第二十章-系统类及其方法以符号形式存储在符号表(三)

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,                   "")  /*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,                   "")                                   \
  template(class_initializer_name,                    "")                                 \
  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,                        "")                                                \
                                                                                                                  \
  /* 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< (1<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* 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;
    }
  }

你可能感兴趣的:(Java虚拟机,java)