Android ART虚拟机 GC的各种类型
前言
本文介绍ART虚拟机的GC类型,为下篇介绍ART的GC做准备。
GcRetentionPolicy
每个Space都有自己的gc回收策略,如下图所示:
- kGcRetentionPolicyNeverCollect:不需要回收某个Space所包含的垃圾对象(因为该Space可能不存在垃圾对象)。
- kGcRetentionPolicyAlwaysCollect:每次垃圾回收都需要处理某个Space空间。
- kGcRetentionPolicyFullCollect:直到最后时刻才回收某个Space空间中的垃圾对象。这个最后时刻就是所谓的full GC。
垃圾收集器类型 和 内存分配器类型
各种头文件
art/runtime/gc/collector_type.h
art/runtime/gc/allocator_type.h
art/runtime/gc/gc_cause.h
art/runtime/gc/collector/garbage_collector.h
// Which types of collections are able to be performed.
enum CollectorType {
// No collector selected.
kCollectorTypeNone,
// Non concurrent mark-sweep.
kCollectorTypeMS,
// Concurrent mark-sweep.
kCollectorTypeCMS,
// Semi-space / mark-sweep hybrid, enables compaction.
kCollectorTypeSS,
// A generational variant of kCollectorTypeSS.
kCollectorTypeGSS,
// Mark compact collector.
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,
};
// Different types of allocators.
enum AllocatorType {
kAllocatorTypeBumpPointer, // Use BumpPointer allocator, has entrypoints.
kAllocatorTypeTLAB, // Use TLAB allocator, has entrypoints.
kAllocatorTypeRosAlloc, // Use RosAlloc allocator, has entrypoints.
kAllocatorTypeDlMalloc, // Use dlmalloc allocator, has entrypoints.
kAllocatorTypeNonMoving, // Special allocator for non moving objects, doesn't have entrypoints.
kAllocatorTypeLOS, // Large object space, also doesn't have entrypoints.
kAllocatorTypeRegion,
kAllocatorTypeRegionTLAB,
};
// What caused the GC?
enum GcCause {
// GC triggered by a failed allocation. Thread doing allocation is blocked waiting for GC before
// retrying allocation.
kGcCauseForAlloc,
// A background GC trying to ensure there is free memory ahead of allocations.
kGcCauseBackground,
// An explicit System.gc() call.
kGcCauseExplicit,
// GC triggered for a native allocation.
kGcCauseForNativeAlloc,
// GC triggered for a collector transition.
kGcCauseCollectorTransition,
// Not a real GC cause, used when we disable moving GC (currently for GetPrimitiveArrayCritical).
kGcCauseDisableMovingGc,
// Not a real GC cause, used when we trim the heap.
kGcCauseTrim,
// Not a real GC cause, used to implement exclusion between GC and instrumentation.
kGcCauseInstrumentation,
// Not a real GC cause, used to add or remove app image spaces.
kGcCauseAddRemoveAppImageSpace,
// GC triggered for background transition when both foreground and background collector are CMS.
kGcCauseHomogeneousSpaceCompact,
// Class linker cause, used to guard filling art methods with special values.
kGcCauseClassLinker,
};
虚拟机启动时gc参数解析设置前后台回收器类型
oreground_collector_type_和background_collector_type_表示进程处于前台(即用户能感知)以及进程处于后台时的回收器类型。
- 前台回收器为CMS时,后台回收器为HSC。
- 前台回收器为SS时,后台回收器类型为HSC。
- 前台回收器类型为GSS时,后台回收器类型也必须为GSS。
art/runtime/parsed_options.cc
bool ParsedOptions::DoParse(const RuntimeOptions& options,
bool ignore_unrecognized,
RuntimeArgumentMap* runtime_options) {
{
// If not set, background collector type defaults to homogeneous compaction.
// If foreground is GSS, use GSS as background collector.
// If not low memory mode, semispace otherwise.
gc::CollectorType background_collector_type_;
gc::CollectorType collector_type_ = (XGcOption{}).collector_type_; // NOLINT [whitespace/braces] [5]
bool low_memory_mode_ = args.Exists(M::LowMemoryMode);
background_collector_type_ = args.GetOrDefault(M::BackgroundGc);
{
XGcOption* xgc = args.Get(M::GcOption);
if (xgc != nullptr && xgc->collector_type_ != gc::kCollectorTypeNone) {
collector_type_ = xgc->collector_type_;
}
}
if (background_collector_type_ == gc::kCollectorTypeNone) {
if (collector_type_ != gc::kCollectorTypeGSS) {
background_collector_type_ = low_memory_mode_ ?
gc::kCollectorTypeSS : gc::kCollectorTypeHomogeneousSpaceCompact;
} else {
background_collector_type_ = collector_type_;
}
}
args.Set(M::BackgroundGc, BackgroundGcOption { background_collector_type_ });
}
}
Heap构造函数根据回收器类型设置垃圾收集器
- 回收器类型为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;
}
ChangeCollector设置gc_plan_
- 如果回收器类型为CMS,则gc_plan_依次为kGcTypeSticky、kGcTypePartial和kGc-TypeFull。
- 如果回收器类型为SS或GSS,则gc_plan_只有kGcTypeFull一种策略。
// Change the collector to be one of the possible options (MS, CMS, SS).
void Heap::ChangeCollector(CollectorType collector_type) {
if (collector_type != collector_type_) {
collector_type_ = collector_type;
gc_plan_.clear();
switch (collector_type_) {
case kCollectorTypeCC: {
gc_plan_.push_back(collector::kGcTypeFull);
if (use_tlab_) {
ChangeAllocator(kAllocatorTypeRegionTLAB);
} else {
ChangeAllocator(kAllocatorTypeRegion);
}
break;
}
case kCollectorTypeMC: // Fall-through.
case kCollectorTypeSS: // Fall-through.
case kCollectorTypeGSS: {
gc_plan_.push_back(collector::kGcTypeFull);
if (use_tlab_) {
ChangeAllocator(kAllocatorTypeTLAB);
} else {
ChangeAllocator(kAllocatorTypeBumpPointer);
}
break;
}
case kCollectorTypeMS: {
gc_plan_.push_back(collector::kGcTypeSticky);
gc_plan_.push_back(collector::kGcTypePartial);
gc_plan_.push_back(collector::kGcTypeFull);
ChangeAllocator(kUseRosAlloc ? kAllocatorTypeRosAlloc : kAllocatorTypeDlMalloc);
break;
}
case kCollectorTypeCMS: {
gc_plan_.push_back(collector::kGcTypeSticky);
gc_plan_.push_back(collector::kGcTypePartial);
gc_plan_.push_back(collector::kGcTypeFull);
ChangeAllocator(kUseRosAlloc ? kAllocatorTypeRosAlloc : kAllocatorTypeDlMalloc);
break;
}
default: {
UNIMPLEMENTED(FATAL);
UNREACHABLE();
}
}
if (IsGcConcurrent()) {
concurrent_start_bytes_ =
std::max(max_allowed_footprint_, kMinConcurrentRemainingBytes) - kMinConcurrentRemainingBytes;
} else {
concurrent_start_bytes_ = std::numeric_limits<size_t>::max();
}
}
}
// Change the allocator, updates entrypoints.
void Heap::ChangeAllocator(AllocatorType allocator) {
if (current_allocator_ != allocator) {
current_allocator_ = allocator;
MutexLock mu(nullptr, *Locks::runtime_shutdown_lock_);
SetQuickAllocEntryPointsAllocator(current_allocator_);
Runtime::Current()->GetInstrumentation()->ResetQuickAllocEntryPoints();
}
}