Hotspot 内存管理之Metaspace(三) 源码解析

    目录

一、Metaspace

1、定义

2、ergo_initialize / global_initialize / post_initialize

3、构造和析构函数

4、allocate / deallocate

5、expand_and_allocate

 6、purge

二、总结

1、内存结构图

2、类数据结构


 在《Hotspot 内存管理之Metaspace(二) 源码解析》中讲解了负责Metaspace内存管理的VirtualSpaceList,ChunkManager,SpaceManager的实现,本篇博客重点讲解最外层的Metaspace的相关接口的实现。

一、Metaspace

1、定义

    Metaspace的定义位于hotspot src/share/vm/memory/metaspace.hpp中,Metaspace表示用来给Klass等元数据分配内存的一个内存空间,通常称为元空间,每个ClassLoader实例包括启动类加载器都会创建一个对应的Metaspace实例,每个Metaspace实例都有一个SpaceManager实例,通过SpaceManager完成内存分配与管理。Metaspace定义的属性如下:

  • static size_t _compressed_class_space_size;  //compressed class对应的Metaspace大小
  • static size_t _first_chunk_word_size;  //第一个NonClassType类型的MetaChunk的大小
  • static size_t _first_class_chunk_word_size; //第一个ClassType类型的MetaChunk的大小
  •  static size_t _commit_alignment;  //commit内存的粒度
  •  static size_t _reserve_alignment;  //reserve内存的粒度
  •  SpaceManager* _vsm;  //NonClassType类型的元数据对应的SpaceManager
  •  SpaceManager* _class_vsm; //ClassType类型的元数据对应的SpaceManager
  • static VirtualSpaceList* _space_list;  // NonClassType类型的元数据对应的VirtualSpaceList
  • static VirtualSpaceList* _class_space_list; // ClassType类型的元数据对应的VirtualSpaceList
  • static ChunkManager* _chunk_manager_metadata;   //NonClassType类型的元数据对应的ChunkManager
  • static ChunkManager* _chunk_manager_class;  // ClassType类型的元数据对应的ChunkManager
  • static const MetaspaceTracer* _tracer; //打印日志使用
  • AllocRecord * _alloc_record_head;  //AllocRecord链表的头部元素
  • AllocRecord * _alloc_record_tail; //AllocRecord链表的尾部元素

注意上述 ClassType类型的ChunkManager和VirtualSpaceList具体是指开启UseCompressedClassPointers下用来存储Class等元数据的元空间。

 AllocRecord类的定义如下:

就是一个简单的记录内存分配结果的数据结构。重点关注以下方法的实现。 

2、ergo_initialize / global_initialize / post_initialize

      ergo_initialize、global_initialize、post_initialize这三个方法都是Metaspace的初始化方法,ergo_initialize用于初始化Metaspace的各种参数,如MetaspaceSize,MaxMetaspaceSize,MinMetaspaceExpansion等;global_initialize方法用于初始化_first_chunk_word_size,_space_list,_chunk_manager_metadata等静态属性;post_initialize就调用MetaspaceGC::post_initialize方法。各方法的调用链如下:

三个的源码实现如下,其中DumpSharedSpaces表示将共享的Metaspace空间dump到一个文件中,给其他JVM使用,默认为false;UseCompressedOops和UseCompressedClassPointers表示使用压缩的oop指针和Klass指针,64位下默认为true;UseSharedSpaces表示使用基于文件的共享Metaspace,即不同的JVM进程通过将Metaspace映射到同一个文件实现Metaspace共享,默认为false。

void Metaspace::ergo_initialize() {
  if (DumpSharedSpaces) {
    // Using large pages when dumping the shared archive is currently not implemented.
    FLAG_SET_ERGO(bool, UseLargePagesInMetaspace, false);
  }

  size_t page_size = os::vm_page_size();
  if (UseLargePages && UseLargePagesInMetaspace) {
    page_size = os::large_page_size();
  }

  //初始化参数
  _commit_alignment  = page_size;
  _reserve_alignment = MAX2(page_size, (size_t)os::vm_allocation_granularity());

  MaxMetaspaceSize = align_size_down_bounded(MaxMetaspaceSize, _reserve_alignment);

  if (MetaspaceSize > MaxMetaspaceSize) {
    MetaspaceSize = MaxMetaspaceSize;
  }

  MetaspaceSize = align_size_down_bounded(MetaspaceSize, _commit_alignment);

  assert(MetaspaceSize <= MaxMetaspaceSize, "MetaspaceSize should be limited by MaxMetaspaceSize");

  if (MetaspaceSize < 256*K) {
    vm_exit_during_initialization("Too small initial Metaspace size");
  }

  MinMetaspaceExpansion = align_size_down_bounded(MinMetaspaceExpansion, _commit_alignment);
  MaxMetaspaceExpansion = align_size_down_bounded(MaxMetaspaceExpansion, _commit_alignment);

  CompressedClassSpaceSize = align_size_down_bounded(CompressedClassSpaceSize, _reserve_alignment);
  set_compressed_class_space_size(CompressedClassSpaceSize);

  //VIRTUALSPACEMULTIPLIER的值是2
  uintx min_metaspace_sz =
      VIRTUALSPACEMULTIPLIER * InitialBootClassLoaderMetaspaceSize;
  if (UseCompressedClassPointers) {
    if ((min_metaspace_sz + CompressedClassSpaceSize) >  MaxMetaspaceSize) {
      if (min_metaspace_sz >= MaxMetaspaceSize) {
        vm_exit_during_initialization("MaxMetaspaceSize is too small.");
      } else {
        FLAG_SET_ERGO(uintx, CompressedClassSpaceSize,
                      MaxMetaspaceSize - min_metaspace_sz);
      }
    }
  } else if (min_metaspace_sz >= MaxMetaspaceSize) {
    FLAG_SET_ERGO(uintx, InitialBootClassLoaderMetaspaceSize,
                  min_metaspace_sz);
  }

}

 static void set_compressed_class_space_size(size_t size) {
    _compressed_class_space_size = size;
  }


void Metaspace::global_initialize() {
  MetaspaceGC::initialize();

  // Initialize the alignment for shared spaces.
  int max_alignment = os::vm_allocation_granularity();
  size_t cds_total = 0;

  MetaspaceShared::set_max_alignment(max_alignment);
  //DumpSharedSpaces默认为false
  if (DumpSharedSpaces) {
#if INCLUDE_CDS
    MetaspaceShared::estimate_regions_size();

    SharedReadOnlySize  = align_size_up(SharedReadOnlySize,  max_alignment);
    SharedReadWriteSize = align_size_up(SharedReadWriteSize, max_alignment);
    SharedMiscDataSize  = align_size_up(SharedMiscDataSize,  max_alignment);
    SharedMiscCodeSize  = align_size_up(SharedMiscCodeSize,  max_alignment);

    // the min_misc_code_size e
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值