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

本文深入解析Hotspot虚拟机Metaspace的内存管理,涵盖VirtualSpaceList、ChunkManager和SpaceManager的构造、内存分配与回收等关键操作。详细解读了get_new_chunk、chunk_freelist_allocate等核心方法的实现。
摘要由CSDN通过智能技术生成

  目录

一、VirtualSpaceList

1、构造和析构函数

2、get_new_chunk

 3、purge

二、ChunkManager

1、定义

2、 chunk_freelist_allocate

3、remove_chunk / return_chunks

三、SpaceManager

1、构造和析构函数

 2、allocate / deallocate

 3、get_initial_chunk_size


       在上一篇《Hotspot 内存管理之Metaspace(一) 源码解析》中讲解了 Metachunk 、Metablock、BlockFreelist、VirtualSpaceNode等基础类的定义和实现,本篇博客继续探讨在这些基础类之上的负责实际内存管理相关类的定义和实现,如SpaceManager,ChunkManager等。

一、VirtualSpaceList

      VirtualSpaceList在hotspot src/share/vm/memory/metaspace.cpp中,表示一个VirtualSpaceNode链表,负责创建和维护所有的VirtualSpaceNode。其定义的属性如下:

属性比较简单,重点关注以下方法的实现。

1、构造和析构函数

VirtualSpaceList::VirtualSpaceList(size_t word_size) :
                                   _is_class(false),
                                   _virtual_space_list(NULL),
                                   _current_virtual_space(NULL),
                                   _reserved_words(0),
                                   _committed_words(0),
                                   _virtual_space_count(0) {
  //获取锁expand_lock
  MutexLockerEx cl(SpaceManager::expand_lock(),
                   Mutex::_no_safepoint_check_flag);
  //创建一个新的virtual_space     
  create_new_virtual_space(word_size);
}

bool VirtualSpaceList::create_new_virtual_space(size_t vs_word_size) {
  assert_lock_strong(SpaceManager::expand_lock());
  //创建compressed class的VirtualSpace不会走到此分支
  if (is_class()) {
    assert(false, "We currently don't support more than one VirtualSpace for"
                  " the compressed class space. The initialization of the"
                  " CCS uses another code path and should not hit this path.");
    return false;
  }
  
  if (vs_word_size == 0) {
    assert(false, "vs_word_size should always be at least _reserve_alignment large.");
    return false;
  }

  size_t vs_byte_size = vs_word_size * BytesPerWord;
  //内存取整
  assert_is_size_aligned(vs_byte_size, Metaspace::reserve_alignment());

  //创建一个新的节点
  VirtualSpaceNode* new_entry = new VirtualSpaceNode(vs_byte_size);
  if (!new_entry->initialize()) {
     //初始化失败,返回false
    delete new_entry;
    return false;
  } else {
    //初始化成功,校验结果
    assert(new_entry->reserved_words() == vs_word_size,
        "Reserved memory size differs from requested memory size");
    //同步结果
    OrderAccess::storestore();
    link_vs(new_entry);
    return true;
  }
}

void VirtualSpaceList::link_vs(VirtualSpaceNode* new_entry) {
  //插入到链表中
  if (virtual_space_list() == NULL) {
      set_virtual_space_list(new_entry);
  } else {
    current_virtual_space()->set_next(new_entry);
  }
  set_current_virtual_space(new_entry);
  //增加计数
  inc_reserved_words(new_entry->reserved_words());
  inc_committed_words(new_entry->committed_words());
  inc_virtual_space_count();

  if (TraceMetavirtualspaceAllocation && Verbose) {
    //打印日志
    VirtualSpaceNode* vsl = current_virtual_space();
    vsl->print_on(gclog_or_tty);
  }
}

void VirtualSpaceList::inc_reserved_words(size_t v) {
  assert_lock_strong(SpaceManager::expand_lock());
  _reserved_words = _reserved_words + v;
}

void VirtualSpaceList::inc_committed_words(size_t v) {
  assert_lock_strong(SpaceManager::expand_lock());
  _committed_words = _committed_words + v;

  assert_committed_below_limit();
}

#define assert_committed_below_limit()                             \
  assert(MetaspaceAux::committed_bytes() <= MaxMetaspaceSize,      \
      err_msg("Too much committed memory. Committed: " SIZE_FORMAT \
              " limit (MaxMetaspaceSize): " SIZE_FORMAT,           \
          MetaspaceAux::committed_bytes(), MaxMetaspaceSize));

void VirtualSpaceList::inc_virtual_space_count() {
  assert_lock_strong(SpaceManager::expand_lock());
  _virtual_space_count++;
}

VirtualSpaceList::VirtualSpaceList(ReservedSpace rs) :
                                   _is_class(true),
                                   _virtual_space_list(NULL),
                                   _current_virtual_space(NULL),
                                   _reserved_words(0),
                                   _committed_words(0),
                                   _virtual_space_count(0) {
  MutexLockerEx cl(SpaceManager::expand_lock(),
                   Mutex::_no_safepoint_check_flag);                 
  VirtualSpaceNode* class_entry = new VirtualSpaceNode(rs);
  bool succeeded = class_entry->initialize();
  if (succeeded) {
    link_vs(class_entry);
  }
}


VirtualSpaceList::~VirtualSpaceList() {
  //从链表头元素开始遍历,释放所有的VirtualSpaceNode
  VirtualSpaceListIterator iter(virtual_space_list());
  while (iter.repeat()) {
    VirtualSpaceNode* vsl = iter.get_next();
    delete vsl;
  }
}

VirtualSpaceListIterator的实现非常简单,如下:

2、get_new_chunk

      get_new_chunk用于获取一个新的满足大小要求的Metachunk,是VirtualSpaceList的核心方法,其调用链如下:

源码实现如下:

Metachunk* VirtualSpaceList::get_new_chunk(size_t chunk_word_size, size_t suggested_commit_granularity) {

  //从当前的VirtualSpaceNode节点分配一个Metachunk
  Metachunk* next = current_virtual_space()->get_chunk_vs(chunk_word_size);
  
  if (next != NULL) {
    //分配成功则返回
    return next;
  }

  //当前节点内存不足,需要扩展创建一个新的节点,扩展的量是根据要求分配的chunk_word_size内存大小计算的,而不是当前节点剩余的已提交内存
  //对chunk_word_size做内存取整
  size_t min_word_size       = align_size_up(chunk_word_size,              Metaspace::commit_alignment_words());
  size_t preferred_word_size = align_size_up(suggested_commit_granularity, Metaspace::commit_alignment_words());
  if (min_word_size >= preferred_word_size) {
    // Can happen when humongous chunks are allocated.
    preferred_word_size = min_word_size;
  }
  //按照min_word_size重新创建一个新的VirtualSpaceNode
  bool expanded = expand_by(min_word_size, preferred_word_size);
  if (expanded) {
     //如果创建成功,则使用新的节点创建一个Metachunk
    next = current_virtual_space()->get_chunk_vs(chunk_word_size);
    assert(next != NULL, "The allocation was expected to succeed after the expansion");
  }

   return next;
}


bool VirtualSpaceList::expand_by(size_t min_words, size_t preferred_words) {
  //校验参数
  assert_is_size_aligned(min_words,       Metaspace::commit_alignment_words());
  assert_is_size_aligned(preferred_words, Metaspace::commit_alignment_words());
  assert(min_words <= preferred_words, "Invalid arguments");

  //MetaspaceGC根据当前已经提交的总内存量和Metaspace最大内存量判断能否扩展
  if (!MetaspaceGC::can_expand(min_words, this->is_class())) {
    return  false;
  }
  size_t allowed_expansion_words = MetaspaceGC::allowed_expansion();
  if (allowed_expansion_words < min_words) {
    return false;
  }
 
  //因为preferred_words和allowed_expansion_words都是大于或者等于min_words,所以取两者的最小值也能满足要求
  size_t max_expansion_words = MIN2(preferred_words, allowed_expansion_words);

  //尝试当前节点扩展
  bool vs_expanded = expand_node_by(current_virtual_space(),
                                    min_words,
                                    max_expansion_words);
  //扩展成功
  if (vs_expanded) {
    return true;
  }
  //节点创建时申请的reserved_size的剩余空间不足导致扩展失败,回收当前节点
  retire_current_virtual_space();

  //取两者间的最大值,并做内存取整
  size_t grow_vs_words = MAX2((size_t)VirtualSpaceSize, preferred_words);
  grow_vs_words = align_size_up(grow_vs_words, Metaspace::reserve_alignment_words());
  //创建一个新的节点
  if (create_new_virtual_space(grow_vs_words)) {
     //pre_committed即创建的时候已经完成commited
    if (current_virtual_space()->is_pre_committed()) {
      // The memory was pre-committed, so we are done here.
      assert(min_words <= current_virtual_space()->committed_words(),
          "The new VirtualSpace was pre-committed, so it"
          "should be large enough to fit the alloc request.");
      return true;
    }
    //非pre_committed,需要手动commited
    return expand_node_by(current_virtual_space(),
                          min_words,
                          max_expansion_words);
  }

  return false;
}

bool VirtualSpaceList
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值