Hotspot源码解析-第十章

发布时间:2024年01月02日

第十章

10.1 全局数据结构初始化

10.1.1 init.cpp

10.1.1.1 vm_init_globals
void vm_init_globals() {
  // 验证ThreadShadow的实现,主要是验证线程对象的_pending_exception属性位置,_pending_exception后面用到时再讲
  check_ThreadShadow();
  // 基础类型初始化,看`章节10.1.2.1`
  basic_types_init();
  eventlog_init(); // 各种事件日志初始化,不影响主流程,先忽略
  mutex_init(); // 各种互斥锁的初始化,不影响主流程,先忽略
  // 内存(块)池初始化,提前分配内存,类似线程池,提升内存分配的性能,分配细节看`章节10.1.3`
  chunkpool_init(); 
  /*
  * 热点性能数据存储内存初始化。热点性能数据的收集通过-XX:+UsePerfData控制开通与否,默认是开通的。
  * 启用 PerfData 后,HotSpot JVM 会在目录下为每个 JVM 进程创建一个文件。通过工具扫描此目录
  * 以查找正在运行的 JVM。如果禁用 PerfData,这些工具将不会自动发现JVM
  * jstat 是依赖于热点性能数据的标准 JDK 工具之一。 不适用于禁用了性能数据的 JVM。
  * 细节上,这块也可以忽略
  */
  perfMemory_init();
}

10.1.2 globalDefinitions.cpp

10.1.2.1 basic_types_init
void basic_types_init() {
    // 下面的操作就是验证各个类型的在32位和64位机器上的内存占用位数
#ifdef ASSERT
#ifdef _LP64
  assert(min_intx ==  (intx)CONST64(0x8000000000000000), "correct constant");
  assert(max_intx ==  CONST64(0x7FFFFFFFFFFFFFFF), "correct constant");
  assert(max_uintx == CONST64(0xFFFFFFFFFFFFFFFF), "correct constant");
  assert( 8 == sizeof( intx),      "wrong size for basic type");
  assert( 8 == sizeof( jobject),   "wrong size for basic type");
#else
  assert(min_intx ==  (intx)0x80000000,  "correct constant");
  assert(max_intx ==  0x7FFFFFFF,  "correct constant");
  assert(max_uintx == 0xFFFFFFFF,  "correct constant");
  assert( 4 == sizeof( intx),      "wrong size for basic type");
  assert( 4 == sizeof( jobject),   "wrong size for basic type");
#endif
  assert( (~max_juint) == 0,  "max_juint has all its bits");
  assert( (~max_uintx) == 0,  "max_uintx has all its bits");
  assert( (~max_julong) == 0, "max_julong has all its bits");
  assert( 1 == sizeof( jbyte),     "wrong size for basic type");
  assert( 2 == sizeof( jchar),     "wrong size for basic type");
  assert( 2 == sizeof( jshort),    "wrong size for basic type");
  assert( 4 == sizeof( juint),     "wrong size for basic type");
  assert( 4 == sizeof( jint),      "wrong size for basic type");
  assert( 1 == sizeof( jboolean),  "wrong size for basic type");
  assert( 8 == sizeof( jlong),     "wrong size for basic type");
  assert( 4 == sizeof( jfloat),    "wrong size for basic type");
  assert( 8 == sizeof( jdouble),   "wrong size for basic type");
  assert( 1 == sizeof( u1),        "wrong size for basic type");
  assert( 2 == sizeof( u2),        "wrong size for basic type");
  assert( 4 == sizeof( u4),        "wrong size for basic type");

  // 验证各个基础类型代表的字符,比如B代表byte,C代表char,依此类推
  int num_type_chars = 0;
  for (int i = 0; i < 99; i++) {
    if (type2char((BasicType)i) != 0) {
      assert(char2type(type2char((BasicType)i)) == i, "proper inverses");
      num_type_chars++;
    }
  }
  // 类型个数只能是11个,8个基础类型 + 1个void类型 + 1个object类型 + 1个array类型
  assert(num_type_chars == 11, "must have tested the right number of mappings");
  assert(char2type(0) == T_ILLEGAL, "correct illegality");

  {
    for (int i = T_BOOLEAN; i <= T_CONFLICT; i++) {
      BasicType vt = (BasicType)i;
      BasicType ft = type2field[vt];
      switch (vt) {
      // the following types might plausibly show up in memory layouts:
      case T_BOOLEAN:
      case T_BYTE:
      case T_CHAR:
      case T_SHORT:
      case T_INT:
      case T_FLOAT:
      case T_DOUBLE:
      case T_LONG:
      case T_OBJECT:
      case T_ADDRESS:     // random raw pointer
      case T_METADATA:    // metadata pointer
      case T_NARROWOOP:   // compressed pointer
      case T_NARROWKLASS: // compressed klass pointer
      case T_CONFLICT:    // might as well support a bottom type
      case T_VOID:        // padding or other unaddressed word
        // layout type must map to itself
        assert(vt == ft, "");
        break;
      default:
        // non-layout type must map to a (different) layout type
        assert(vt != ft, "");
        assert(ft == type2field[ft], "");
      }
      // every type must map to same-sized layout type:
      assert(type2size[vt] == type2size[ft], "");
    }
  }
  // These are assumed, e.g., when filling HeapWords with juints.
  assert(is_power_of_2(sizeof(juint)), "juint must be power of 2");
  assert(is_power_of_2(HeapWordSize), "HeapWordSize must be power of 2");
  assert((size_t)HeapWordSize >= sizeof(juint),
         "HeapWord should be at least as large as juint");
  assert(sizeof(NULL) == sizeof(char*), "NULL must be same size as pointer");
#endif
  // 设置Java与OS的线程优先级对应关系,默认都是-1(JavaPriority1_To_OSPriority到JavaPriority10_To_OSPriority初始值都是-1),也就是没有优先级
  if( JavaPriority1_To_OSPriority != -1 )
    os::java_to_os_priority[1] = JavaPriority1_To_OSPriority;
  if( JavaPriority2_To_OSPriority != -1 )
    os::java_to_os_priority[2] = JavaPriority2_To_OSPriority;
  if( JavaPriority3_To_OSPriority != -1 )
    os::java_to_os_priority[3] = JavaPriority3_To_OSPriority;
  if( JavaPriority4_To_OSPriority != -1 )
    os::java_to_os_priority[4] = JavaPriority4_To_OSPriority;
  if( JavaPriority5_To_OSPriority != -1 )
    os::java_to_os_priority[5] = JavaPriority5_To_OSPriority;
  if( JavaPriority6_To_OSPriority != -1 )
    os::java_to_os_priority[6] = JavaPriority6_To_OSPriority;
  if( JavaPriority7_To_OSPriority != -1 )
    os::java_to_os_priority[7] = JavaPriority7_To_OSPriority;
  if( JavaPriority8_To_OSPriority != -1 )
    os::java_to_os_priority[8] = JavaPriority8_To_OSPriority;
  if( JavaPriority9_To_OSPriority != -1 )
    os::java_to_os_priority[9] = JavaPriority9_To_OSPriority;
  if(JavaPriority10_To_OSPriority != -1 )
    os::java_to_os_priority[10] = JavaPriority10_To_OSPriority;

  // Set the size of basic types here (after argument parsing but before
  // stub generation).
  if (UseCompressedOops) {  // 压缩指针,为了降低学习难度,又不失去完整流程的学习,先忽略压缩指针情况
    // Size info for oops within java objects is fixed
    heapOopSize        = jintSize;
    LogBytesPerHeapOop = LogBytesPerInt;
    LogBitsPerHeapOop  = LogBitsPerInt;
    BytesPerHeapOop    = BytesPerInt;
    BitsPerHeapOop     = BitsPerInt;
  } else {
    // 堆对象指针内存占用大小,32位机器占4字节,64位机器占8字节
    heapOopSize        = oopSize;
    // 每个字(word)的字节的幂次方,32位机器为2,64位机器为3
    LogBytesPerHeapOop = LogBytesPerWord;
    // 每个堆对象指针的位数的幂次方,32位机器为5,64位机器为6
    LogBitsPerHeapOop  = LogBitsPerWord;
    // 每个字(word)的字节的数,32位机器为4字节,64位机器为8字节,
    BytesPerHeapOop    = BytesPerWord;
    // 每个堆对象指针的位数,32位机器为32位,64位机器为64位
    BitsPerHeapOop     = BitsPerWord;
  }
  // object和array在jvm中的表现都是指针,所以就是 heapOopSize 的值
  _type2aelembytes[T_OBJECT] = heapOopSize;
  _type2aelembytes[T_ARRAY]  = heapOopSize;
}

10.1.3 allocation.cpp

10.1.3.1 chunkpool_init
void chunkpool_init() {
  ChunkPool::initialize();
}
/*
* 将chunk分为4种大小
*/
static void initialize() {
    // 为了满足各种内存大小的分配,分别按4种类型的大小创建chunk池,其实就是将Chunk组成一个链表,ChunkPool指向链表的表头
    _large_pool  = new ChunkPool(Chunk::size        + Chunk::aligned_overhead_size());
    _medium_pool = new ChunkPool(Chunk::medium_size + Chunk::aligned_overhead_size());
    _small_pool  = new ChunkPool(Chunk::init_size   + Chunk::aligned_overhead_size());
    _tiny_pool   = new ChunkPool(Chunk::tiny_size   + Chunk::aligned_overhead_size());
  }

allocation.hpp中的定义的Chunk类

Chunk类是继承自CHeapObj类的,当new Chunk的时候也是通过CHeapObj类的new的实现完成的内存分配,由CHeapObj的名字可以看出,new分配内存时是在C堆内存下通过malloc系统调用函数分配的,注意,这里讲的是C堆,不是Java堆。

class Chunk: CHeapObj<mtChunk> {
  friend class VMStructs;

 protected:
  Chunk*       _next;     // Next Chunk in list
  const size_t _len;      // Size of this Chunk
 public:
  void* operator new(size_t size, AllocFailType alloc_failmode, size_t length) throw();
  void  operator delete(void* p);
  Chunk(size_t length);

  enum {
    // default sizes; make them slightly smaller than 2**k to guard against
    // buddy-system style malloc implementations
#ifdef _LP64
    slack      = 40,            // [RGV] Not sure if this is right, but make it
                                //       a multiple of 8.
#else
    slack      = 20,            // suspected sizeof(Chunk) + internal malloc headers
#endif
    // 最小的chunk大小,slack就是chunk本身的大小,可以忽略这个slack占用的内存
    tiny_size  =  256  - slack, // Size of first chunk (tiny)
    // 1k大小的chunk
    init_size  =  1*K  - slack, // Size of first chunk (normal aka small)
    // 10k大小的chunk
    medium_size= 10*K  - slack, // Size of medium-sized chunk
    // 32k大小的chunk  
    size       = 32*K  - slack, // Default size of an Arena chunk (following the first)
    // 1k + 32 字节大小的非池化的chunk大小
    non_pool_size = init_size + 32 // An initial size which is not one of above
  };
// 其他代码省略
}
文章来源:https://blog.csdn.net/zhang527294844/article/details/135345498
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。