前言
本文主要介绍Heap的构造函数,从构造函数里大量使用各种Space,可以看出ART虚拟机的一个重要的特点就是大量使用映射内存。主要代码在art/runtime/gc/heap.cc里。
第一部分
主要完成了boot镜像所需art文件的加载,然后得到一系列的ImageSpace对象,最后再保存到Heap对应的成员变量中。
static const char* kDlMallocSpaceName[2] = {
"main dlmalloc space", "main dlmalloc space 1"};
static const char* kRosAllocSpaceName[2] = {
"main rosalloc space", "main rosalloc space 1"};
static const char* kMemMapSpaceName[2] = {
"main space", "main space 1"};
static const char* kNonMovingSpaceName = "non moving space";
static const char* kZygoteSpaceName = "zygote space";
Heap::Heap(size_t initial_size.....)
:max_allowed_footprint_(initial_size),
native_footprint_gc_watermark_(initial_size),
foreground_collector_type_(foreground_collector_type),
background_collector_type_(background_collector_type),
desired_collector_type_(foreground_collector_type_),
...{
Runtime* const runtime = Runtime::Current();
// 设置垃圾回收器类型
ChangeCollector(desired_collector_type_);
// 初始化两个bitmap
live_bitmap_.reset(new accounting::HeapBitmap(this));
mark_bitmap_.reset(new accounting::HeapBitmap(this));
// 加载ImageSpace,
// 主要完成了boot镜像所需art文件的加载,然后得到一系列的ImageSpace对象,最后再保存到Heap对应的成员变量中
if (!image_file_name.empty()) {
std::vector<std::string> image_file_names;
image_file_names.push_back(image_file_name);
// The loaded spaces. Secondary images may fail to load, in which case we need to remove already added spaces.
std::vector<space::Space*> added_image_spaces;
uint8_t* const original_requested_alloc_space_begin = requested_alloc_space_begin;
for (size_t index = 0; index < image_file_names.size(); ++index) {
std::string& image_name = image_file_names[index];
std::string error_msg;
space::ImageSpace* boot_image_space = space::ImageSpace::CreateBootImage(
image_name.c_str(),
image_instruction_set,
index > 0,
&error_msg);
if (boot_image_space != nullptr) {
// Oat files referenced by image files immediately follow them in memory, ensure alloc space isn't going to get in the middle
// 将boot_image_space保存到heap对应的管理模块中
AddSpace(boot_image_space);
added_image_spaces.push_back(boot_image_space);
// oat文件
uint8_t* oat_file_end_addr = boot_image_space->GetImageHeader().GetOatFileEnd();
requested_alloc_space_begin = AlignUp(oat_file_end_addr, kPageSize);
// heap里的成员变量,保存art文件对应的ImageSpace对象
boot_image_spaces_.push_back(boot_image_space);
// ...
}
}
第二部分
主要创建各种Space,各种Space类下篇介绍;
构造函数里初始化的重要参数解释如下:
- foreground_collector_type:当应用程序处于前台(即用户能感知的情况)时GC的类型。此处为kCollectorTypeCMS(以后简称CMS)
- background_collector_type:当应用程序位于后台时GC的类型。此处为kCollectorTypeHomogeneousSpaceCompact (以后简称HSC)。注意,这是一种空间压缩的方法,可减少内存碎片。但需要较长时间暂停程序的运行,所以只能在程序位于后台(用户不可见)的时候来执行。
- non_moving_space_capacity: 对应runtime_options.def中的NonMovingSpaceCapacity参数,默认取值为Heap.h文件中的kDefaultNonMovingSpaceCapacity(64MB)。
- large_0bject_space_type参数,x86平台上其取值为kMap
- large_object_threshold参数,默认取值为Heap.h的kDefaultLargeObjectThreshold(大小为3个内存页,此处为12K B)。
- initial_size:取自dalvik.vm.heapstartsize
- capacity,取自dalvik.vm.heapsize
- growth_limit:取自dalvik.vm.heapgrowthlimit
bool support_homogeneous_space_compaction =
background_collector_type_ == gc::kCollectorTypeHomogeneousSpaceCompact ||
use_homogeneous_space_compaction_for_oom_;
std::unique_ptr<MemMap> main_mem_map_1;
std::unique_ptr<MemMap> main_mem_map_2;
uint8_t* request_begin = requested_alloc_space_begin;
if (request_begin != nullptr && separate_non_moving_space) {
request_begin += non_moving_space_capacity; // +64M
}
std::unique_ptr<MemMap> non_moving_space_mem_map;
if (separate_non_moving_space) {
const char* space_name = is_zygote ? kZygoteSpaceName: kNonMovingSpaceName;
// Reserve the non moving mem map before the other two since it needs to be at a specific address.
non_moving_space_mem_map.reset(
MemMap::MapAnonymous(space_name, requested_alloc_space_begin,
non_moving_space_capacity, PROT_READ | PROT_WRITE, true, false,
&error_str));
// Try to reserve virtual memory at a lower address if we have a separate non moving space.
request_begin = reinterpret_cast<uint8_t*>(300 * MB); // 0x12C00000
}
// kMemMapSpaceName[0]值为main_space,大小为capacity,内存地址从0x12C00000开始
if (foreground_collector_type_ != kCollectorTypeCC) {
if (separate_non_moving_space || !is_zygote) {
main_mem_map_1.reset(MapAnonymousPreferredAddress(kMemMapSpaceName[0], request_begin, capacity_, &error_str));
} else {
// If no separate non-moving space and we are the zygote, the main space must come right after the image space to avoid a gap. This is required since we want the zygote space to be adjacent to the image space.
main_mem_map_1.reset(MemMap::MapAnonymous(kMemMapSpaceName[0], request_begin, capacity_, PROT_READ | PROT_WRITE, true, false, &error_str));
}
}
// kMemMapSpaceName[1]值为main space 1,Create main mem map 2,内存地址紧跟main space
if (support_homogeneous_space_compaction || background_collector_type_ == kCollectorTypeSS || foreground_collector_type_ == kCollectorTypeSS) {
main_mem_map_2.reset(MapAnonymousPreferredAddress(kMemMapSpaceName[1], main_mem_map_1->End(), capacity_, &error_str));
}
// Create the non moving space first so that bitmaps don't take up the address range. 是一个DlMallocSpace
if (separate_non_moving_space) {
const size_t size = non_moving_space_mem_map->Size(); // 默认为64M
non_moving_space_ = space::DlMallocSpace::CreateFromMemMap(
non_moving_space_mem_map.release(), "zygote / non moving space", kDefaultStartingSize,
initial_size, size, size, false);
non_moving_space_->SetFootprintLimit(non_moving_space_->Capacity());
AddSpace(non_moving_space_);
}
// Create other spaces based on whether or not we have a moving GC.
if (foreground_collector_type_ == kCollectorTypeCC) {
...
} else if (IsMovingGc(foreground_collector_type_) && foreground_collector_type_ != kCollectorTypeGSS) {
...
} else {
// 初始化成员变量main_space,根据kUseRosAlloc常量值判断use rosalloc/RosAllocSpace instead of dlmalloc/DlMallocSpace,并赋值给dlmalloc_space_或rosalloc_space_
CreateMainMallocSpace(main_mem_map_1.release(), initial_size, growth_limit_, capacity_);
AddSpace(main_space_);
if (foreground_collector_type_ == kCollectorTypeGSS) {
...
} else if (main_mem_map_2.get() != nullptr) {
// 初始化成员变量main_space_backup_,Pointer to the space which becomes the new main space when we do homogeneous space compaction.
const char* name = kUseRosAlloc ? kRosAllocSpaceName[1] : kDlMallocSpaceName[1];
main_space_backup_.reset(CreateMallocSpaceFromMemMap(main_mem_map_2.release(), initial_size, growth_limit_, capacity_, name, true));
AddSpace(main_space_backup_.get());
}
}
// Allocate the large object space.
if (large_object_space_type == space::LargeObjectSpaceType::kFreeList) {
large_object_space_ = space::FreeListSpace::Create("free list large object space", nullptr, capacity_);
} else if (large_object_space_type == space::LargeObjectSpaceType::kMap) {
large_object_space_ = space::LargeObjectMapSpace::Create("mem map large object space");
} else {
// Disable the large object space by making the cutoff excessively large.
large_object_threshold_ = std::numeric_limits<size_t>::max();
large_object_space_ = nullptr;
}
if (large_object_space_ != nullptr) {
AddSpace(large_object_space_);
}
// Remove the main backup space since it slows down the GC to have unused extra spaces.
// 从堆管理中移除main_space_backup_
if (main_space_backup_.get() != nullptr) {
RemoveSpace(main_space_backup_.get());
}
// Allocate the card table.
// Start at 64 KB, we can be sure there are no spaces mapped this low since the address range is reserved by the kernel.
static constexpr size_t kMinHeapAddress = 4 * KB;
card_table_.reset(accounting::CardTable::Create(reinterpret_cast<uint8_t*>(kMinHeapAddress), 4 * GB - kMinHeapAddress));
if (HasBootImageSpace()) {
// 为每一个ImageSpace创建一个ModUnionTable
for (space::ImageSpace* image_space : GetBootImageSpaces()) {
accounting::ModUnionTable* mod_union_table = new accounting::ModUnionTableToZygoteAllocspace( "Image mod-union table", this, image_space);
AddModUnionTable(mod_union_table);
}
}
// 创建RememberSet
if (collector::SemiSpace::kUseRememberedSet && non_moving_space_ != main_space_) {
accounting::RememberedSet* non_moving_space_rem_set = new accounting::RememberedSet("Non-moving space remembered set", this, non_moving_space_);
AddRememberedSet(non_moving_space_rem_set);
}
num_bytes_allocated_.StoreRelaxed(0);
// Mark stack that we reuse to avoid re-allocating the mark stack.
// Allocation stack, new allocations go here so that we can do sticky mark bits. This enables us to use the live bitmap as the old mark bitmap.
// Second allocation stack so that we can process allocation with the heap unlocked.
mark_stack_.reset(accounting::ObjectStack::Create("mark stack", kDefaultMarkStackSize, kDefaultMarkStackSize));
const size_t alloc_stack_capacity = max_allocation_stack_size_ + kAllocationStackReserveSize;
allocation_stack_.reset(accounting::ObjectStack::Create( "allocation stack", max_allocation_stack_size_, alloc_stack_capacity));
live_stack_.reset(accounting::ObjectStack::Create( "live stack", max_allocation_stack_size_, alloc_stack_capacity));
第三部分
主要是gc相关;
- 回收器类型为CMS时,前台回收器类型为CMS,后台回收器类型为HSC。garbage_collectors_包含四个回收器对象,分别是MarkSweep、PartialMarkSweep、StickyMarkSweep和SemiSpace。其中,前三个回收器启用concurrent gc功能,而SemiSpace关闭分代gc的功能。
- 回收器类型为SS时,前台回收器类型为SS,后台回收器类型为HSC,garbage_collectors_包含一个SemiSpace回收器对象(关闭分代gc功能,generational为false)。
- 回收器类型为GSS时,前后台都使用GSS回收器,garbage_collectors_包含一个SemiSpace回收器对象,启用分代gc的功能(generational为true)。
gc_complete_lock_ = new Mutex("GC complete lock");
gc_complete_cond_.reset(new ConditionVariable("GC complete condition variable", *gc_complete_lock_));
thread_flip_lock_ = new Mutex("GC thread flip lock");
thread_flip_cond_.reset(new ConditionVariable("GC thread flip condition variable", *thread_flip_lock_));
task_processor_.reset(new TaskProcessor());
reference_processor_.reset(new ReferenceProcessor());
pending_task_lock_ = new Mutex("Pending task lock");
// Create our garbage collectors.
for (size_t i = 0; i < 2; ++i) {
const bool concurrent = i != 0;
if ((MayUseCollector(kCollectorTypeCMS) && concurrent) ||
(MayUseCollector(kCollectorTypeMS) && !concurrent)) {
garbage_collectors_.push_back(new collector::MarkSweep(this, concurrent));
garbage_collectors_.push_back(new collector::PartialMarkSweep(this, concurrent));
garbage_collectors_.push_back(new collector::StickyMarkSweep(this, concurrent));
}
}
if (kMovingCollector) {
if (MayUseCollector(kCollectorTypeSS) || MayUseCollector(kCollectorTypeGSS) ||
MayUseCollector(kCollectorTypeHomogeneousSpaceCompact) ||
use_homogeneous_space_compaction_for_oom_) {
const bool generational = foreground_collector_type_ == kCollectorTypeGSS;
semi_space_collector_ = new collector::SemiSpace(this, generational, generational ? "generational" : "");
garbage_collectors_.push_back(semi_space_collector_);
}
if (MayUseCollector(kCollectorTypeCC)) {
concurrent_copying_collector_ = new collector::ConcurrentCopying(this);
garbage_collectors_.push_back(concurrent_copying_collector_);
}
if (MayUseCollector(kCollectorTypeMC)) {
mark_compact_collector_ = new collector::MarkCompact(this);
garbage_collectors_.push_back(mark_compact_collector_);
}
}
}
bool Heap::MayUseCollector(CollectorType type) const {
return foreground_collector_type_ == type || background_collector_type_ == type;
}
其他方法
addSpace
- 如果是连续内存地址的Space对象,则将其加入continuous_spaces_数组中。该数组元素按照内存地址的起始位置由小到大排列。如果这个Space对象有live_bitmap_和mark_bitmap_位图对象,则对应将其加入Heap的live_bitmap_和mark_bitmap_的管理。
- 如果是内存地址不连续的Space对象,则将其加入discontinuous_spaces_数组。没有排序的要求。如果这个Space对象内有live_bitmap_和mark_bitmap_位图对象,则对应将其加入Heap的live_bitmap_和mark_bitmap_的管理。
- 如果是可分配内存的Space对象,则将其加入alloc_spaces_数组。
void Heap::AddSpace(space::Space* space) {
WriterMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_);
if (space->IsContinuousSpace()) {
space::ContinuousSpace* continuous_space = space->AsContinuousSpace();
// Continuous spaces don't necessarily have bitmaps.
// ContinuousSpace默认实现为ContinuousMemmapSpace,定义了live_bitmap、mark_bitmap这两成员变量;但只有DlMallocSpace和RosAllocSpace初始化了这俩。
accounting::ContinuousSpaceBitmap* live_bitmap = continuous_space->GetLiveBitmap();
accounting::ContinuousSpaceBitmap* mark_bitmap = continuous_space->GetMarkBitmap();
if (live_bitmap != nullptr) {
// 受管理
live_bitmap_->AddContinuousSpaceBitmap(live_bitmap);
mark_bitmap_->AddContinuousSpaceBitmap(mark_bitmap);
}
continuous_spaces_.push_back(continuous_space);
// Ensure that spaces remain sorted in increasing order of start address.
// 内存空间起始小的排在前面
std::sort(continuous_spaces_.begin(), continuous_spaces_.end(), [](const space::ContinuousSpace* a, const space::ContinuousSpace* b) {
return a->Begin() < b->Begin();
});
} else {
space::DiscontinuousSpace* discontinuous_space = space->AsDiscontinuousSpace();
live_bitmap_->AddLargeObjectBitmap(discontinuous_space->GetLiveBitmap());
mark_bitmap_->AddLargeObjectBitmap(discontinuous_space->GetMarkBitmap());
discontinuous_spaces_.push_back(discontinuous_space);
}
if (space->IsAllocSpace()) {
alloc_spaces_.push_back(space->AsAllocSpace());
}
}
RemoveSpace
RemoveSpace用于从上述管理模块中移除一个Space对象。
void Heap::RemoveSpace(space::Space* space) {
WriterMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_);
if (space->IsContinuousSpace()) {
space::ContinuousSpace* continuous_space = space->AsContinuousSpace();
// Continuous spaces don't necessarily have bitmaps.
accounting::ContinuousSpaceBitmap* live_bitmap = continuous_space->GetLiveBitmap();
accounting::ContinuousSpaceBitmap* mark_bitmap = continuous_space->GetMarkBitmap();
if (live_bitmap != nullptr) {
live_bitmap_->RemoveContinuousSpaceBitmap(live_bitmap);
mark_bitmap_->RemoveContinuousSpaceBitmap(mark_bitmap);
}
auto it = std::find(continuous_spaces_.begin(), continuous_spaces_.end(), continuous_space);
continuous_spaces_.erase(it);
} else {
space::DiscontinuousSpace* discontinuous_space = space->AsDiscontinuousSpace();
live_bitmap_->RemoveLargeObjectBitmap(discontinuous_space->GetLiveBitmap());
mark_bitmap_->RemoveLargeObjectBitmap(discontinuous_space->GetMarkBitmap());
auto it = std::find(discontinuous_spaces_.begin(), discontinuous_spaces_.end(), discontinuous_space);
discontinuous_spaces_.erase(it);
}
if (space->IsAllocSpace()) {
auto it = std::find(alloc_spaces_.begin(), alloc_spaces_.end(), space->AsAllocSpace());
alloc_spaces_.erase(it);
}
}