Heap
的創建位于/art/runtime/runtime.cc
的Runtime::Init
方法中
bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) {
...
//-Xgc
XGcOption xgc_option = runtime_options.GetOrDefault(Opt::GcOption);
heap_ = new gc::Heap(runtime_options.GetOrDefault(Opt::MemoryInitialSize),//-Xms:8m
//-XX:HeapGrowthLimit:256m
runtime_options.GetOrDefault(Opt::HeapGrowthLimit),
//-XX:HeapMinFree:512k
runtime_options.GetOrDefault(Opt::HeapMinFree),
//-XX:HeapMaxFree:8m
runtime_options.GetOrDefault(Opt::HeapMaxFree),
//-XX:HeapTargetUtilization:0.75
runtime_options.GetOrDefault(Opt::HeapTargetUtilization),
//-XX:ForegroundHeapGrowthMultiplier
runtime_options.GetOrDefault(Opt::ForegroundHeapGrowthMultiplier),
//-Xmx:512m
runtime_options.GetOrDefault(Opt::MemoryMaximumSize),
//-XX:NonMovingSpaceCapacity
runtime_options.GetOrDefault(Opt::NonMovingSpaceCapacity),
//-Ximage:/system/framework/boot.art
runtime_options.GetOrDefault(Opt::Image),
//imgaeinstructionset,是一個extra_info,用來hook: null
runtime_options.GetOrDefault(Opt::ImageInstructionSet),
//-Xgc:kuseReadBarrier ? gc::kCollectorTypeCC : gc::kCollectorTypeDefault
xgc_option.collector_type_,
//-XX:BackgroundGC
runtime_options.GetOrDefault(Opt::BackgroundGc),
//-XX:LargeObjectSpace
runtime_options.GetOrDefault(Opt::LargeObjectSpace),
//-XX:LargeObjectThreshold
runtime_options.GetOrDefault(Opt::LargeObjectThreshold),
//-XX:ParallelGCThreads:0u
runtime_options.GetOrDefault(Opt::ParallelGCThreads),
//-XX:ConcGCThreads
runtime_options.GetOrDefault(Opt::ConcGCThreads),
//-XX:LowMemoryMode:false
runtime_options.Exists(Opt::LowMemoryMode),
//-XX:LongPauseLogThreshold
runtime_options.GetOrDefault(Opt::LongPauseLogThreshold),
//-XX:LongGCLogThreshold
runtime_options.GetOrDefault(Opt::LongGCLogThreshold),
//-XX:IgnoreMaxFootprint
runtime_options.Exists(Opt::IgnoreMaxFootprint),
//-XX:UseTLAB
runtime_options.GetOrDefault(Opt::UseTLAB),
//default false
xgc_option.verify_pre_gc_heap_,
//default kIsDebugBuild
xgc_option.verify_pre_sweeping_heap_,
//default false
xgc_option.verify_post_gc_heap_,
//default kIsDebugBuild
xgc_option.verify_pre_gc_rosalloc_,
// default false
xgc_option.verify_pre_sweeping_rosalloc_,
//default false
xgc_option.verify_post_gc_rosalloc_,
//default false
xgc_option.gcstress_,
//-XX:EnableHSpaceCompactForOOM
runtime_options.GetOrDefault(Opt::EnableHSpaceCompactForOOM),
//-XX:HspaceCompactForOOMMinIntervalMs
runtime_options.GetOrDefault(Opt::HSpaceCompactForOOMMinIntervalsMs));
...
}
一. 相關知識預熱
1.1 Garbage Collection Type
垃圾回收的算法有多種,如MarkSweep-標記清楚算法,MarkCompact-標記整理算法,Copying-復制算法等等,之前的Dalvik一直使用的是MarkSweep算法,ART則在MarkSweep的基礎上添加了對其他垃圾回收算法的支持,具體的算法可以通過-Xgc
指定,如果沒有特別指定,則使用默認指定的:
// /art/smdline/cmdline_types.h
gc::CollectorType collector_type_ = kUseReadBarrier ?
// If RB is enabled (currently a build-time decision),
// use CC as the default GC.
gc::kCollectorTypeCC :
gc::kCollectorTypeDefault;
kUseReadBarrier
定義在/art/runtime/globals.h
#ifdef USE_BAKER_READ_BARRIER
static constexpr bool kUseBakerReadBarrier = true;
#else
static constexpr bool kUseBakerReadBarrier = false;
#endif
#ifdef USE_BROOKS_READ_BARRIER
static constexpr bool kUseBrooksReadBarrier = true;
#else
static constexpr bool kUseBrooksReadBarrier = false;
#endif
#ifdef USE_TABLE_LOOKUP_READ_BARRIER
static constexpr bool kUseTableLookupReadBarrier = true;
#else
static constexpr bool kUseTableLookupReadBarrier = false;
#endif
static constexpr bool kUseBakerOrBrooksReadBarrier = kUseBakerReadBarrier || kUseBrooksReadBarrier;
static constexpr bool kUseReadBarrier =
kUseBakerReadBarrier || kUseBrooksReadBarrier || kUseTableLookupReadBarrier;
kUseReadBarrier
根據三個編譯宏決定true或false,只要這個三個編譯宏中有一個存在,則kUseReadBarrier=true
gc::kCollectorTypeCC
和gc::kCollectorTypeDefault
定義在/art/runtime/gc/collector_type.h
enum CollectorType {
// No collector selected.
kCollectorTypeNone,
//普通Mark-Sweep
kCollectorTypeMS,
// 并發Mark-Sweep.
kCollectorTypeCMS,
// Semi-space和Mark-Sweep的混合
kCollectorTypeSS,
// Generational Semi-space
kCollectorTypeGSS,
// Mark compact
kCollectorTypeMC,
// Heap trimming collector, doesn't do any actual collecting.
kCollectorTypeHeapTrim,
// A (mostly) concurrent copying collector.
kCollectorTypeCC,
// Instrumentation critical section fake collector.
kCollectorTypeInstrumentation,
// Fake collector for adding or removing application image spaces.
kCollectorTypeAddRemoveAppImageSpace,
// A homogeneous space compaction collector used in background transition
// when both foreground and background collector are CMS.
kCollectorTypeHomogeneousSpaceCompact,
// Class linker fake collector.
kCollectorTypeClassLinker,
};
static constexpr CollectorType kCollectorTypeDefault =
#if ART_DEFAULT_GC_TYPE_IS_CMS
kCollectorTypeCMS
#elif ART_DEFAULT_GC_TYPE_IS_SS
kCollectorTypeSS
#elif ART_DEFAULT_GC_TYPE_IS_GSS
kCollectorTypeGSS
#else
kCollectorTypeCMS
#error "ART default GC type must be set"
#endif
從代碼中的定義可以看到,如果kUseReadBarrier=true
,則垃圾回收算法使用Concurrent-Copying
,否則默認算法,默認算法根據編譯宏選擇,沒有特別指定的情況下使用Concurrent Mark-Sweep
二. Heap::Heap()
2.1 構造函數聲明
Heap(size_t initial_size,//堆的初始大小
size_t growth_limit,//堆的增長上限
size_t min_free,//堆的最小空閑值
size_t max_free,//堆的最大空閑值
double target_utilization,//堆的目標利用率
double foreground_heap_growth_multiplier,//前臺堆增長因子(乘數)
size_t capacity,//堆的容量
size_t non_moving_space_capacity,//存儲不可移動對象的space的容量
const std::string& original_image_file_name,//image文件路徑
InstructionSet image_instruction_set,//指令集
CollectorType foreground_collector_type,//前臺回收器類型
CollectorType background_collector_type,//后臺回收器類型
space::LargeObjectSpaceType large_object_space_type,//存儲大對象的space類型
size_t large_object_threshold,//大對象數量的閾值
size_t parallel_gc_threads,//GC暫停階段用于同時執行GC任務的線程數
size_t conc_gc_threads,//并行GC的線程數
bool low_memory_mode,//是否是low memory mode
size_t long_pause_threshold,//GC造成應用程序暫停的時間閥值,超過則輸出log
size_t long_gc_threshold,//GC時間閥值,超過則輸出log
bool ignore_max_footprint,//不對堆的增長進行限制,堆可以增長到它的最大容量
bool use_tlab,//是否開啟TLAB選項
bool verify_pre_gc_heap,//是否在開始GC前驗證堆
bool verify_pre_sweeping_heap,//是否在GC執行清掃前驗證堆
bool verify_post_gc_heap,//是否在GC完成清掃后驗證堆
bool verify_pre_gc_rosalloc,//是否在開始GC前驗證RosAllocSpace
bool verify_pre_sweeping_rosalloc,//是否在GC執行清掃前驗證RosAllocSpace
bool verify_post_gc_rosalloc,//是否在GC完成清掃后驗證RosAllocSpace
bool gc_stress_mode,
bool use_homogeneous_space_compaction,//是否使用homogeneous space compaction來避免OOM
uint64_t min_interval_homogeneous_space_compaction_by_oom);//兩次OOM引起homogeneous space compaction時間間隔
2.2 構造函數實現
2.2.1 字段初始化
Heap::Heap(...) :
//space::MallocSpace*,存放不可移動對象
non_moving_space_(nullptr),
//kAllocatorTypeROSAlloc space
rosalloc_space_(nullptr),
//kAllocatorTypeDlMalloc space
dlmalloc_space_(nullptr),
//GC操作的主要space,這個space不是dlmalloc_space_就是rosalloc_space_
main_space_(nullptr),
//回收器類型
collector_type_(kCollectorTypeNone),
//前臺回收器類型
foreground_collector_type_(foreground_collector_type),
//后臺回收器類型
background_collector_type_(background_collector_type),
//希望的回收器類型,如果它!=collector_type_, heap trimming daemon會transitions堆
desired_collector_type_(foreground_collector_type_),
//Mutex*
pending_task_lock_(nullptr),
//GC暫停階段用于同時執行GC任務的線程數
parallel_gc_threads_(parallel_gc_threads),
//concurrent gc線程數
conc_gc_threads_(conc_gc_threads),
//是否是低內存模式
low_memory_mode_(low_memory_mode),
//GC造成應用程序暫停的時間閥值,超過則輸出log
long_pause_log_threshold_(long_pause_log_threshold),
//GC時間閥值,超過則輸出log
long_gc_log_threshold_(long_gc_log_threshold),
//是否對堆的增長不限制
ignore_max_footprint_(ignore_max_footprint),
//zygote space創建時的鎖, Mutex
zygote_creation_lock_("zygote creation lock", kZygoteCreationLock),
//space::ZygoteSpace 在zygote space創建之前不會包含大對象
zygote_space_(nullptr),
//大對象數量的閾值
large_object_threshold_(large_object_threshold),
//跟蹤在JNI critical section中有多少個線程
disable_thread_flip_count_(0),
thread_flip_running_(false),
//正在運行的回收器類型
collector_type_running_(kCollectorTypeNone),
//最后一次運行的GC類型
last_gc_type_(collector::kGcTypeNone),
//下一次將要運行的GC類型
next_gc_type_(collector::kGcTypePartial),
//堆的容量
capacity_(capacity),
//堆的增長上限
growth_limit_(growth_limit),
//分配對象的上限數,一旦超過著擱置會引起一次GC
max_allowed_footprint_(initial_size),
//由registerNativeAllocation請求的一次concurrent GC需要的臨界線, size_t
native_footprint_gc_watermark_(initial_size),
//bool, 是否需要在下一次的native allocation中運行finalizers
native_need_to_run_finalization_(false),
//當num_bytes_allocated_超過該值后,concurrent GC會啟動
concurrent_start_bytes_(std::numeric_limits<size_t>::max()),
//總共釋放的bytes自從heap創建以來
total_bytes_freed_ever_(0),
//總共釋放的對象自從heap創建以來
total_objects_freed_ever_(0),
//當前分配的bytes數量.每次釋放和分配以后都會更新
num_bytes_allocated_(0),
//native分配的bytes數量
native_bytes_allocated_(0),
//Mutex
native_histogram_lock_("Native allocation lock"),
//Histogram<uint64_t>,native分配的統計圖
native_allocation_histogram_("Native allocation sizes",
1U,
kNativeAllocationHistogramBuckets),
//native釋放的統計圖
native_free_histogram_("Native free sizes", 1U, kNativeAllocationHistogramBuckets),
num_bytes_freed_revoke_(0),
verify_missing_card_marks_(false),
verify_system_weaks_(false),
//是否在開始GC前驗證堆
verify_pre_gc_heap_(verify_pre_gc_heap),
//是否在GC執行清掃前驗證堆
verify_pre_sweeping_heap_(verify_pre_sweeping_heap),
//是否在GC完成清掃后驗證堆
verify_post_gc_heap_(verify_post_gc_heap),
//是否驗證ModUnionTable
verify_mod_union_table_(false),
//是否在開始GC前驗證RosAllocSpace
verify_pre_gc_rosalloc_(verify_pre_gc_rosalloc),
//是否在GC執行清掃前驗證RosAllocSpace
verify_pre_sweeping_rosalloc_(verify_pre_sweeping_rosalloc),
//是否在GC完成清掃后驗證RosAllocSpace
verify_post_gc_rosalloc_(verify_post_gc_rosalloc),
/* For GC a lot mode, we limit the allocations stacks to be kGcAlotInterval allocations. This
* causes a lot of GC since we do a GC for alloc whenever the stack is full. When heap
* verification is enabled, we limit the size of allocation stacks to speed up their
* searching.
*/
//分配棧最大數量
max_allocation_stack_size_(kGCALotMode ? kGcAlotAllocationStackSize
: (kVerifyObjectSupport > kVerifyObjectModeFast) ? kVerifyObjectAllocationStackSize :
kDefaultAllocationStackSize),
//當前分配器
current_allocator_(kAllocatorTypeDlMalloc),
//當前不可移動對象分配器
current_non_moving_allocator_(kAllocatorTypeNonMoving),
//階躍型指針space
bump_pointer_space_(nullptr),
//臨時space,Semispace回收器會將對象拷貝至這里
temp_space_(nullptr),
//RegionSpace 有一系列大小相等的區域組成
region_space_(nullptr),
//最小空余內存
min_free_(min_free),
//最大空余內存
max_free_(max_free),
//堆目標利用率
target_utilization_(target_utilization),
//前臺堆增長因子
foreground_heap_growth_multiplier_(foreground_heap_growth_multiplier),
//mutators暫停等待GC的總共時間
total_wait_time_(0),
//VerifyObjectMode, 目前heap verification的狀態
verify_object_mode_(kVerifyObjectModeDisabled),
//Compacting GC disable count
disable_moving_gc_count_(0),
is_running_on_memory_tool_(Runtime::Current()->IsRunningOnMemoryTool()),
use_tlab_(use_tlab),
//homogeneous space compaction時的新main space
main_space_backup_(nullptr),
//兩次OOM引起homogeneous space compaction時間間隔
min_interval_homogeneous_space_compaction_by_oom_(
min_interval_homogeneous_space_compaction_by_oom),
//上一次由OOM引起的HomogeneousSpaceCompact的時間
last_time_homogeneous_space_compaction_by_oom_(NanoTime()),
//CollectorTransitionTask*
pending_collector_transition_(nullptr),
//HeapTrimTask*
pending_heap_trim_(nullptr),
//是否使用homogeneous space compaction來避免OOM
use_homogeneous_space_compaction_for_oom_(use_homogeneous_space_compaction_for_oom),
//如果當前的回收工作導致一些線程暫停,則該值為true
running_collection_is_blocking_(false),
//blocking gc 數量
blocking_gc_count_(0U),
//blocking gc總共持續時間
blocking_gc_time_(0U),
//GC count rate統計圖最后已更新時間
last_update_time_gc_count_rate_histograms_( // Round down by the window duration.
(NanoTime() / kGcCountRateHistogramWindowDuration) * kGcCountRateHistogramWindowDuration),
//在上一個window運行的GC數量
gc_count_last_window_(0U),
//在上一個window運行的blocking GC數量
blocking_gc_count_last_window_(0U),
//每一個window的GC調用統計圖
gc_count_rate_histogram_("gc count rate histogram", 1U, kGcCountRateMaxBucketCount),
//每一個window的blocking GC調用統計圖
blocking_gc_count_rate_histogram_("blocking gc count rate histogram", 1U,
kGcCountRateMaxBucketCount),
//是否支持allocation tracking
alloc_tracking_enabled_(false),
//Mutex*
backtrace_lock_(nullptr),
seen_backtrace_count_(0u),
unique_backtrace_count_(0u),
gc_disabled_for_shutdown_(false) {
2.2.2 具體創建邏輯
Heap的構造函數的代碼較多,不過整體邏輯比較清晰,整體邏輯可以分為以下幾塊:
- 判斷當前是否在zygote進程,如果不在zygote,將
background_collector_type_
設為和foreground_collector_type_
一樣,并檢查傳入的desired_collector_type_
和collector_type_
是否一樣,如果不一樣,則將collector_type_
設為desired_collector_type_
Runtime* const runtime = Runtime::Current();
//判斷當前是否是zygote模式,如果不是判斷后臺回收器類型是否和前臺回收器相等,不想等,則設為相等
const bool is_zygote = runtime->IsZygote();
if (!is_zygote) {
if (background_collector_type_ != foreground_collector_type_) {
...
background_collector_type_ = foreground_collector_type_;
}
}
//檢查collector_type_是否和desired_collector_type_相等,不等的話將collector_type_置為desired_collector_type_
ChangeCollector(desired_collector_type_);
- 創建兩個HeapBitmap(
live_bitmap_
:用來記錄上次GC之后還存活的對象;mark_bitmap_
:用來記錄當前GC中還存活的對象)
live_bitmap_.reset(new accounting::HeapBitmap(this));
mark_bitmap_.reset(new accounting::HeapBitmap(this));
- 如果
foreground_collector_type_
是Concurrent-Copying,設置requested_alloc_space_begin
即alloc space的起始地址為(如果前臺回收器是CC則是300MB-non_moving_space_capacity,否則是nullptr)
if (foreground_collector_type_ == kCollectorTypeCC) {
...
requested_alloc_space_begin = reinterpret_cast<uint8_t*>(300 * MB) - non_moving_space_capacity;
}
- 根據傳入的image文件路徑(
/system/framework/boot.art
)創建ImageSpace,在ImageSpace后面緊跟的是/system/framework/boot.oat
,如果創建成功,將requested_alloc_space_begin
指向boot.oat地址的末尾;如果創建ImageSpace失敗,刪除已加載的Space,將requested_alloc_space_begin
指回原來的(300MB-non_moving_space_capacity)
//創建ImageSpace, image_file_name是/system/framework/boot.art
if (!image_file_name.empty()) {
std::vector<std::string> image_file_names;
image_file_names.push_back(image_file_name);
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];///system/framework/boot.art
std::string error_msg;
//創建boot_image_space
space::ImageSpace* boot_image_space = space::ImageSpace::CreateBootImage(
image_name.c_str(),
image_instruction_set,
index > 0,
&error_msg);
//創建boot_image_space成功
if (boot_image_space != nullptr) {
/* 根據boot_image_space是否時連續空間,將boot_image_space添加到對應的Space列表,并在live_bitmap_和mark_bitmap_中添加對應的位圖 */
AddSpace(boot_image_space);
added_image_spaces.push_back(boot_image_space);
//Oat文件即boot.oat緊跟在boot_image_space末尾
uint8_t* oat_file_end_addr = boot_image_space->GetImageHeader().GetOatFileEnd();
...
//將boot.oat的地址按頁大小(pageSize)對齊
requested_alloc_space_begin = AlignUp(oat_file_end_addr, kPageSize);
boot_image_spaces_.push_back(boot_image_space);
if (index == 0) {
//如果是第一塊Space,檢查是否還有其他的oat文件需要加載
const OatFile* boot_oat_file = boot_image_space->GetOatFile();
if (boot_oat_file == nullptr) {
continue;
}
//如果還有其他的oat文件,根據OatHeader獲取boot_classpath,再根據boot_classpath生成
//oat文件完整路徑,將完整路徑添加進image文件列表,從而可以在下次循環中加載
const OatHeader& boot_oat_header = boot_oat_file->GetOatHeader();
const char* boot_classpath =
boot_oat_header.GetStoreValueByKey(OatHeader::kBootClassPathKey);
if (boot_classpath == nullptr) {
continue;
}
space::ImageSpace::CreateMultiImageLocations(image_file_name,
boot_classpath,
&image_file_names);
}
} else {
//創建ImageSpace失敗, 刪除已加載的Space
for (space::Space* loaded_space : added_image_spaces) {
RemoveSpace(loaded_space);
delete loaded_space;
}
boot_image_spaces_.clear();
requested_alloc_space_begin = original_requested_alloc_space_begin;
break;
}
}
}
- 判斷是否支持Homogeneous-Space-Compact.當
background_collector_type_
是Homogeneous-Space-Compact或者foreground_collector_type_
不是GSS(Generational Semi-Space)
和CC(Concurrent-Copying)
時,支持Homogeneous-Space-Compact
if (foreground_collector_type_ == kCollectorTypeGSS ||
foreground_collector_type_ == kCollectorTypeCC) {
use_homogeneous_space_compaction_for_oom_ = false;
}
//如果后臺回收器是homogeneous space compact或者前臺回收器不是GSS和CC時,支持homogeneous space compact
bool support_homogeneous_space_compaction =
background_collector_type_ == gc::kCollectorTypeHomogeneousSpaceCompact ||
use_homogeneous_space_compaction_for_oom_;
- 判斷是否給Non-Moving Space獨立的地址.只要以下滿足四個條件中的一項就會給Non-Moving Space獨立地址(處于Zygote;支持Homogeneous-Space-Compact(
foreground_collector_type_
不是GSS
或者不是CC
);foreground_collector_type_
可以移動對象;background_collector_type_
可以移動對象), 之后再排除foreground_collector_type_
是GSS的情況,即前臺回收器是GSS時,不給Non-Moving Space獨立地址
//如果當前處于Zygote模式或者支持homogeneous space compact或者前臺回收器是可以移動對象的或者后臺回收器也可以移動對象時
//給non_moving_space一個獨立的地址
bool separate_non_moving_space = is_zygote ||
support_homogeneous_space_compaction || IsMovingGc(foreground_collector_type_) ||
IsMovingGc(background_collector_type_);
//再次檢查前臺進程是否是GSS,如果是,則不給non_moving_space_一個獨立的地址
if (foreground_collector_type_ == kCollectorTypeGSS) {
separate_non_moving_space = false;
}
只要傳入的type是SS,GSS,CC,MC,Homogeneous-Space-Compact其中一個時,
IsMovingGc
返回的都是true
- 創建兩個內存映射
MemMap
std::unique_ptr<MemMap> main_mem_map_1;
std::unique_ptr<MemMap> main_mem_map_2;
- 如果之前創建ImageSpace失敗同時
foreground_collector_type_
是MarkSweep
而且此時的Runtime由dex2oat創建即處于dex2oat進程中時,將requested_alloc_space_begin
指向kAllocSpaceBeginForDeterministicAoT
// 如果前臺回收器是MS(MarkSweep)且requested_alloc_space_begin
// 是null(即之前ImageSpace創建失敗)同時當前是dex2oat程序
// 將requested_alloc_space_begin設為kAllocSpaceBeginForDeterministicAoT
if (foreground_collector_type_ == kCollectorTypeMS &&
requested_alloc_space_begin == nullptr &&
Runtime::Current()->IsAotCompiler()) {
requested_alloc_space_begin = reinterpret_cast<uint8_t*>(kAllocSpaceBeginForDeterministicAoT);
}
- 初始化
request_begin
.如果Non-Moving Space有獨立地址,根據當前是否是zygote確定Non-Moving Space的名字,之后創建一塊匿名內存映射,由non_moving_space_mem_map
指向,non_moving_space_mem_map
緊跟在requested_alloc_space_begin
后面,如果ImageSpace創建成功,就是緊跟在ImageSpace+boot.oat后面,否則緊跟在kAllocSpaceBeginForDeterministicAoT
后面,最后設置request_begin
為300MB,即其他Space的起始地址為300MB
uint8_t* request_begin = requested_alloc_space_begin;
if (request_begin != nullptr && separate_non_moving_space) {
request_begin += non_moving_space_capacity;
}
std::string error_str;
std::unique_ptr<MemMap> non_moving_space_mem_map;
//如果確定給non moving space一塊獨立的地址
if (separate_non_moving_space) {
ScopedTrace trace2("Create separate non moving space");
// 如果當前正在Zygote當中,將non moving space設為zygote space
const char* space_name = is_zygote ? kZygoteSpaceName: kNonMovingSpaceName;
//創建匿名內存映射
//non moving sapce緊跟在requested_alloc_space_begin后面(即如果ImageSpace創建成功,緊跟在ImageSpace + boo.oat后面)
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));
...
// 如果要給non moving space一個獨立的地址, 將其他Space的起始地址設為300MB,由request_begin指向
request_begin = reinterpret_cast<uint8_t*>(300 * MB);
}
- 如果
foreground_collector_type_
不是CC
,初始化之前創造的main_mem_map_1
,這塊內存的作用是作為MarkSweep
的Main Space或者Compact GC
的From-Bump-Space.當Non-Moving Space有獨立地址且當前不處于Zygote時,緊跟在300MB后面創建匿名內存映射;否則緊跟在ImageSpace+boot.oat后面創建匿名內存映射
//如果前臺回收器不是CC,創建第一塊匿名共享內存,由main_mem_map_1指向,這塊內存的作用是作為Compact GC的From Bump Space或者
//MarkSweep的Main Space
if (foreground_collector_type_ != kCollectorTypeCC) {
ScopedTrace trace2("Create main mem map");
if (separate_non_moving_space || !is_zygote) {
//如果non moving space有獨立地址或者當前不是zygote,則main_mem_map_1緊跟在 request_begin后面,即300MB后面
//名字是main space
main_mem_map_1.reset(MapAnonymousPreferredAddress(kMemMapSpaceName[0],
request_begin,
capacity_,
&error_str));
} else {
//如果non-moving space有獨立地址且當前處于zygote或者non-moving space沒有獨立地址,
//則main space必須緊跟在ImageSpace后面,這樣zygote space就會臨近ImageSpace
main_mem_map_1.reset(MemMap::MapAnonymous(kMemMapSpaceName[0], request_begin, capacity_,
PROT_READ | PROT_WRITE, true, false,
&error_str));
}
...
}
- 如果支持Homogeneous-Space-Compact或者
background_collector_type_
和foreground_collector_type_
其中一個是SS
時,創建第二塊匿名內存映射main_mem_map_2
//如果支持homogeneous space compact或者后臺回收器和前臺回收器中有一個為為SS(Semi Space)時,創建第二塊匿名共享內存
//由main_mem_map_2指向
if (support_homogeneous_space_compaction ||
background_collector_type_ == kCollectorTypeSS ||
foreground_collector_type_ == kCollectorTypeSS) {
ScopedTrace trace2("Create main mem map 2");
main_mem_map_2.reset(MapAnonymousPreferredAddress(kMemMapSpaceName[1], main_mem_map_1->End(),
capacity_, &error_str));
...
}
- 如果Non-Moving Space有獨立地址,則之前已經創建了匿名內存映射
non_moving_space_mem_map
,現在將這塊內存封裝成DlMallocSpace
,由non-moving_space
指向,并將這塊Space添加至Space列表中
//如果non moving space有獨立的地址時,將non_moving_space_mem_map封裝成Non-Moving Space(space::MallocSpace)
if (separate_non_moving_space) {
ScopedTrace trace2("Add non moving space");
//Non-Moving Space必須是dlmalloc,因為目前并不支持多個rosalloc spaces
const size_t size = non_moving_space_mem_map->Size();
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大小限制
non_moving_space_->SetFootprintLimit(non_moving_space_->Capacity());
...
//將non_moving_space_添加至space列表中
AddSpace(non_moving_space_);
}
- 根據條件處理之前創建的另外兩塊匿名內存映射
main_mem_map_1
和main_mem_map_2
.因為在之前的邏輯中,當foreground_collector_type_
是CC時,并沒有創建main_mem_map_1
匿名內存映射,所以如果foreground_collector_type_
恰好是CC時,緊跟request_begin
(如果Non-Moving Space有獨立地址,則是300MB,否則是ImageSpace+boot.oat)創建一個RegionSpace
,由region_space_
指向; 如果foreground_collector_type_
不是CC時,也要分兩種情況:(1)foreground_collector_type_
是SS,MC,Homogeneous-Space-Compact
中的一個;(2)foreground_collector_type_
是MarkSweep, Compact MarkSweep
或者GSS
. 對于第一種情況來說,將main_mem_map_1
封裝成BumpPointerSpace1
并添加至space列表,由bump_pointer_space_
指向,將main_mem_map_2
封裝成另一塊BumpPointerSpace2
同樣添加至space列表,由temp_space_
指向;對于第二種情況,首先將main_mem_map_1
封裝成MainSpace
同時添加至space列表,之后如果Non-Moving Space沒有獨立地址,則將non_moving_space_
指向MainSpace,即MainSpace和Non-Moving Space共用同一塊內存,接著判斷如果foreground_collector_type_是GSS時,調用BumpPointerSpace::Craete
直接創建BumpPointerSpace1
(bump_pointer_space_
)和BumpPointerSpace2
(temp_space_
)并依次添加至space列表;如果foreground_collector_type_
不是GSS
時,即MarkSweep
或Compact MarkSweep
,且main_mem_map_2
不為空時(如果支持HomogeneousSpaceCompact),將main_mem_map_2
封裝成Backup Space
,并添加至space列表
if (foreground_collector_type_ == kCollectorTypeCC) {
// 如果前臺回收器是CC(Concurrent Copying),創建RegionSpace,并將RegionSpace添加至space列表
region_space_ = space::RegionSpace::Create("Region space", capacity_ * 2, request_begin);
AddSpace(region_space_);
} else if (IsMovingGc(foreground_collector_type_) &&
foreground_collector_type_ != kCollectorTypeGSS) {
//如果前臺回收器是除了GSS(Generational Semi-Space)以外的Compact GC,將main_mem_map_1封裝成BumpPointerSpace
//并將bump_pointer_space_添加至space列表
// TODO: Place bump-pointer spaces somewhere to minimize size of card table.
bump_pointer_space_ = space::BumpPointerSpace::CreateFromMemMap("Bump pointer space 1",
main_mem_map_1.release());
...
AddSpace(bump_pointer_space_);
//將main_mem_map_2封裝成第二塊BumpPointerSpace,由temp_space_指向,同時將temp_space_添加至space列表
temp_space_ = space::BumpPointerSpace::CreateFromMemMap("Bump pointer space 2",
main_mem_map_2.release());
...
AddSpace(temp_space_);
...
} else {
//如果前臺回收器不是Compact GC即MarkSweep或者是GSS,則在main_mem_map_1創建Main Space,并將Main Space添加至space列表
CreateMainMallocSpace(main_mem_map_1.release(), initial_size, growth_limit_, capacity_);
...
AddSpace(main_space_);
if (!separate_non_moving_space) {
//如果Non-Moving Space沒有獨立地址,則將non_moving_space_指向main_space_,即Non-Moving Space和Main Space是同一塊Space
non_moving_space_ = main_space_;
...
}
if (foreground_collector_type_ == kCollectorTypeGSS) {
....
//如果前臺回收器是GSS, 并創建BumpPointerSpace,由bump_pointer_space_指向
//同時將bump_pointer_space_添加至space列表
main_mem_map_2.release();
bump_pointer_space_ = space::BumpPointerSpace::Create("Bump pointer space 1",
kGSSBumpPointerSpaceCapacity, nullptr);
...
AddSpace(bump_pointer_space_);
//創建第二塊BumpPointerSpace,由temp_space_指向,并將temp_space_添加至space列表
temp_space_ = space::BumpPointerSpace::Create("Bump pointer space 2",
kGSSBumpPointerSpaceCapacity, nullptr);
...
AddSpace(temp_space_);
} else if (main_mem_map_2.get() != nullptr) {
//此時前臺回收器根據排除法只剩MarkSweep了,將main_mem_map_2封裝成Backup Space,由main_space_backup_指向
//同時將main_space_backup_添加至space列表,如果kUseRosAlloc為true,main_space_backup_為RosAllocSpace,否則為DlMallocSpace
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());
}
}
- 創建大對象存儲空間.
// 創建LargeObjectSpace(大對象存儲空間)
if (large_object_space_type == space::LargeObjectSpaceType::kFreeList) {
//如果LargeObjectSpace類型是FreeList,創建FreeList類型的LargeObjectSpace
large_object_space_ = space::FreeListSpace::Create("free list large object space", nullptr,
capacity_);
...
} else if (large_object_space_type == space::LargeObjectSpaceType::kMap) {
//創建相互獨立的內存快組成的LargeObjectSpace
large_object_space_ = space::LargeObjectMapSpace::Create("mem map large object space");
...
} else {
large_object_threshold_ = std::numeric_limits<size_t>::max();
large_object_space_ = nullptr;
}
//如果LargeObjectSpace不為空,則添加至Space列表
if (large_object_space_ != nullptr) {
AddSpace(large_object_space_);
}
- 如果
foreground_collector_type_
是MarkSweep或Compact MarkSweep且創建了Backup Space
時,由于Backup Space占用的額外的空間會降低GC速度,所以移除Backup Space;之后創建CardTable
(Card Table是為了記錄在垃圾收集過程中對象的引用情況的),ModUnionTable
(來記錄ImageSpace對ZygoteSpace引用情況的ModUnionTable),RememberSet
(用來記錄Non-moving Space對其他Space引用情況的RememberedSet,GSS
時不會創建,CC, SS, MC, HomogeneousSpaceCompact
時根據collector::SemiSpace::kUseRememberedSet == true
判斷,MS,CMS
時根據Non-Moving Space有沒有獨立地址加collector::SemiSpace::kUseRememberedSet == true
判斷)
//獲取連續空間的起始地址和結束地址
uint8_t* heap_begin = continuous_spaces_.front()->Begin();
uint8_t* heap_end = continuous_spaces_.back()->Limit();
size_t heap_capacity = heap_end - heap_begin;
//移除main_space_backup_,此時foreground_collector_type_是MarkSweep
//因為Backup Space的額外的未使用的空間降低了GC速度
if (main_space_backup_.get() != nullptr) {
RemoveSpace(main_space_backup_.get());
}
...
// 創建card table,因為不知道在low_4gb模式下,app image會在何處定位,
// 所以card table將會從64KB開始覆蓋整個4GB的低地址,64KB以前的地址預留給kernel
static constexpr size_t kMinHeapAddress = 4 * KB;
card_table_.reset(accounting::CardTable::Create(reinterpret_cast<uint8_t*>(kMinHeapAddress), 4 * GB - kMinHeapAddress));
....
//如果前臺回收器是CC(Concurrent Copying)同時kUseTableLookupReadBarrier=true,創建ReadBarrierTable
if (foreground_collector_type_ == kCollectorTypeCC && kUseTableLookupReadBarrier) {
rb_table_.reset(new accounting::ReadBarrierTable());
...
}
if (HasBootImageSpace()) {
// 如果有ImageSpace,則創建用來記錄ImageSpace對ZygoteSpace引用情況的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);
}
}
//如果Non-moving Space有獨立地址而且kUseRememberedSet=true,
//創建用來記錄Non-moving Space對其他Space引用情況的RememberedSet
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);
}
- 創建
Mark-Stack
,Allocation-Stack
,Live-Stack
;創建之后GC需要用到的的鎖;創建TaskProcessor
,ReferenceProcessor
;如果前后臺回收器有一個是CMS,則創建一組包含三個支持并發的Collector:MarkSweep, PartialMarkSweep, StickyMarkSweep
回收器; 如果前后臺回收器有一個是MS,則創建一組包含三個不支持并發的Collector:MarkSweep, PartialMarkSweep, StickyMarkSweep
回收器;之后再根據條件創建Semi-Space Collector
(SS
或GSS
時創建),Concurrent-Copying Collector
(CC
時創建),Mark Compact Collector
(MS,CMS
shichu)
// TODO: Count objects in the image space here?
num_bytes_allocated_.StoreRelaxed(0);
// 創建Mark-Stack, Allocation-Stack, Live-Stack
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_complete_lock_,thread_flip_lock_
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_));
//創建TaskProcessor, ReferenceProcessor, pending_task_lock_
task_processor_.reset(new TaskProcessor());
reference_processor_.reset(new ReferenceProcessor());
pending_task_lock_ = new Mutex("Pending task lock");
if (ignore_max_footprint_) {
//如果不限制堆的增長,則將堆的最大限制數設為最大
SetIdealFootprint(std::numeric_limits<size_t>::max());
//將concurrent gc的啟動值也設為最大,即只有堆達到最大時,才開啟concurrent gc
concurrent_start_bytes_ = std::numeric_limits<size_t>::max();
}
...
// 如果前后臺回收器有一個是CMS,則創建一組包含三個支持并發的Collector:MarkSweep, PartialMarkSweep, StickyMarkSweep回收器
// 如果前后臺回收器有一個是MS,則創建一組包含三個不支持并發的Collector:MarkSweep, PartialMarkSweep, StickyMarkSweep回收器
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) {//kMovingCollector=true
if (MayUseCollector(kCollectorTypeSS) || MayUseCollector(kCollectorTypeGSS) ||
MayUseCollector(kCollectorTypeHomogeneousSpaceCompact) ||
use_homogeneous_space_compaction_for_oom_) {
//如果前后臺回收器中某一個是SS,GSS,HomogeneousSpaceCompact三者其中一個或者
//使用homogeneous space compaction來避免OOM時,再創鍵一個Semi-Space Collector
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)) {
//如果前后臺回收器中某一個是CC,再創建一個ConcurrentCopying Collector
concurrent_copying_collector_ = new collector::ConcurrentCopying(this);
garbage_collectors_.push_back(concurrent_copying_collector_);
}
if (MayUseCollector(kCollectorTypeMC)) {
//如果前后臺回收器中某一個是MarkCompact,再創建一個MarkCompact Collector
mark_compact_collector_ = new collector::MarkCompact(this);
garbage_collectors_.push_back(mark_compact_collector_);
}
}
- 如果有ImageSpace同時Non-Moving Space不為空同時滿足三個條件(處于zygote,Non-Moving Space有獨立地址,前臺回收器是GSS)中的一個時,檢查ImageSpace和Non-Moving Space之間沒有內存空隙
if (!GetBootImageSpaces().empty() && non_moving_space_ != nullptr &&
(is_zygote || separate_non_moving_space || foreground_collector_type_ == kCollectorTypeGSS)) {
//如果有ImageSpace同時Non-Moving Space不為空同時滿足三個條件
//(處于zygote,Non-Moving Space有獨立地址,前臺回收器是GSS)中的一個時,
//檢查ImageSpace和Non-Moving Space只見沒有內存空隙
space::ImageSpace* first_space = nullptr;
for (space::ImageSpace* space : boot_image_spaces_) {
if (first_space == nullptr || space->Begin() < first_space->Begin()) {
first_space = space;
}
}
bool no_gap = MemMap::CheckNoGaps(first_space->GetMemMap(), non_moving_space_->GetMemMap());
if (!no_gap) {
PrintFileToLog("/proc/self/maps", LogSeverity::ERROR);
MemMap::DumpMaps(LOG(ERROR), true);
...
}
}
instrumentation::Instrumentation* const instrumentation = runtime->GetInstrumentation();
if (gc_stress_mode_) {
backtrace_lock_ = new Mutex("GC complete lock");
}
if (is_running_on_memory_tool_ || gc_stress_mode_) {
instrumentation->InstrumentQuickAllocEntryPoints();
}
三. 總結
3.1 前臺回收器是ConcurrentCopying
從代碼邏輯看,如果foreground_collector_type_=kCollectorTypeCC
時Heap的創建流程要跟其他回收器類型的創建流程不太相同:
requested_alloc_space_begin = 300MB - non_moving_space_capacity
- 創建ImageSpace(只要image文件不為空,都會創建),如果創建成功,
requested_alloc_space_begin=ImageSpace+boo.oat
這一點所有回收器類型都一樣,不同的是,如果創建失敗,
requested_alloc_space_begin = 300MB - non_moving_space_capacity
, 其他回收器類型則是requested_alloc_space_begin = nullptr
- 如果
background_collector_type_ != kCollectorTypeHomogeneousSpaceCompact
,則不支持Homogeneous-Space-Compact
- 由于是
CC
回收器,所以必然會給Non-Moving Space獨立的地址 - 由于是
CC
回收器,所以即使ImageSpace創建失敗,requested_alloc_space_begin
也不會為nullptr
,又因為Non-Moving Space有獨立的地址,所以最后request_begin=requested_alloc_space_begin + non_moving_space_capacity
如果ImageSpace創建成功,
request_begin=ImageSpace+boot.oat+non_moving_space_capacity
;如果創建失敗,request_begin = 300MB-non_moving_space_capacity+non_moving_space_capacity
->request_begin=300MB
- 緊跟著
requested_alloc_space_begin
創建用于Non-Moving Space的匿名內存映射non_moving_space_mem_map
, 將request_begin
固定在300MB的地址(request_begin=reinterpret_cast<uint8_t*>(300*MB)
);之后將匿名內存映射封裝成Non-Moving Space,如果在Zygote中,就叫ZygoteSpace
,否則叫Non-Moving Space
- 由于是
CC
回收器,所以不會創建兩塊匿名內存main_mem_map_1,main_mem_map_2
,而是緊跟著在request_begin
后(即300MB,因為之前已經將request_begin
固定在這個地址)直接創建RegionSpace
- 創建
LargeObjectSpace
- 如果
kUseTableLookupReadBarrier=true
,創建ReadBarrierTable
- 創建
CardTable
,ModUnionTable
(如果ImageSpace創建成功),如果collector::SemiSpace::kUseRememberedSet == true
創建RememberedSet
;創建allocation_stack_,mark_stack_,live_stack_
;創建鎖;創建TaskProcessor,ReferenceProcessor
- 由于是
CC
回收器,創建collector::ConcurrentCopying
并添加至garbage_collectors_
- 如果ImageSpace創建成功,且Non-Moving Space不為空,檢查ImageSpace和Non-Moving Space之間有沒有內存間隙
因為是
CC
,所以Non-Moving Space必然有獨立地址,所以只需要判斷ImageSpace創建成功和Non-Moving Space不為空
3.2 前臺回收器是GSS
GSS(Generational Semi-Space)是另一個較為特殊的回收器類型
requested_alloc_space_begin=nullptr
- 創建ImageSpace,如果成功,
requested_alloc_space_begin=ImageSpace+boot.oat
,如果創建失敗,requested_alloc_space_begin=nullptr
- 如果
background_collector_type_ != kCollectorTypeHomogeneousSpaceCompact
,則肯定不支持Homogeneous-Space-Compact - 由于是
GSS
回收器,所以不會給Non-Moving Space獨立的地址(這一點很重要,即不會創建Non-Moving Space的匿名內存映射) - 如果ImageSpace創建失敗,則
request_begin=requested_alloc_space_begin=nullptr
;如果創建成功,則request_begin=reuqest_alloc_space_begin=ImageSpace+boo.oat
- 由于是
GSS
回收器,那么Non-Moving Space不會有獨立地址,如果此時處于Zygote中,則緊跟ImageSpace+boo.oat創建匿名內存映射main_mem_map_1
(因為Non-Moving Space沒有獨立地址,所以不會將request_begin固定在300MB,又因為如果ImageSpace創建成功此時request_begin=ImageSpace+boot.oat) - 如果
background_collector_type_ == kCollectorTypeHomogeneousSpaceCompact
,則會緊跟著main_mem_map_1
再創建第二塊匿名內存映射main_mem_map_2
,否則不會創建main_mem_map_2
- 將
main_mem_map_1
封裝成Main Space
,由于是GSS
回收器,所以將non_moving_space_
也指向Main Space
- 由于是
GSS
回收器,調用space::BumpPointerSpace::Create
直接創建BumpPointerSpace1
和BumpPointerSpace2
- 創建
LargeObjectSpace
- 創建
CardTable
,ModUnionTable
(如果ImageSpace創建成功),由于是GSS
回收器,所以non_moving_space_ == main_space_
,所以不會創建RememberedSet
;創建allocation_stack_,mark_stack_,live_stack_
;創建鎖;創建TaskProcessor,ReferenceProcessor
- 由于是
GSS
,所以創建collector::SemiSpace
,其中generational_ = true
- 如果ImageSpace創建成功,且
MainSpace
不為空,檢查ImageSpace和Non-Moving Space之間有沒有內存間隙
因為是
GSS
,所以non_moving_space_
指向MainSpace
,所以只需要判斷ImageSpace創建成功和Non-Moving Space不為空
3.3 Moving GC(Semi-Space, MarkCompact, HomogeneousSpaceCompact)
requested_alloc_space_begin=nullptr
- 創建ImageSpace,如果成功,
requested_alloc_space_begin=ImageSpace+boot.oat
,如果創建失敗,requested_alloc_space_begin=nullptr
- 由于不是
GSS
和CC
,所以只要傳入的use_homogeneous_space_compaction==true
或者background_collector_type_ == kCollectorTypeHomogeneousSpaceCompact
時會支持Homogeneous-Space-Compact - Non-Moving必然有獨立的地址
- 如果ImageSpace創建成功,
request_begin = requested_alloc_space_begin + non_moving_space_capacity
,否則request_begin=nullptr
- 創建Non-Moving Space使用的匿名內存映射
non_moving_space_mem_map
,將request_begin
固定在300MB的地址(request_begin=reinterpret_cast<uint8_t*>(300*MB)
) - 緊跟
request_begin
創建匿名內存映射main_mem_map_1
- 如果支持Homogeneous-Space-Compact或者前后臺回收器有一個是
Semi-Space
,則緊跟main_mem_map_1
創建第二塊匿名內存映射main_mem_map_2
- 將
non_moving_space_mem_map
封裝成Non-Moving Space
,由non_moving_space_
指向 - 將
main_mem_map_1
封裝成BumpPointerSpace1
,將main_mem_map_2
封裝成BumpPointerSpace2
- 創建
LargeObjectSpace
- 創建
CardTable
,ModUnionTable
(如果ImageSpace創建成功),如果collector::SemiSpace::kUseRememberedSet == true
創建RememberedSet
;創建allocation_stack_,mark_stack_,live_stack_
;創建鎖;創建TaskProcessor,ReferenceProcessor
- 如果前后臺回收器中有一個是
SS
或Homogeneous-Space-Compact
,創建collector::SemiSpace
;如果前后臺回收器有一個是MarkCompact
,則創建collector::MarkCompact
- 如果ImageSpace創建成功,且Non-Moving Space不為空,檢查ImageSpace和Non-Moving Space之間有沒有內存間隙
因為Non-Moving必然有獨立的地址,所以只需要判斷ImageSpace創建成功和Non-Moving Space不為空
3.4 前臺回收器MarkSweep或Concurrent MarkSweep
requested_alloc_space_begin=nullptr
- 創建ImageSpace,如果成功,
requested_alloc_space_begin=ImageSpace+boot.oat
,如果創建失敗,requested_alloc_space_begin=nullptr
- 由于不是
GSS
和CC
,所以只要傳入的use_homogeneous_space_compaction=true
或者background_collector_type_ == kCollectorTypeHomogeneousSpaceCompact
時會支持Homogeneous-Space-Compact - 只要當前處于Zygote當中,則Non-Moving Space必然有獨立地址,否則得看是否支持Homogeneous-Space-Compact,支持的話,就有獨立地址,不支持就沒有
- 如果ImageSpace創建失敗且
foreground_collector_type_=kCollectorTypeMS
同時當前處于dex2oat,requested_alloc_space_begin=kAllocSpaceBeginForDeterministicAoT
- 如果ImageSpace創建成功且如果Non-Moving Space有獨立地址的話,創建Non-Moving Space要用到的匿名內存映射
non_moving_space_mem_map
,將request_begin
固定在300MB的地址(request_begin=reinterpret_cast<uint8_t*>(300*MB)
) - 如果Non-Moving Space有獨立地址或者當前不在Zygote中,緊跟著
request_begin
(300MB)創建匿名內存映射main_mem_map_1
;如果Non-Moving Space沒有獨立地址同時處于Zygote中,則緊跟著ImageSpace_boot.oat創建匿名內存映射main_mem_map_1
- 如果支持Homogeneous-Space-Compact,緊跟著
main_mem_map_1
創建第二塊匿名內存映射main_mem_map_2
,否則不創建main_mem_map_2
- 如果Non-Moving Space有獨立地址,將
non_moving_space_mem_map
封裝成Non-Moving Space
- 將
main_mem_map_1
封裝成Main Space
,如果Non-Moving Space沒有獨立地址,則將non_moving_space_
也指向MainSpace
- 如果之前創建了
main_mem_map_2
,則將main_mem_map_2
封裝成Main Backup Space
- 創建
LargeObjectSpace
- 移除
Main Backup Space
- 創建
CardTable
,ModUnionTable
(如果ImageSpace創建成功),如果Non-Moving Space有獨立地址,創建RememberedSet
,否則不創建;創建allocation_stack_,mark_stack_,live_stack_
;創建鎖;創建TaskProcessor,ReferenceProcessor
- 創建一組回收器,里面有三個回收器分別是
MarkSweep, PartialMarkSweep, StickyMarkSweep
,如果是Concurrent Mark Compact
,則這一組回收器是支持并行GC的;如果是MarkSweep
,則這一組不支持并行GC - 如果ImageSpace創建成功且Non-Moving Space不為空同時滿足:處于Zygote或者Non-Moving Space有獨立地址時,檢查ImageSpace和Non-Moving Space之間有沒有內存間隙
因為Non-Moving Space有沒有獨立地址不確定,需要視條件而定