目录
3、remove_chunk / return_chunks
在上一篇《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