概述:
众所周知jvm虚拟机为了提高内存回收效率,更高效的进行内存管理与回收,对堆内存进行了分代管理比如hotspot虚拟机的新生代,老年代。根据各代的特征( 新生代对象分配频繁而生存周期短,老年代生存周期长不需要频繁回收)来应用不同的内存回收算法
art虚拟机也是如此,不过Android U上年轻代、老年代回收都采用的concurrent_copying回收算法,虚拟机定义了gc_type枚举类来定义不同的回收策略
enum GcType {
kGcTypeNone,
//粘性回收,只回收上次回收后分配的对象
kGcTypeSticky,
//部分回收,回收初zygote space之外的应用堆内存
kGcTypePartial,
//圈梁回收,应用堆包括zygote space
kGcTypeFull,
kGcTypeMax,
};
枚举类型自上至下回收力度逐渐增大,本文主要分析kGcTypeSticky,其他回收类型后续文章再分析
上图可以是在进行并发回收任务的时候(HeapTaskDaemon线程),如果没有找到合适的回收类型,会依次进行力度更大的回收
如果回收类型为 kGcTypeSticky,会启动年轻代回收器进行回收,那年轻代回收器到底是什么,都回收哪块内存就是我们今天要阐述的内容。
并发拷贝cc算法的一般流程:初始化->标记->复制->回收
art虚拟中并发拷贝算法的实现类concurrent_copying 中的gc全貌
void ConcurrentCopying::RunPhases() {
CHECK(kUseBakerReadBarrier || kUseTableLookupReadBarrier);
CHECK(!is_active_);
is_active_ = true;
Thread* self = Thread::Current();
thread_running_gc_ = self;
Locks::mutator_lock_->AssertNotHeld(self);
{
ReaderMutexLock mu(self, *Locks::mutator_lock_);
InitializePhase(); //初始化阶段
// In case of forced evacuation, all regions are evacuated and hence no
// need to compute live_bytes.
if (use_generational_cc_ && !young_gen_ && !force_evacuate_all_) {
MarkingPhase();
}
}
if (kUseBakerReadBarrier && kGrayDirtyImmuneObjects) {
// Switch to read barrier mark entrypoints before we gray the objects. This is required in case
// a mutator sees a gray bit and dispatches on the entrypoint. (b/37