Heap的創(chuàng)建位于/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));
...
}
一. 相關(guān)知識預熱
1.1 Garbage Collection Type
垃圾回收的算法有多種,如MarkSweep-標記清楚算法,MarkCompact-標記整理算法,Copying-復制算法等等,之前的Dalvik一直使用的是MarkSweep算法,ART則在MarkSweep的基礎(chǔ)上添加了對其他垃圾回收算法的支持,具體的算法可以通過-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根據(jù)三個編譯宏決定true或false,只要這個三個編譯宏中有一個存在,則kUseReadBarrier=true
gc::kCollectorTypeCC和gc::kCollectorTypeDefault定義在/art/runtime/gc/collector_type.h
enum CollectorType {
// No collector selected.
kCollectorTypeNone,
//普通Mark-Sweep
kCollectorTypeMS,
// 并發(fā)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,否則默認算法,默認算法根據(jù)編譯宏選擇,沒有特別指定的情況下使用Concurrent Mark-Sweep
二. Heap::Heap()
2.1 構(gòu)造函數(shù)聲明
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,//前臺堆增長因子(乘數(shù))
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,//大對象數(shù)量的閾值
size_t parallel_gc_threads,//GC暫停階段用于同時執(zhí)行GC任務(wù)的線程數(shù)
size_t conc_gc_threads,//并行GC的線程數(shù)
bool low_memory_mode,//是否是low memory mode
size_t long_pause_threshold,//GC造成應(yīng)用程序暫停的時間閥值,超過則輸出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執(zhí)行清掃前驗證堆
bool verify_post_gc_heap,//是否在GC完成清掃后驗證堆
bool verify_pre_gc_rosalloc,//是否在開始GC前驗證RosAllocSpace
bool verify_pre_sweeping_rosalloc,//是否在GC執(zhí)行清掃前驗證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 構(gòu)造函數(shù)實現(xiàn)
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暫停階段用于同時執(zhí)行GC任務(wù)的線程數(shù)
parallel_gc_threads_(parallel_gc_threads),
//concurrent gc線程數(shù)
conc_gc_threads_(conc_gc_threads),
//是否是低內(nèi)存模式
low_memory_mode_(low_memory_mode),
//GC造成應(yīng)用程序暫停的時間閥值,超過則輸出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創(chuàng)建時的鎖, Mutex
zygote_creation_lock_("zygote creation lock", kZygoteCreationLock),
//space::ZygoteSpace 在zygote space創(chuàng)建之前不會包含大對象
zygote_space_(nullptr),
//大對象數(shù)量的閾值
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),
//分配對象的上限數(shù),一旦超過著擱置會引起一次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創(chuàng)建以來
total_bytes_freed_ever_(0),
//總共釋放的對象自從heap創(chuàng)建以來
total_objects_freed_ever_(0),
//當前分配的bytes數(shù)量.每次釋放和分配以后都會更新
num_bytes_allocated_(0),
//native分配的bytes數(shù)量
native_bytes_allocated_(0),
//Mutex
native_histogram_lock_("Native allocation lock"),
//Histogram<uint64_t>,native分配的統(tǒng)計圖
native_allocation_histogram_("Native allocation sizes",
1U,
kNativeAllocationHistogramBuckets),
//native釋放的統(tǒng)計圖
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執(zhí)行清掃前驗證堆
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執(zhí)行清掃前驗證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.
*/
//分配棧最大數(shù)量
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 有一系列大小相等的區(qū)域組成
region_space_(nullptr),
//最小空余內(nèi)存
min_free_(min_free),
//最大空余內(nèi)存
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的狀態(tài)
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 數(shù)量
blocking_gc_count_(0U),
//blocking gc總共持續(xù)時間
blocking_gc_time_(0U),
//GC count rate統(tǒng)計圖最后已更新時間
last_update_time_gc_count_rate_histograms_( // Round down by the window duration.
(NanoTime() / kGcCountRateHistogramWindowDuration) * kGcCountRateHistogramWindowDuration),
//在上一個window運行的GC數(shù)量
gc_count_last_window_(0U),
//在上一個window運行的blocking GC數(shù)量
blocking_gc_count_last_window_(0U),
//每一個window的GC調(diào)用統(tǒng)計圖
gc_count_rate_histogram_("gc count rate histogram", 1U, kGcCountRateMaxBucketCount),
//每一個window的blocking GC調(diào)用統(tǒng)計圖
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 具體創(chuàng)建邏輯
Heap的構(gòu)造函數(shù)的代碼較多,不過整體邏輯比較清晰,整體邏輯可以分為以下幾塊:
- 判斷當前是否在zygote進程,如果不在zygote,將
background_collector_type_設(shè)為和foreground_collector_type_一樣,并檢查傳入的desired_collector_type_和collector_type_是否一樣,如果不一樣,則將collector_type_設(shè)為desired_collector_type_
Runtime* const runtime = Runtime::Current();
//判斷當前是否是zygote模式,如果不是判斷后臺回收器類型是否和前臺回收器相等,不想等,則設(shè)為相等
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_);
- 創(chuàng)建兩個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,設(shè)置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;
}
- 根據(jù)傳入的image文件路徑(
/system/framework/boot.art)創(chuàng)建ImageSpace,在ImageSpace后面緊跟的是/system/framework/boot.oat,如果創(chuàng)建成功,將requested_alloc_space_begin指向boot.oat地址的末尾;如果創(chuàng)建ImageSpace失敗,刪除已加載的Space,將requested_alloc_space_begin指回原來的(300MB-non_moving_space_capacity)
//創(chuàng)建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;
//創(chuàng)建boot_image_space
space::ImageSpace* boot_image_space = space::ImageSpace::CreateBootImage(
image_name.c_str(),
image_instruction_set,
index > 0,
&error_msg);
//創(chuàng)建boot_image_space成功
if (boot_image_space != nullptr) {
/* 根據(jù)boot_image_space是否時連續(xù)空間,將boot_image_space添加到對應(yīng)的Space列表,并在live_bitmap_和mark_bitmap_中添加對應(yīng)的位圖 */
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文件,根據(jù)OatHeader獲取boot_classpath,再根據(jù)boot_classpath生成
//oat文件完整路徑,將完整路徑添加進image文件列表,從而可以在下次循環(huán)中加載
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 {
//創(chuàng)建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
- 創(chuàng)建兩個內(nèi)存映射
MemMap
std::unique_ptr<MemMap> main_mem_map_1;
std::unique_ptr<MemMap> main_mem_map_2;
- 如果之前創(chuàng)建ImageSpace失敗同時
foreground_collector_type_是MarkSweep而且此時的Runtime由dex2oat創(chuàng)建即處于dex2oat進程中時,將requested_alloc_space_begin指向kAllocSpaceBeginForDeterministicAoT
// 如果前臺回收器是MS(MarkSweep)且requested_alloc_space_begin
// 是null(即之前ImageSpace創(chuàng)建失敗)同時當前是dex2oat程序
// 將requested_alloc_space_begin設(shè)為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有獨立地址,根據(jù)當前是否是zygote確定Non-Moving Space的名字,之后創(chuàng)建一塊匿名內(nèi)存映射,由non_moving_space_mem_map指向,non_moving_space_mem_map緊跟在requested_alloc_space_begin后面,如果ImageSpace創(chuàng)建成功,就是緊跟在ImageSpace+boot.oat后面,否則緊跟在kAllocSpaceBeginForDeterministicAoT后面,最后設(shè)置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設(shè)為zygote space
const char* space_name = is_zygote ? kZygoteSpaceName: kNonMovingSpaceName;
//創(chuàng)建匿名內(nèi)存映射
//non moving sapce緊跟在requested_alloc_space_begin后面(即如果ImageSpace創(chuàng)建成功,緊跟在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的起始地址設(shè)為300MB,由request_begin指向
request_begin = reinterpret_cast<uint8_t*>(300 * MB);
}
- 如果
foreground_collector_type_不是CC,初始化之前創(chuàng)造的main_mem_map_1,這塊內(nèi)存的作用是作為MarkSweep的Main Space或者Compact GC的From-Bump-Space.當Non-Moving Space有獨立地址且當前不處于Zygote時,緊跟在300MB后面創(chuàng)建匿名內(nèi)存映射;否則緊跟在ImageSpace+boot.oat后面創(chuàng)建匿名內(nèi)存映射
//如果前臺回收器不是CC,創(chuàng)建第一塊匿名共享內(nèi)存,由main_mem_map_1指向,這塊內(nèi)存的作用是作為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時,創(chuàng)建第二塊匿名內(nèi)存映射main_mem_map_2
//如果支持homogeneous space compact或者后臺回收器和前臺回收器中有一個為為SS(Semi Space)時,創(chuàng)建第二塊匿名共享內(nèi)存
//由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有獨立地址,則之前已經(jīng)創(chuàng)建了匿名內(nèi)存映射
non_moving_space_mem_map,現(xiàn)在將這塊內(nèi)存封裝成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);
//設(shè)置Non-Moving Space大小限制
non_moving_space_->SetFootprintLimit(non_moving_space_->Capacity());
...
//將non_moving_space_添加至space列表中
AddSpace(non_moving_space_);
}
- 根據(jù)條件處理之前創(chuàng)建的另外兩塊匿名內(nèi)存映射
main_mem_map_1和main_mem_map_2.因為在之前的邏輯中,當foreground_collector_type_是CC時,并沒有創(chuàng)建main_mem_map_1匿名內(nèi)存映射,所以如果foreground_collector_type_恰好是CC時,緊跟request_begin(如果Non-Moving Space有獨立地址,則是300MB,否則是ImageSpace+boot.oat)創(chuàng)建一個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共用同一塊內(nèi)存,接著判斷如果foreground_collector_type_是GSS時,調(diào)用BumpPointerSpace::Craete直接創(chuàng)建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),創(chuàng)建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創(chuàng)建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, 并創(chuàng)建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_);
//創(chuàng)建第二塊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) {
//此時前臺回收器根據(jù)排除法只剩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());
}
}
- 創(chuàng)建大對象存儲空間.
// 創(chuàng)建LargeObjectSpace(大對象存儲空間)
if (large_object_space_type == space::LargeObjectSpaceType::kFreeList) {
//如果LargeObjectSpace類型是FreeList,創(chuàng)建FreeList類型的LargeObjectSpace
large_object_space_ = space::FreeListSpace::Create("free list large object space", nullptr,
capacity_);
...
} else if (large_object_space_type == space::LargeObjectSpaceType::kMap) {
//創(chuàng)建相互獨立的內(nèi)存快組成的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且創(chuàng)建了Backup Space時,由于Backup Space占用的額外的空間會降低GC速度,所以移除Backup Space;之后創(chuàng)建CardTable(Card Table是為了記錄在垃圾收集過程中對象的引用情況的),ModUnionTable(來記錄ImageSpace對ZygoteSpace引用情況的ModUnionTable),RememberSet(用來記錄Non-moving Space對其他Space引用情況的RememberedSet,GSS時不會創(chuàng)建,CC, SS, MC, HomogeneousSpaceCompact時根據(jù)collector::SemiSpace::kUseRememberedSet == true判斷,MS,CMS時根據(jù)Non-Moving Space有沒有獨立地址加collector::SemiSpace::kUseRememberedSet == true判斷)
//獲取連續(xù)空間的起始地址和結(jié)束地址
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());
}
...
// 創(chuàng)建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,創(chuàng)建ReadBarrierTable
if (foreground_collector_type_ == kCollectorTypeCC && kUseTableLookupReadBarrier) {
rb_table_.reset(new accounting::ReadBarrierTable());
...
}
if (HasBootImageSpace()) {
// 如果有ImageSpace,則創(chuàng)建用來記錄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,
//創(chuàng)建用來記錄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);
}
- 創(chuàng)建
Mark-Stack,Allocation-Stack,Live-Stack;創(chuàng)建之后GC需要用到的的鎖;創(chuàng)建TaskProcessor,ReferenceProcessor;如果前后臺回收器有一個是CMS,則創(chuàng)建一組包含三個支持并發(fā)的Collector:MarkSweep, PartialMarkSweep, StickyMarkSweep回收器; 如果前后臺回收器有一個是MS,則創(chuàng)建一組包含三個不支持并發(fā)的Collector:MarkSweep, PartialMarkSweep, StickyMarkSweep回收器;之后再根據(jù)條件創(chuàng)建Semi-Space Collector(SS或GSS時創(chuàng)建),Concurrent-Copying Collector(CC時創(chuàng)建),Mark Compact Collector(MS,CMSshichu)
// TODO: Count objects in the image space here?
num_bytes_allocated_.StoreRelaxed(0);
// 創(chuàng)建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));
// 創(chuàng)建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_));
//創(chuàng)建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_) {
//如果不限制堆的增長,則將堆的最大限制數(shù)設(shè)為最大
SetIdealFootprint(std::numeric_limits<size_t>::max());
//將concurrent gc的啟動值也設(shè)為最大,即只有堆達到最大時,才開啟concurrent gc
concurrent_start_bytes_ = std::numeric_limits<size_t>::max();
}
...
// 如果前后臺回收器有一個是CMS,則創(chuàng)建一組包含三個支持并發(fā)的Collector:MarkSweep, PartialMarkSweep, StickyMarkSweep回收器
// 如果前后臺回收器有一個是MS,則創(chuàng)建一組包含三個不支持并發(fā)的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時,再創(chuàng)鍵一個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,再創(chuàng)建一個ConcurrentCopying Collector
concurrent_copying_collector_ = new collector::ConcurrentCopying(this);
garbage_collectors_.push_back(concurrent_copying_collector_);
}
if (MayUseCollector(kCollectorTypeMC)) {
//如果前后臺回收器中某一個是MarkCompact,再創(chuàng)建一個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之間沒有內(nèi)存空隙
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只見沒有內(nèi)存空隙
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();
}
三. 總結(jié)
3.1 前臺回收器是ConcurrentCopying
從代碼邏輯看,如果foreground_collector_type_=kCollectorTypeCC時Heap的創(chuàng)建流程要跟其他回收器類型的創(chuàng)建流程不太相同:
requested_alloc_space_begin = 300MB - non_moving_space_capacity- 創(chuàng)建ImageSpace(只要image文件不為空,都會創(chuàng)建),如果創(chuàng)建成功,
requested_alloc_space_begin=ImageSpace+boo.oat
這一點所有回收器類型都一樣,不同的是,如果創(chuàng)建失敗,
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創(chuàng)建失敗,requested_alloc_space_begin也不會為nullptr,又因為Non-Moving Space有獨立的地址,所以最后request_begin=requested_alloc_space_begin + non_moving_space_capacity
如果ImageSpace創(chuàng)建成功,
request_begin=ImageSpace+boot.oat+non_moving_space_capacity;如果創(chuàng)建失敗,request_begin = 300MB-non_moving_space_capacity+non_moving_space_capacity->request_begin=300MB
- 緊跟著
requested_alloc_space_begin創(chuàng)建用于Non-Moving Space的匿名內(nèi)存映射non_moving_space_mem_map, 將request_begin固定在300MB的地址(request_begin=reinterpret_cast<uint8_t*>(300*MB));之后將匿名內(nèi)存映射封裝成Non-Moving Space,如果在Zygote中,就叫ZygoteSpace,否則叫Non-Moving Space - 由于是
CC回收器,所以不會創(chuàng)建兩塊匿名內(nèi)存main_mem_map_1,main_mem_map_2,而是緊跟著在request_begin后(即300MB,因為之前已經(jīng)將request_begin固定在這個地址)直接創(chuàng)建RegionSpace - 創(chuàng)建
LargeObjectSpace - 如果
kUseTableLookupReadBarrier=true,創(chuàng)建ReadBarrierTable - 創(chuàng)建
CardTable,ModUnionTable(如果ImageSpace創(chuàng)建成功),如果collector::SemiSpace::kUseRememberedSet == true創(chuàng)建RememberedSet;創(chuàng)建allocation_stack_,mark_stack_,live_stack_;創(chuàng)建鎖;創(chuàng)建TaskProcessor,ReferenceProcessor - 由于是
CC回收器,創(chuàng)建collector::ConcurrentCopying并添加至garbage_collectors_ - 如果ImageSpace創(chuàng)建成功,且Non-Moving Space不為空,檢查ImageSpace和Non-Moving Space之間有沒有內(nèi)存間隙
因為是
CC,所以Non-Moving Space必然有獨立地址,所以只需要判斷ImageSpace創(chuàng)建成功和Non-Moving Space不為空
3.2 前臺回收器是GSS
GSS(Generational Semi-Space)是另一個較為特殊的回收器類型
requested_alloc_space_begin=nullptr- 創(chuàng)建ImageSpace,如果成功,
requested_alloc_space_begin=ImageSpace+boot.oat,如果創(chuàng)建失敗,requested_alloc_space_begin=nullptr - 如果
background_collector_type_ != kCollectorTypeHomogeneousSpaceCompact,則肯定不支持Homogeneous-Space-Compact - 由于是
GSS回收器,所以不會給Non-Moving Space獨立的地址(這一點很重要,即不會創(chuàng)建Non-Moving Space的匿名內(nèi)存映射) - 如果ImageSpace創(chuàng)建失敗,則
request_begin=requested_alloc_space_begin=nullptr;如果創(chuàng)建成功,則request_begin=reuqest_alloc_space_begin=ImageSpace+boo.oat - 由于是
GSS回收器,那么Non-Moving Space不會有獨立地址,如果此時處于Zygote中,則緊跟ImageSpace+boo.oat創(chuàng)建匿名內(nèi)存映射main_mem_map_1(因為Non-Moving Space沒有獨立地址,所以不會將request_begin固定在300MB,又因為如果ImageSpace創(chuàng)建成功此時request_begin=ImageSpace+boot.oat) - 如果
background_collector_type_ == kCollectorTypeHomogeneousSpaceCompact,則會緊跟著main_mem_map_1再創(chuàng)建第二塊匿名內(nèi)存映射main_mem_map_2,否則不會創(chuàng)建main_mem_map_2 - 將
main_mem_map_1封裝成Main Space,由于是GSS回收器,所以將non_moving_space_也指向Main Space - 由于是
GSS回收器,調(diào)用space::BumpPointerSpace::Create直接創(chuàng)建BumpPointerSpace1和BumpPointerSpace2 - 創(chuàng)建
LargeObjectSpace - 創(chuàng)建
CardTable,ModUnionTable(如果ImageSpace創(chuàng)建成功),由于是GSS回收器,所以non_moving_space_ == main_space_,所以不會創(chuàng)建RememberedSet;創(chuàng)建allocation_stack_,mark_stack_,live_stack_;創(chuàng)建鎖;創(chuàng)建TaskProcessor,ReferenceProcessor - 由于是
GSS,所以創(chuàng)建collector::SemiSpace,其中generational_ = true - 如果ImageSpace創(chuàng)建成功,且
MainSpace不為空,檢查ImageSpace和Non-Moving Space之間有沒有內(nèi)存間隙
因為是
GSS,所以non_moving_space_指向MainSpace,所以只需要判斷ImageSpace創(chuàng)建成功和Non-Moving Space不為空
3.3 Moving GC(Semi-Space, MarkCompact, HomogeneousSpaceCompact)
requested_alloc_space_begin=nullptr- 創(chuàng)建ImageSpace,如果成功,
requested_alloc_space_begin=ImageSpace+boot.oat,如果創(chuàng)建失敗,requested_alloc_space_begin=nullptr - 由于不是
GSS和CC,所以只要傳入的use_homogeneous_space_compaction==true或者background_collector_type_ == kCollectorTypeHomogeneousSpaceCompact時會支持Homogeneous-Space-Compact - Non-Moving必然有獨立的地址
- 如果ImageSpace創(chuàng)建成功,
request_begin = requested_alloc_space_begin + non_moving_space_capacity,否則request_begin=nullptr - 創(chuàng)建Non-Moving Space使用的匿名內(nèi)存映射
non_moving_space_mem_map,將request_begin固定在300MB的地址(request_begin=reinterpret_cast<uint8_t*>(300*MB)) - 緊跟
request_begin創(chuàng)建匿名內(nèi)存映射main_mem_map_1 - 如果支持Homogeneous-Space-Compact或者前后臺回收器有一個是
Semi-Space,則緊跟main_mem_map_1創(chuàng)建第二塊匿名內(nèi)存映射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 - 創(chuàng)建
LargeObjectSpace - 創(chuàng)建
CardTable,ModUnionTable(如果ImageSpace創(chuàng)建成功),如果collector::SemiSpace::kUseRememberedSet == true創(chuàng)建RememberedSet;創(chuàng)建allocation_stack_,mark_stack_,live_stack_;創(chuàng)建鎖;創(chuàng)建TaskProcessor,ReferenceProcessor - 如果前后臺回收器中有一個是
SS或Homogeneous-Space-Compact,創(chuàng)建collector::SemiSpace;如果前后臺回收器有一個是MarkCompact,則創(chuàng)建collector::MarkCompact - 如果ImageSpace創(chuàng)建成功,且Non-Moving Space不為空,檢查ImageSpace和Non-Moving Space之間有沒有內(nèi)存間隙
因為Non-Moving必然有獨立的地址,所以只需要判斷ImageSpace創(chuàng)建成功和Non-Moving Space不為空
3.4 前臺回收器MarkSweep或Concurrent MarkSweep
requested_alloc_space_begin=nullptr- 創(chuàng)建ImageSpace,如果成功,
requested_alloc_space_begin=ImageSpace+boot.oat,如果創(chuàng)建失敗,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創(chuàng)建失敗且
foreground_collector_type_=kCollectorTypeMS同時當前處于dex2oat,requested_alloc_space_begin=kAllocSpaceBeginForDeterministicAoT - 如果ImageSpace創(chuàng)建成功且如果Non-Moving Space有獨立地址的話,創(chuàng)建Non-Moving Space要用到的匿名內(nèi)存映射
non_moving_space_mem_map,將request_begin固定在300MB的地址(request_begin=reinterpret_cast<uint8_t*>(300*MB)) - 如果Non-Moving Space有獨立地址或者當前不在Zygote中,緊跟著
request_begin(300MB)創(chuàng)建匿名內(nèi)存映射main_mem_map_1;如果Non-Moving Space沒有獨立地址同時處于Zygote中,則緊跟著ImageSpace_boot.oat創(chuàng)建匿名內(nèi)存映射main_mem_map_1 - 如果支持Homogeneous-Space-Compact,緊跟著
main_mem_map_1創(chuàng)建第二塊匿名內(nèi)存映射main_mem_map_2,否則不創(chuàng)建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 - 如果之前創(chuàng)建了
main_mem_map_2,則將main_mem_map_2封裝成Main Backup Space - 創(chuàng)建
LargeObjectSpace - 移除
Main Backup Space - 創(chuàng)建
CardTable,ModUnionTable(如果ImageSpace創(chuàng)建成功),如果Non-Moving Space有獨立地址,創(chuàng)建RememberedSet,否則不創(chuàng)建;創(chuàng)建allocation_stack_,mark_stack_,live_stack_;創(chuàng)建鎖;創(chuàng)建TaskProcessor,ReferenceProcessor - 創(chuàng)建一組回收器,里面有三個回收器分別是
MarkSweep, PartialMarkSweep, StickyMarkSweep,如果是Concurrent Mark Compact,則這一組回收器是支持并行GC的;如果是MarkSweep,則這一組不支持并行GC - 如果ImageSpace創(chuàng)建成功且Non-Moving Space不為空同時滿足:處于Zygote或者Non-Moving Space有獨立地址時,檢查ImageSpace和Non-Moving Space之間有沒有內(nèi)存間隙
因為Non-Moving Space有沒有獨立地址不確定,需要視條件而定