GC1_MS_CMS

MarkSweep类家族

image-20210214155402726

表14-1 MarkSweep类家族GetGcType取值情况

集合Live和集合Mark构成

image-20210215103550136

CMS时Heap space相关成员变量取值情况

image-20210215104155814

CMS时Heap位图相关成员变量取值情况

image-20210215104300766

图14-7 CMS时Heap位图相关成员变量取值情况

一个HeapBitmap对象可以管理多个ContinuousSpace的某一种位图对象

CMS时Heap mark_stack_等成员变量的情况

image-20210215104426808

MarkSweep::MarkSweep

MarkSweep::MarkSweep(Heap* heap, bool is_concurrent,
                    const std::string& name_prefix)
        : GarbageCollector(heap,      name_prefix +
                        (is_concurrent ? "concurrent mark sweep": "mark sweep")),
        current_space_bitmap_(nullptr),
        mark_bitmap_(nullptr), mark_stack_(nullptr),
        .....
        is_concurrent_(is_concurrent),...... {
    /*MarkSweep构造函数并不复杂,此处先介绍下它的几个成员变量(其作用留待后续代码分析时时再详细讲解):
    current_space_bitmap_:类型为ContinuousSpaceBitmap*。
    mark_bitmap_:类型为HeapBitmap*。
    mark_stack_:类型为ObjectStack*。  */
    .....
    /*下面的代码行将创建一个内存映射对象。ART内部大量使用内存映射对象。下面的
      sweep_array_free_buffer_mem_map_的用法需要到介绍StickyMarkSweep时才能见到。总之,读者将它看作一块内存即可。*/
    MemMap* mem_map = MemMap::MapAnonymous(......);
    sweep_array_free_buffer_mem_map_.reset(mem_map);
    .....
    }

MarkSweep::RunPhases

图解

graph TB
IsConcurrent{IsConcurrent}-->|yes|MarkingPhaseC(MarkingPhase)
MarkingPhaseC-->pauseC(pause)
pauseC-->PausePhaseC("PausePhase_reMark")
PausePhaseC-->RevokeAllThreadLocalBuffers
RevokeAllThreadLocalBuffers-->ReclaimPhase
ReclaimPhase-->FinishPhase

IsConcurrent-->|no|pause
pause-->MarkingPhase
MarkingPhase-->PausePhase
PausePhase-->RevokeAllThreadLocalBuffers
void MarkSweep::RunPhases() {
    Thread* self = Thread::Current();
    //初始化MarkSweep类的几个成员变量。其中,MarkSweep的mark_bitmap_将设置为Heap的成员变量mark_bitmap_(读者可回顾图14-7)
    InitializePhase();
    if (IsConcurrent()) {//if条件为true,则是CMS的行为
        ......
        { /*CMS和MS的区别:下面代码中ReaderMutexLock为辅助类,真正用于同步的关键对象为
          mutator_lock_。它是一个全局定义的读写互斥锁。即支持多个线程同时进行读操作。但如果
          某个线程要执行写操作的话,必须等待所有执行读操作的线程释放这个锁。同理,执行写操作的
          线程如果先抢到这个锁的话,其他想做读操作或写操作的线程都必须要等待当前拥有这个锁的写
          线程释放该锁。ReaderMutextLock在构造函数中将针对mutator_lock_申请一个读锁,而在析构函数中释放读锁。*/
        ReaderMutexLock mu(self, *Locks::mutator_lock_);
        MarkingPhase();//①标记工作,详情见下文代码分析,main
        }
    /*ScopedPause也是一个辅助类,其构造函数中会暂停除调用线程外其他所有Java线程的运行,其内部
      调用ThreadList的SuspendAll,详情可参考12.2.3节的内容。ScopedPause的析构函数中会恢复这些线程的运行。
      简单来说,下面的这段代码运行时,其他Java线程将停止运行。  */
    ScopedPause pause(this);
    ....
    PausePhase();//②PausePhase的详情见下文代码分析,main
      
    /*撤销线程对象的TLAB空间。此后Thread TLAB空间为0,TLAB的作用在于加速内存分配的速度。
      TLAB所需的内存资源来自对应的空间对象,例如BumpPointerSpace、RegionSpace等。请读者
      注意,Revoke是撤销的意思,不是Free(释放)。撤销TLAB之后那些创建在TLAB上的对象依然存在。
      这些对象中的垃圾对象将在后续清除阶段回收。*/
        RevokeAllThreadLocalBuffers();
    } else {
        //如果回收器类型为MS,则先暂停其他Java线程的运行,
        ScopedPause pause(this);
        .....
        MarkingPhase();
        ......
        PausePhase();
        RevokeAllThreadLocalBuffers();
    }
    //标记相关的工作结束,开始准备清除工作
    { //注意,mutator_lock_被用作读锁。这和上面CMS逻辑中调用MarkingPhase函数的处理
      //一样。这说明无论CMS还是MS,清除任务(Reclaim Phase)可以和mutator同时执行
        ReaderMutexLock mu(self, *Locks::mutator_lock_);
        ReclaimPhase();//③回收工作,详情见下文代码分析,main
    }
    .....
    FinishPhase();//④GC的收尾,详情见下文代码分析,main
}

InitializePhase

……

MarkingPhase

图解

graph LR
MarkingPhase-->|标记根对象|MarkRoots-->VisitRoots("Runtime::Current()->VisitRoots(this)")
MarkRoots-->PushOnMarkStack
MarkingPhase-->|从根对象触发编辑所有能追踪到的对象|MarkReachableObjects-->Object.VisitReferences
void MarkSweep::MarkingPhase() {
    TimingLogger::ScopedTiming t(__FUNCTION__, GetTimings());
    Thread* self = Thread::Current();
    //①我们单独介绍下面三个函数调用,笔者将它们归为标记前的准备工作
    BindBitmaps();
    FindDefaultSpaceBitmap();
    /*调用Heap ProcessCards函数,该函数的作用见下文解释。此处请注意最后一个参数的取值:
    (1) MarkSweep GetGcType返回kGcTypeFull,所以最后一个参数取值为false。
    (2) PartialMarkSweep GetGcType返回kGcTypePartial,所以最后一个参数取值为false。
    (3) StickyMarkSweep GetGcType返回值为kGcTypeSticky,所以最后一个参数取值为
        true。 */
    heap_->ProcessCards(GetTimings(), false, true, GetGcType() != kGcTypeSticky);
    WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
    //②标记相关函数,,标记的信息保存在各个空间的mark_bitmap_中
    MarkRoots(self);//MarkRoots用于标记根对象
    MarkReachableObjects();//从根对象出发以标记所有能追踪到的对象
    //③下面这个函数和CMS有关,我们后续统一介绍它
    PreCleanCards();
}

BeforeMark

BindBitmaps
void MarkSweep::BindBitmaps() {
    ......
    WriterMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_);
    /*搜索Heap continuous_spaces_数组中的空间对象,如果某个空间对象的gc_retention_policy_
      成员变量取值为kGcRetentionPolicyNeverCollect,则将它加入MarkSweep immune_spaces_
      (类型为ImmuneSpace,其内部有一个std set容器)中。回顾13.7.1节的内容可知,只有ImageSpace
      (结合14.3.3节的图14-6可知,它就是boot.art文件映射到内存后得到的空间对象)满足这个条
      件。再次请读者注意,kGcRetentionPolicyNeverCollect表示不用对该空间的对象进行垃圾回收。*/
    for (const auto& space : GetHeap()->GetContinuousSpaces()) {
        if (space->GetGcRetentionPolicy() == space::kGcRetentionPolicyNeverCollect) {
            immune_spaces_.AddSpace(space);//AddSpace的代码见下文介绍
        }
    }
}

immune_spaces.cc

ImmuneSpaces::AddSpace
void ImmuneSpaces::AddSpace(space::ContinuousSpace* space) {
    //ImageSpace重载了GetLiveBitmap和GetMarkBitmap函数,返回的都是
    //ImageSpace的live_bitmap_成员。所以,下面的if条件对ImageSpace而言并不满足
    if (space->GetLiveBitmap() != space->GetMarkBitmap()) {
        //调用ContinuousMemMapAllocSpace BindLiveToMarkBitmap函数。它的作用我们
        //在StickyMarkSweep类中再来介绍。MarkSweep还用不到它
        space->AsContinuousMemMapAllocSpace()->BindLiveToMarkBitmap();
    }
    //spaces_是ImmuneSpace的成员,为一个std set集合
    spaces_.insert(space);
    //ImmuneSpaces是一个辅助类的数据结构
    CreateLargestImmuneRegion();
}
FindDefaultSpaceBitmap
void MarkSweep::FindDefaultSpaceBitmap() {
    ......
    //遍历Heap continuous_space_数组,读者可回顾图14-6了解CMS情况下Heap continuous_space_数组的取值情况
    for (const auto& space : GetHeap()->GetContinuousSpaces()) {
        accounting::ContinuousSpaceBitmap* bitmap = space->GetMarkBitmap();
        /*参考13.7.1节的内容可知,DlMallocSpace和RosAllocSpace
          都满足下面的if条件(它们的回收策略为kGcRetentionPolicyAlwaysCollect)。
          if条件满足后,将把空间对象中的mark_bitmap_赋值给MarkSweep的成员变量 current_space_bitmap_。*/
        if (bitmap != nullptr &&  space->GetGcRetentionPolicy() == space::kGcRetentionPolicyAlwaysCollect) {
        //current_space_bitmap_为MarkSweep的成员变量,指向一个ContinuousSpaceBitmap对象
            current_space_bitmap_ = bitmap;
            //从下面这个if条件来看,current_space_bitmap_取值来自Heap main_space_的
            //mark_bitmap_。读者可回顾14.3.3节中的图14-6
            if (space != heap_->GetNonMovingSpace()) { break; }
        }
    }
}
Heap::ProcessCards
void Heap::ProcessCards(..., bool use_rem_sets, bool process_alloc_space_cards, bool clear_alloc_space_cards) {
    /*注意参数,MarkSweep 调用它时,所传入的参数值为:
      use_rem_sets为false。 process_alloc_space_cards为true。clear_alloc_space_cards为true。  */
    //遍历continuous_spaces_数组
    for (const auto& space : continuous_spaces_) {
        //找到和这个space关联的ModUnionTable或者RememberedSet对象
       //无论使用ModUnionTable还是RememberedSet,最终操作的都是Heap card_table_
        accounting::ModUnionTable* table = FindModUnionTableFromSpace(space);
        accounting::RememberedSet* rem_set = FindRememberedSetFromSpace(space);
        /*在Heap PreZygoteFork被调用前,Heap中space对象的情况见图14-6。在那里,
          ImageSpace对象关联了一个ModUnionTable对象,其余两个空间对象各关联了
          一个RememberedSet对象。  */
        if (table != nullptr) {
            /*调用ModUnionTable的ClearCards函数,其作用我们在13.8.2.4节中曾介绍过。
              该函数调用的结果是:
            这个ModUnionTable管理的空间对象在Heap CardTable中对应card的值将发生如下变化:
            (1) 如果card旧值为kCardDirty,则设置其新值为kCardDirty - 1,
            (2) 否则设置其新值为0。*/
        table->ClearCards();
    } else if (use_rem_sets&& rem_set != nullptr) {
        /*在本例中,use_rem_sets取值为false,if条件不满足。RememberedSet ClearCards
          函数的代码见13.8.2.3.1节。其效果和上面ModUnionTableClearCards一样。 */
        rem_set->ClearCards();
    } else if (process_alloc_space_cards) {//对本例而言,该参数为true
        if (clear_alloc_space_cards) {//满足条件
            /*下面将处理card_table_中覆盖space对象的card信息。ClearCardRange函数
              将设置对应card的值为0。*/
            uint8_t* end = space->End();
            ......
            card_table_->ClearCardRange(space->Begin(), end);
            } else {
                /*如果clear_alloc_space_cards为false,则调用CardTable的
                ModifyCardsAtomic函数修改对应内存范围的card的值。其中:
                (1) 如果card的旧值为kCardDirty,则新值为kCardDirty-1
                (2) card的旧值为非kCardDirty时,新值为0。*/
                card_table_->ModifyCardsAtomic(space->Begin(), space->End(),
                                AgeCardVisitor(),VoidFunctor());
        }
}  } }

Mark

MarkRoots
void MarkSweep::MarkRoots(Thread* self) {
    ......
    if (Locks::mutator_lock_->IsExclusiveHeld(self)) {
        /*如果if条件为true,说明其他Java线程已暂停运行。14.2节中我们已经介绍过Runtime
          VisitRoots函数了。此处,MarkSweep实现了RootVisitor接口。下面将直接介绍MarkSweep
          所实现的RootVisitor VisitRoots接口函数。*/
        Runtime::Current()->VisitRoots(this);
        /*下面这个函数将遍历所有Thread对象,设置它们的tlsPtr_thread_local_alloc_stack_
          end和thread_local_alloc_stack_top为空,即收回线程的Allocation Stack空间。
          注意,结合图14-8的内容和13.6.4.3节的相关知识可知,此处只是将线程的Allocation Stack
          空间大小设置为0,而存储在Allocation Stack中的信息依然存在(因为Heap allocation_
          stack_没有被修改)。*/
        RevokeAllThreadLocalAllocationStacks(self);
    } else {
    ......//和CMS有关,详见14.4.9节
    }
}
VisitRoots
void MarkSweep::VisitRoots(mirror::Object*** roots, size_t count,const RootInfo& info) {
    for (size_t i = 0; i < count; ++i) {
        MarkObjectNonNull(*roots[i]);
    }
}
void MarkSweep::VisitRoots(CompressedReference<Object>** roots, size_t count,const RootInfo& info) {
    for (size_t i = 0; i < count; ++i) {
        MarkObjectNonNull(roots[i]->AsMirrorPtr());
    }
}
MarkObjectNonNull
//对Obj进行标记。标记就是设置该Obj所在空间对象的mark_bimap_位图对应位的值为1。
//这个新被标记的Obj保存到MarkSweep mark_sweep_容器中。
inline void MarkSweep::MarkObjectNonNull(mirror::Object* obj,
                 mirror::Object* holder, MemberOffset offset) {
    //MarkObjectNonNull最后两个参数有默认值,分别为nullptr和MemberOffset(0)
    ......
    //如果obj位于immune_spaces_所包含的空间对象中,则无须标记,详情见if中的解释
    if (immune_spaces_.IsInImmuneRegion(obj)) {
        ......
        /*注意下面这句调试时才会执行的代码。MarkSweep成员变量mark_bitmap_类型为HeapBitmap,
          它其实就是Heap的mark_bitmap_成员。回顾本章的图14-6可知,HeapBitmap包含了所有
          连续空间对象的mark_bitmap_成员。不过,对ImageSpace来说,它的live_bitmap_也被
          包含在Heap mark_bitmap_中了。
          在下面这行代码中,Test函数将测试obj在位图中对应的位是否为1。如果Test返回值为0,
          DCHECK会打印一条错误信息(如果打开调试的话)。这说明一个Obj如果位于ImageSpace空
          间的话,它一定是存活的(同时也是早就被标记了的。因为ImageSpaceGetMarkBitmap返回
          的也是live_bitmap_)。但是,请读者注意,尽管位于ImageSpace空间中的对象是长久存
          活的,但是这些对象的引用型成员变量所指向的对象却可能位于其他空间,而这些对象就可能
          是垃圾。*/
        DCHECK(mark_bitmap_->Test(obj));
    } else if (LIKELY(current_space_bitmap_->HasAddress(obj))) {
        /*根据“准备工作”一节FindDefaultSpaceBitmap函数可知,current_space_bitmap_
          为某个空间对象的mark_bitmap_。判断一个Obj是否被标记的标准就是该Obj
          在mark_bitmap_中对应位的值是否为1。所以,本段代码的主要工作可总结为:
          (1) HasAddress检查current_space_bitmap_对应的内存空间是否包含了obj对象
          (2) 如果满足条件,则调用Set函数设置obj对应位的值为1。于是,这个Obj就算被标记了。
          (3) Set函数返回该位的旧值。如果旧值为0,说明这个obj之前没有被标记。调用
          PushOnMarkStack将obj加入到MarkSweep mark_stack_容器中。mark_stack_为 一个ObjectStack对象。   */
        if (UNLIKELY(!current_space_bitmap_->Set(obj))) {
            PushOnMarkStack(obj);
        }
    } else {
        /*说明obj不在current_space_bitmap_所关联的那个空间对象中,此时就需要搜索Heap
          所有的空间对象,显然这比直接操作current_space_bitmap_要耗时。从这里可以看出,
          使用current_space_bitmap_是一种优化处理。后面我们还会看到类似的这种优化处理。*/
        ......
        /*mark_bitmap_指向一个HeapBitmap对象,它就是Heap中的mark_bitmap_。根据图
          14-8的介绍,HeapBitmap管理了所有空间对象的SpaceBitmap。下面的Set函数将搜索
          所有空间对象,找到包含这个Obj的Space对象,然后设置对应位的值。 */
        if (!mark_bitmap_->Set(obj,...)) {
            PushOnMarkStack(obj);
        }
    }
}
MarkReachableObjects
void MarkSweep::MarkReachableObjects() {
    //处理immune_spaces_空间中的对象,对理解card table的作用非常关键,请读者注意
    UpdateAndMarkModUnion();
    RecursiveMark();//我们重点介绍这个函数
}
UpdateAndMarkModUnion
void MarkSweep::UpdateAndMarkModUnion() {
    for (const auto&space : immune_spaces_.GetSpaces()) {
        .......
        /*space要么是ImageSpace,要么是ZygoteSpace。如果它们关联了一个ModUnionTable
          对象,则通过ModUnionTable的UpdateAndMarkReference函数来处理。否则通过它们的
          live_bitmap_来处理。其中:
          UpdateAndMarkReference的参数是一个MarkObjectVisitor类型的函数调用对象,MarkSweep
          类实现了它的MarkObject和MarkHeapReference接口函数。
          而live_bimap_ VisitMarkedRange函数最后一个参数为函数调用对象。最终,不管下面
          代码中的if和else哪个条件满足,MarkSweep的MarkObjectNonNull都将被调用。 */
        accounting::ModUnionTable* mod_union_table = heap_->FindModUnionTableFromSpace(space);
        if (mod_union_table != nullptr) {
            mod_union_table->UpdateAndMarkReferences(this);
        } else {
        //如果该空间没有关联ModUnionTable,则只能遍历该空间的所有存活对象了
        space->GetLiveBitmap()->VisitMarkedRange(
                    reinterpret_cast<uintptr_t>(space->Begin()),
                    reinterpret_cast<uintptr_t>(space->End()),
                    ScanObjectVisitor(this));
        }
    }
}
RecursiveMark
void MarkSweep::RecursiveMark() {
    ......
    if (kUseRecursiveMark) {//kUseRecursiveMark为编译常量,默认值为false
        ....//这部分代码中有和parallel处理有关的内容,感兴趣的读者可自行阅读
    }
    ProcessMarkStack(false);//此处传递的参数为false
}
ProcessMarkStack
void MarkSweep::ProcessMarkStack(bool paused) {
    /*ProcessMarkStack就是遍历mark_stack_中的obj对象,追踪它们的引用型参数。
      注意,追踪根对象的引用型成员变量是一个非常耗时的工作,所以可以利用多线程来处理,这就是
      parallel collection的一个体现。根据下面的if条件判断,是否使用parallel gc需要
      满足一定条件,即:
      (1) kParallelProcessMarkStack:编译常量,默认取值为true.
      (2) GetThreadCount返回值大于1。
      (3) mark_stack_所保存的Obj对象个数大于128(kMinimumParallelMarkStackSize的值)
      GetThreadCount的代码请读者自行阅读。其中会涉及kProcessStateJankPerceptible枚举
      变量。我们在10.3.2.2节中曾介绍过它。当应用处于前台时,它的进程状态会被设置为这个值,表
      示如果应用发生卡顿,用户是能感受到的。*/
    size_t thread_count = GetThreadCount(paused);//
    if (kParallelProcessMarkStack && thread_count > 1 &&
        mark_stack_->Size() >= kMinimumParallelMarkStackSize) {
            ProcessMarkStackParallel(thread_count);//后文再详细介绍这个函数
    } else {
        /*else代码块为不使用parallel collection的处理。处理方式很简单,就是遍历
          mark_stack_中的元素,调用它们的VisitReference函数。每找到一个引用型参数就调用
          MarkSweep MarkObject函数进行标记。如果是新标记的对象,就将其加入mark_stack_
          容器中。如此往复直到mark_stack_中的元素都处理完为止。  */
        static const size_t kFifoSize = 4;
        BoundedFifoPowerOfTwo<mirror::Object*, kFifoSize> prefetch_fifo;
        for (;;) {
        mirror::Object* obj = nullptr;
        if (kUseMarkStackPrefetch) {//kUseMarkStackPrefetch默认为true
            /*这段代码为一种优化实现,利用了GCC的__builtin_prefetch功能加速获取
              mark_stack_中的元素。感兴趣的读者可以自行研究它。*/
            .....
        } else {
            //如果不使用优化实现的话,遍历mark_stack_的代码逻辑就非常简单了
            if (mark_stack_->IsEmpty()) {  break;  }
            obj = mark_stack_->PopBack();
        }
        /*ScanObject将调用Object VisitReferences,所设置的函数调用对象最终会通过MarkSweep
          MarkObject函数来标记所找到的引用型成员变量。我们在13.8.3节中曾介绍过VisitReferences
          函数。注意,对Reference类型的对象有一些特殊处理。我们后文将介绍这部分内容。  */
          ScanObject(obj);
        }
    }
}

PausePhase

void MarkSweep::PausePhase() {
    Thread* self = Thread::Current();
    if (IsConcurrent()) {//①如果是CMS,则需要调用下面两个函数
        WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
        /*回顾MarkSweep RunPhases可知,在CMS情况下gc线程执行MarkingPhase的时候,mutator
          线程可同时运行。也就是说,对CMS而言,MarkingPhase标记的对象可能还不全面,所以在
          PausePhase的时候要重新做一次标记。当然,这次标记不会像MarkingPhase那样耗时,否则
          CMS就没有什么价值了。 */
        ReMarkRoots();
        RecursiveMarkDirtyObjects(true, accounting::CardTable::kCardDirty);
    }
    {
        ......
        //写锁,使用全局静态变量heap_bitmap_lock_同步对象
        WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
        /*②调用Heap SwapStack函数,内部将执行下面这条语句:
          allocation_stack_.swap(live_stack_)。它将live_stack_和allocation_stack_
          的内容进行交换。     */
        heap_->SwapStacks();
        live_stack_freeze_size_ = heap_->GetLiveStack()->Size();
        /*再次清空Thread的Allocation Stack空间。注意,我们在MarkRoots函数中也
          调用过这个函数。两次执行它的原因是因为在MarkRoots中清空之后直到代码运行到这里时,
          可能有mutator线程又重新分配和使用了Allocation Stack。*/
        RevokeAllThreadLocalAllocationStacks(self);
    }
    //③下文将简单介绍Runtime DisallowNewSystemWeaks的内容
    Runtime::Current()->DisallowNewSystemWeaks();
    //④下面这行代码和Java Reference对象的处理有关,我们后续单独介绍这部分知识
    GetHeap()->GetReferenceProcessor()->EnableSlowPath();
}

RecursiveMarkDirtyObjects

void MarkSweep::RecursiveMarkDirtyObjects(bool paused, uint8_t minimum_age) {
    /*ScanGrayObjects是一个比较复杂的函数,但理解它并不难,笔者仅介绍其功能,感兴趣的
      读者可以自行研究它的代码。
      在StickyMarkSweep MarkReachableObjects中,mark_stack_被清空。这并不是说
      StickyMarkSweep不需要它,而是StickyMarkSweep需要往mark_stack_填充自己的内
      容(MarkRoots往mark_stack_填充的对象算MarkSweep的)—该工作由下面的
      ScanGrayObjects完成。ScanGrayObjects的功能很简单:
      (1) 遍历Heap continuous_spaces_中的空间对象。每找到一个mark_bitmap_不为空指针
          的空间对象,就转到2去执行。
      (2) 调用Heap card_table_的Scan函数。找到那些card值大于或等于minimum_age的card,
          然后根据这个card再到空间对象去找到对应的mirror Object对象。注意,这些对象必须
          是在空间对象mark_bitmap_所标记过了的。
      (3) 每找到这样的一个mirror Object对象就调用MarkSweep的ScanObject以标记它的
          引用型成员变量。ScanObject内部会调用MarkSweep MarkObject进行标记处理。
      现在我们以某个空间对象A为例来说明和ScanGrayObjects有关的处理逻辑:
      (1) BindBitmaps中,A的mark_bitmap_的内容替换成了live_bitmap_。这表示
          mark_bitmap_保存了上次GC后留存的对象。
      (2) A对应的card在Heap ProcessCards中被修改为kCardDirty – 1或者0。
          值为kCardDirty – 1的card表示对应的对象的引用型成员变量被修改过。
      (3) ScanGrayObject扫描属于A的并且值为kCardDirty -1的card。然后找到这些card
          中被标记了的对象(对象是否被标记由于A的mark_bitmap_决定)。
      (4) 每找到一个这样的对象就调用MarkObject对它们的引用型成员变量进行标记。
          简单来说,ScanGrayObjects就是确定被标记过的对象中有哪些对象的引用型成员变量被
          修改过。main*/
    ScanGrayObjects(paused, minimum_age);
    //下面这个函数在14.4.3.2.2节中介绍过该函数
    ProcessMarkStack(paused);
}

runtime.cc

DisallowNewSystemWeaks

void Runtime::DisallowNewSystemWeaks() {
    //DisallocwNewSystemWeaks涉及ART虚拟机的很多个模块,比如下面的monitor_list_、
    //intern_table_、java_vm_等。出于篇幅考虑,本节仅介绍java_vm_的情况
    monitor_list_->DisallowNewMonitors();
    intern_table_->ChangeWeakRootState(gc::kWeakRootStateNoReadsOrWrites);
    //禁止JNI层创建新的WeakGlobal对象,或者解析一个WeakGlobal对象。我们简单介绍它对创建WeakGlobal型对象的影响
    java_vm_->DisallowNewWeakGlobals();
    heap_->DisallowNewAllocationRecords();
    lambda_box_table_->DisallowNewWeakBoxedLambdas();
}

void JavaVMExt::DisallowNewWeakGlobals() {
    Thread* const self = Thread::Current();
    MutexLock mu(self, weak_globals_lock_);
    //下面这个变量的数据类型为Atomic<bool>,设置其值为false
    allow_accessing_weak_globals_.StoreSequentiallyConsistent(false);
}

ReclaimPhase

图解

graph LR
SweepWalk-->|在live_bitmap中但不在mark_bitmap中,认为是垃圾对象,回调|SweepCallback-->从live_bitmap中清除
SweepCallback-->space.free释放空间
void MarkSweep::ReclaimPhase() {
    Thread* const self = Thread::Current();
    ProcessReferences(self);//①对Java Reference对象的处理,我们后续统一介绍
    //②清除系统中"Weak"型的垃圾对象。我们将介绍JNI WeakGlobal型对象的清除
    SweepSystemWeaks(self);
    Runtime* const runtime = Runtime::Current();
    runtime->AllowNewSystemWeaks();//重新允许"Weak"对象的创建和解析
    //清除不再需要的ClassLoader对象。请感兴趣的读者自行研究
    runtime->GetClassLinker()->CleanupClassLoaders();
    {
        WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
        GetHeap()->RecordFreeRevoke();
        //③下面的Sweep函数是关键,用于清理之前未被标记的对象
        Sweep(false);//注意,此处调用Sweep的参数为false
        //下面这两个函数用于处理空间对象中的位图
        SwapBitmaps();
        //UnBindBitmaps的处理需结合StickyMarkSweep来介绍
        GetHeap()->UnBindBitmaps();
        }
}

SweepSystemWeaks

void MarkSweep::SweepSystemWeaks(Thread* self) {
    ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
    /*调用Runtime SweepSystemWeaks函数,参数为一个IsMarkedVisitor类型的对象。
      根据14.3.1节的介绍可知,IsMarkedVisitor是一个虚基类,仅定义
      了一个IsMarked虚函数。GarbageCollector类继承了IsMarkedVistior类。而
      IsMarked由GarbageCollector的具体子类来实现。*/
    Runtime::Current()->SweepSystemWeaks(this);
}

inline mirror::Object* MarkSweep::IsMarked(mirror::Object* object) {
    //先看看这个object是否属于immue_spaces_空间中的对象
    if (immune_spaces_.IsInImmuneRegion(object)) {
        return object;
    }
    //current_space_bitmap_来自某个Space对象的mark_bitmap_,先检查这个object是否
    //属于该空间,然后判断它是否被标记
    if (current_space_bitmap_->HasAddress(object)) {
        return current_space_bitmap_->Test(object) ? object : nullptr;
    }
    //mark_bitmap_就是Heap mark_bitmap_的成员,它将遍历Heap的所有space对象,
    //先判断object属于哪个空间,然后检查是否被标记。
    return mark_bitmap_->Test(object) ? object : nullptr;
}
void Runtime::SweepSystemWeaks(IsMarkedVisitor* visitor) {
    GetInternTable()->SweepInternTableWeaks(visitor);
    GetMonitorList()->SweepMonitorList(visitor);
    //笔者仅介绍JNI层对WeakGlobal型对象的清除过程
    GetJavaVM()->SweepJniWeakGlobals(visitor);
    GetHeap()->SweepAllocationRecords(visitor);
    GetLambdaBoxTable()->SweepWeakBoxedLambdas(visitor);
}

java_vm_ext.cc

void JavaVMExt::SweepJniWeakGlobals(IsMarkedVisitor* visitor) {
    MutexLock mu(Thread::Current(), weak_globals_lock_);
    Runtime* const runtime = Runtime::Current();
    /*weak_globals_的类型为IndirectReferenceTable(笔者简写其为IRTable),
      在下面这段C++11的for each循环中,entry的类型为GcRoot<mirror::Object>*。
      它直接来自IRTable的成员变量table_。如果修改了entry的值,也就是修改了
      weak_globals_的内容。*/
    for (auto* entry : weak_globals_) {
    //遍历weak_globals_中的元素,元素是一个WeakGlobal型的对象
      if (!entry->IsNull()) {
      //调用GcRoot的Read函数,不使用ReadBarrier。GcRoot的Read函数其实很有讲究,
      //主要和Read Barrier的处理有关。本书所使用的例子均不使用Read barrier
      mirror::Object* obj = entry->Read<kWithoutReadBarrier>();
      /*调用IsMarkedVisitor的IsMarked函数。对MS而言,此处调用的是MarkSweep类
        的IsMarked函数,下文将看到它的代码。IsMarked返回值为一个Object对象。如果
        MarkSweep IsMarked返回为空指针,说明输入obj没有被标记—说明该obj是
        垃圾对象。 */
        mirror::Object* new_obj = visitor->IsMarked(obj);
        if (new_obj == nullptr) {
            /*new_obj为空指针,说明这个WeakGlobal型对象指向的那个对象是垃圾,将会被清除。
              这时我们需要修改WeakGlobal型对象的内容,使它指向另外一个有特殊含义的对象—
              即Runtime的sentinel_成员变量(由GetClearedJniWeakGlobal函数返回)。Runtime
              sentinel_就是一个Java Object对象,它在ClassLinker InitFromBootImage
              函数中创建。该对象本身没有什么特别之处,只不过它有特殊用途而已。*/
            new_obj = runtime->GetClearedJniWeakGlobal();
            }
            //修改WeakGloabl型对象的内容
            *entry = GcRoot<mirror::Object>(new_obj);
        }
    }
}

Sweep

void MarkSweep::Sweep(bool swap_bitmaps) {//注意,调用时swap_bitmaps为false
    ......
    {
    /*GetLiveStack返回Heap的live_stack_。14.4.4节中介绍过Heap live_stack_的内容。它
      保存了mutator线程所创建的对象。从严格意义上来说是从下面的Reset调用后到PausePhase调用
      Heap SwapStacks之前这段时间内mutator创建的对象。为什么这么说呢?原因是在于它们的使用
      步骤:
      (1) mutator只会将创建的对象存储于Heap allocation_stack_中。
      (2) Heap SwapStacks将交换Heap live_stack_和allocation_stack_的内容。此后,
          allocation_stack_容器为空容器(原因在步骤3)。
      (3) Heap MarkAllocStackAsLive后,live_stack_会被Reset,也就是容器会被清空。
          而live_stack_在第2步中会和allocation_stack_交换,所以交换后,
          allocation_stack_就是空容器了。
      简单来说,live_stack_中的对象属于集合Live。但是,请读者注意,live_stack_只是集合
      Live的一部分。因为它只保存了两次GC间创建的对象。*/
      accounting::ObjectStack* live_stack = heap_->GetLiveStack();
      /*调用Heap MarkAllocStackAsLive对live_stack中的元素进行处理。
      (1) 这些元素就是一个个mirror Object对象,它们属于集合Live。
      (2) MarkAllocStackAsLive将找到这些对象所在的空间,然后对这些空间对象的
      live_bitmap_位图进行设置。也就是说,集合Live由空间对象的live_bitmap_表示。*/
        heap_->MarkAllocStackAsLive(live_stack);
        live_stack->Reset();//清空Heap live_stack_的内容
    }
    //遍历HeapContinuous_spaces_的成员,读者可回顾14.4.1节中的图14-6。
    for (const auto& space : GetHeap()->GetContinuousSpaces()) {
        /*结合图14-6以及13.1节的内容可知,只有
          "main rosalloc space"和"zygote / non moving space"这两个空间为
          ContinuousMemMapAllocSpace。而".../boot.art"对应的ImageSpace属于
          ContinuousSpace。 */
        if (space->IsContinuousMemMapAllocSpace()) {
            space::ContinuousMemMapAllocSpace* alloc_space = space->AsContinuousMemMapAllocSpace();
            ......
            //调用ContinuousMemMapAllocSpace的Sweep函数,swap_bitmaps值为false
            RecordFree(alloc_space->Sweep(swap_bitmaps));
        }
    }
    //回收DiscontinuousSpace对象中的垃圾,请读者自行阅读这部分代码
    SweepLargeObjects(swap_bitmaps)
}
ContinuousMemMapAllocSpace::Sweep
collector::ObjectBytePair ContinuousMemMapAllocSpace::Sweep(bool swap_bitmaps) {
    /*Sweep的返回值类型为ObjectBytePair,它类似std的pair类,包含两个信息,第一个信息
      是回收的垃圾对象的个数,第二个信息是回收的内存的字节数。*/

    //获取空间的live_bitmap_和mark_bitmap_成员,它们分别代表集合Live和集合Mark
    accounting::ContinuousSpaceBitmap* live_bitmap = GetLiveBitmap();
    accounting::ContinuousSpaceBitmap* mark_bitmap = GetMarkBitmap();
    //如果live_bitmap和mark_bitmap是同一个对象,则不需要清除
    if (live_bitmap == mark_bitmap) {
        return collector::ObjectBytePair(0, 0);
    }
    SweepCallbackContext scc(swap_bitmaps, this);
        //交换live_bitmap和mark_bitmap的值。本次调用if的条件不满足
        if (swap_bitmaps) {
            std::swap(live_bitmap, mark_bitmap);
    }
    /*调用ContinuousSpaceBitmap的SweepWalk函数,它将扫描从Begin()开始,到End()
      结束的这段内存空间。请读者注意SweepWalk的参数:
      live_bitmap:代表集合Live。
      mark_bitmap:代表集合Mark。
      SweepWalk判断一个对象是否为垃圾对象的条件很简单。假设某个对象在两个位图中的索引是i,
      那么,该对象是垃圾的条件是"live_bitmap[i] & ~mark_bitmap[i]"为true,即:
      (1) 如果live_bitmap[i]为1,说明它属于集合Live。
      (2) 如果mark_bitmap[i]为0,说明这个对象不属于集合Mark。
      当条件1和2满足时,这个对象就是垃圾对象。
      GetSweepCallback由子类实现,返回一个处理垃圾对象回调函数。SweepWalk每找到一个垃圾对象
      都会调用这个回调函数进行处理。*/
    accounting::ContinuousSpaceBitmap::SweepWalk(
        *live_bitmap, *mark_bitmap, reinterpret_cast<uintptr_t>(Begin()),
        reinterpret_cast<uintptr_t>(End()), GetSweepCallback(),
        reinterpret_cast<void*>(&scc));
    return scc.freed;
}
MallocSpace::SweepCallback
void MallocSpace::SweepCallback(size_t num_ptrs, mirror::Object** ptrs,
            void* arg) {
    /*ContinuousSpaceBitmap SweepWalk找到垃圾对象后就会回调SweepCallback。
      参数中的num_ptrs代表垃圾对象的个数,而**ptrs代表一个垃圾对象数组的起始地址。*/
    SweepCallbackContext* context = static_cast<SweepCallbackContext*>(arg);
    space::MallocSpace* space = context->space->AsMallocSpace();
    Thread* self = context->self;
    //回调时传入的信息,swap_bitmaps为false
    if (!context->swap_bitmaps) {
        accounting::ContinuousSpaceBitmap* bitmap = space->GetLiveBitmap();
        //既然是垃圾对象,则需要将其从live_bitmap_中去除
        for (size_t i = 0; i < num_ptrs; ++i) {
            bitmap->Clear(ptrs[i]);
        }
    }
    context->freed.objects += num_ptrs;
    //RosAlloc和DlMallocSpace均实现了FreeList函数,用于释放一组对象的内存
    context->freed.bytes += space->FreeList(self, num_ptrs, ptrs);
}

SwapBitmaps

/*SwapBitmaps的作用其实很简单,就是交换集合Live和集合Mark在相关数据结构中对应的成员变量。我们以集合Live和集合Mark为目标来看待交换后的结果。
集合Live包含了此次GC中搜索到的对象。显然,它们构成了集合Live第二部分的内容——即上一次GC后剩下的对象。注意,本次GC的剩余对象将作为下一次GC中集合Live的内容。
集合Mark包含的信息是原集合Live去掉本次GC中的垃圾对象后的结果。*/
void GarbageCollector::SwapBitmaps() {
    ......
    const GcType gc_type = GetGcType();
    for (const auto& space : GetHeap()->GetContinuousSpaces()) {
        /*回顾13.7.1节的内容可知,ZygoteSpace的gc_retention_policy_取值为kGcRetention-
          PolicyFullCollect,而BumpPointerSpace、RegionSpace、DlMallocSpace、
          RosAllocSpace的gc_retention_policy_取值为kGcRetentionPolicyAlwaysCollect,
          ImageSpace的gc_retention_policy_取值为kGcRetentionPolicyNeverCollect。
          下面这个if条件中包含两个判断,其中的第二个判断说明只在MarkSweep的时候才处理ZygoteSpace
          空间。而PartialMarkSweep以及StickMarkSweep均不需要处理它。
          这也符合kGcTypeFull等回收策略的要求。  */
        if( space->GetGcRetentionPolicy() ==
                    space::kGcRetentionPolicyAlwaysCollect
            || (gc_type == kGcTypeFull && space->GetGcRetentionPolicy() ==
                space::kGcRetentionPolicyFullCollect)) {
        accounting::ContinuousSpaceBitmap* live_bitmap = space->GetLiveBitmap();
        accounting::ContinuousSpaceBitmap* mark_bitmap = space->GetMarkBitmap();
        if (live_bitmap != nullptr && live_bitmap != mark_bitmap) {
         /*更新Heap live_bitmap_和mark_bitmap_数组中的元素,ReplaceBitmap第一个
              参数为旧值,第二个参数为新值。其内部将先找到旧值所在的数组索引,然后将新值存储
              到该索引位置上。下面这两行代码就是交换Heap live_bitmap_和mark_bitmap_
              对应元素的信息。 */
            heap_->GetLiveBitmap()->ReplaceBitmap(live_bitmap, mark_bitmap);
                heap_->GetMarkBitmap()->ReplaceBitmap(mark_bitmap, live_bitmap);
                //交换space中live_bitmap_和mark_bitmap_。
                space->AsContinuousMemMapAllocSpace()->SwapBitmaps();
            }
        }
    }
    ......//对大内存对象的处理,和上面类似
}

Heap::UnBindBitmaps

void Heap::UnBindBitmaps() {
    ......
    for (const auto& space : GetContinuousSpaces()) {
        if (space->IsContinuousMemMapAllocSpace()) {
            space::ContinuousMemMapAllocSpace* alloc_space =
                                    space->AsContinuousMemMapAllocSpace();
            //temp_bitmap_不为空,说明之前曾经调用过BindLiveToMarkBitmap
            if (alloc_space->HasBoundBitmaps())
                alloc_space->UnBindBitmaps();
        }
    }
}

space.cc

void ContinuousMemMapAllocSpace::UnBindBitmaps() {
    //temp_bitmap_保存了原mark_bitmap_的内容,而mark_bitmap_保存了原live_bitmap_的内容
    accounting::ContinuousSpaceBitmap* new_bitmap = temp_bitmap_.release();
    //恢复Heap mark_bitmap_对应索引的内容
    Runtime::Current()->GetHeap()->GetMarkBitmap()->ReplaceBitmap(
                            mark_bitmap_.get(), new_bitmap);
    //恢复mark_bitmap_的内容
    mark_bitmap_.reset(new_bitmap);
}

FinishPhase

void MarkSweep::FinishPhase() {
    ......
    mark_stack_->Reset();//清空MarkSweep mark_stack_的内容
    Thread* const self = Thread::Current();
    ReaderMutexLock mu(self, *Locks::mutator_lock_);
    WriterMutexLock mu2(self, *Locks::heap_bitmap_lock_);
    //清空空间对象mark_bitmap_,也就是GC结束后,集合Mark将被清空
    heap_->ClearMarkedObjects();
}

partial_mark_sweep

PartialMarkSweep

class PartialMarkSweep : public MarkSweep {
    public:
        virtual GcType GetGcType() const OVERRIDE {
            return kGcTypePartial; //回收策略
        }
        ......
    protected:
        virtual void BindBitmaps() OVERRIDE;
        ......
};

BindBitmaps

void PartialMarkSweep::BindBitmaps() {
    //调用父类的BindBitmaps,根据14.4.3.1节的介绍可知,ImageSpace将
    //加入immune_spaces_
    MarkSweep::BindBitmaps();

    WriterMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_);
    for (const auto& space : GetHeap()->GetContinuousSpaces()) {
        //根据13.1节的内容可知,只有ZygoteSpace空间的回收策略是
        //kGcRetentionPolicyFullCollect。所以,下面这几行代码就是将ZygoteSpace加入
        //immune_spaces_
        if (space->GetGcRetentionPolicy() == space::kGcRetentionPolicyFullCollect) {
            immune_spaces_.AddSpace(space);
        }
    }
}

sticky_mark_sweep

StickyMarkSweep

class StickyMarkSweep FINAL : public PartialMarkSweep {
    //StickyMarkSweep派生自PartialMarkSweep
    public:
        GcType GetGcType() const OVERRIDE {
            return kGcTypeSticky;
        }
        ....
    protected:
        void BindBitmaps() OVERRIDE;
        void MarkReachableObjects()  OVERRIDE ;
        void Sweep(bool swap_bitmaps) OVERRIDE;
        ......
};

BindBitmaps

void StickyMarkSweep::BindBitmaps() {
    //StickyMarkSweep不处理ImageSpace和ZygoteSpace
    PartialMarkSweep::BindBitmaps();
    WriterMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_);
    for (const auto& space : GetHeap()->GetContinuousSpaces()) {
        if (space->IsContinuousMemMapAllocSpace() &&
            space->GetGcRetentionPolicy() ==  space::kGcRetentionPolicyAlwaysCollect) {
            //调用ContinuousMemMapAllocSpace的BindLiveToMarkBitmap函数,见下文解释
            space->AsContinuousMemMapAllocSpace()->BindLiveToMarkBitmap();
        }
    }
    //处理DiscontinuousSpace的情况,请读者自行阅读
    ......
}

ContinuousMemMapAllocSpace::BindLiveToMarkBitmap

void ContinuousMemMapAllocSpace::BindLiveToMarkBitmap() {
    accounting::ContinuousSpaceBitmap* live_bitmap = GetLiveBitmap();
    if (live_bitmap != mark_bitmap_.get()) {
        accounting::ContinuousSpaceBitmap* mark_bitmap = mark_bitmap_.release();
        /*下面这行代码的意思是更新Heap mark_bitmap_中原mark_bitmap所在的元素。
          更新前,该元素的旧值为mark_bitmap,更新后该元素的新增为live_bitmap。
          要理解这行代码的含义,需要读者明白两点:
          (1) 根据上文对MarkSweep GC代码逻辑的介绍可知,空间对象的live_bitmap_就是本次
              GC的集合Live。
          (2) Heap mark_bitmap_为集合Mark。调用BindBitmaps的时候,标记工作还未开展,
              所以集合Mark为空(集合Mark在上次GC的FinishPhase中被清空)。
            结合1和2,对StickyMarkSweep来说,标记还没有开始做(BindBitmaps函数为GC的
            准备工作),我们就已经把上次GC的幸存对象“标记”好了。所以,上次GC的幸存对象在本
            次GC中将被保留。*/
        Runtime::Current()->GetHeap()->GetMarkBitmap()->ReplaceBitmap(mark_bitmap, live_bitmap);
        //mark_bitmap的值保存到temp_bitmap_中
        temp_bitmap_.reset(mark_bitmap);
        //原live_bitmap的信息保存到mark_bitmap_中
        mark_bitmap_.reset(live_bitmap);
    }
}

MarkReachableObjects

void StickyMarkSweep::MarkReachableObjects() {
    //mark_stack_被清空,这表示在MarkRoots中做过标记的对象不再需要。但集合Mark的
    //信息却留了下来
    mark_stack_->Reset();
    //注意下面这个函数最后一个参数的取值为kCardDirty – 1
    RecursiveMarkDirtyObjects(false, accounting::CardTable::kCardDirty - 1);
}

Sweep

void StickyMarkSweep::Sweep(bool swap_bitmaps ATTRIBUTE_UNUSED) {
    /*SweepArray的第一个参数为Heap live_stack_。live_stack_包含了两次GC间所创建的
      对象。它就是StickyMarkSweep中的集合Live。 */
    SweepArray(GetHeap()->GetLiveStack(), false);
}

SweepArray

void MarkSweep::SweepArray(accounting::ObjectStack* allocations, bool swap_bitmaps) {
    Thread* self = Thread::Current();
    /*sweep_array_free_buffer_mem_map_是MarkSweep的成员变量,在构造函数中创建
      读者将它看作一块内存即可。下面这行代码将这块内存转成数组变量以方便后续代码的使用。
      数据变量名为chunk_free_buffer,数组元素的类型为Object*。 */
    mirror::Object** chunk_free_buffer = reinterpret_cast<mirror::Object**>(
        sweep_array_free_buffer_mem_map_->BaseBegin());
    size_t chunk_free_pos = 0;
    ......
    /*allocations为输入参数,指向Heap live_stack_,读者将live_stack_看成一个数组
      容器即可。下面的变量中,objects为这个数组的起始元素,count为数组的元素个数。 */
    StackReference<mirror::Object>* objects = allocations->Begin();
    size_t count = allocations->Size();

    /*sweep_spaces是一个数组,用于保存此次GC所要扫描的空间对象。请读者注意,这段
      代码中包含一个优化处理。根据注释可知,Heapnon_moving_space_中不太可能出现很多垃
      圾对象,所以代码将把non_moving_space_放到sweep_spaces数组的最后。*/
    std::vector<space::ContinuousSpace*>sweep_spaces;
    space::ContinuousSpace* non_moving_space = nullptr;
    for (space::ContinuousSpace* space : heap_->GetContinuousSpaces()) {
        if (space->IsAllocSpace() &&!immune_spaces_.ContainsSpace(space)&&
            space->GetLiveBitmap() != nullptr) {
            if (space == heap_->GetNonMovingSpace()) {
                //如果是Heap non_moving_space_,则先不加到sweep_spaces数组中
                non_moving_space = space;
            } else {
                sweep_spaces.push_back(space);//将space保存到数组中
            }
        }
    }
    //如果存在non_moving_space,则将其加到数组的最后
    if (non_moving_space != nullptr) {
        sweep_spaces.push_back(non_moving_space);
    }
    //接下来开始处理垃圾对象,逐个空间处理
    for (space::ContinuousSpace* space : sweep_spaces) {
        //space和alloc_space指向的是同一个空间对象。只不过后续需要调用AllocSpace的
        //FreeList函数释放内存,所以这里会先定义一个alloc_space变量
        space::AllocSpace* alloc_space = space->AsAllocSpace();
        accounting::ContinuousSpaceBitmap* live_bitmap = space->GetLiveBitmap();
        accounting::ContinuousSpaceBitmap* mark_bitmap = space->GetMarkBitmap();
        ......
        //objects为Heap live_stack_容器的起始元素,count为容器的元素个数,main
        StackReference<mirror::Object>* out = objects;
        for (size_t i = 0; i <count; ++i) {
            mirror::Object* const obj = objects[i].AsMirrorPtr();
            //kUseThreadLocalAllocationStack为编译常量,默认为true
            if (kUseThreadLocalAllocationStack&& obj == nullptr) {
                continue;
            }
            //先判断space是否包含obj
            if (space->HasAddress(obj)) {
                //空间对象的mark_bitmap没有设置obj,所以obj是垃圾对象,main
                if (!mark_bitmap->Test(obj)) {
                    /*kSweepArrayChunkFreeSize的值为0。我们找到一个垃圾对象后并不是马上就
                      清理它,而是先存起来,等攒到一定数量后再一起清理。所以,下面这段代
                      码的含义就很好理解了。kSweepArrayChunkFreeSize值为1024。  */
                    if (chunk_free_pos >= kSweepArrayChunkFreeSize) {
                        freed.objects += chunk_free_pos;
                        //释放一组垃圾对象的内存,main
                        freed.bytes += alloc_space->FreeList(self, chunk_free_pos,
                                                    chunk_free_buffer);
                        chunk_free_pos = 0;
                    }
                    //如果个数还未超过1024,先存起来
                    chunk_free_buffer[chunk_free_pos++] = obj;
                }
            } else {//对应!mark_bitmap->Test(obj)为false的时候,即obj不是垃圾对象
                /*obj不是垃圾对象的话,则把obj存到Heap live_stack_新的位置上。随着垃圾对象
                  被清除,非垃圾对象将向前移动以填补垃圾对象所占据的位置,这样可减少后续其他空间
                  对象处理的工作量。当然,live_stack_的元素个数也需要相应调整。main*/
                (out++)->Assign(obj);
            }
        }
        ......
        count = out - objects;//调整live_stack_的元素个数
    }
    ......//对Discontinuousspaces的处理
    {
        ......
        allocations->Reset();//清空Heap live_stack_的内容
    }
    sweep_array_free_buffer_mem_map_->MadviseDontNeedAndZero();
}

其他

mark_sweep.h/cc

GetCollectorType

//PartialMarkSweep和StickyMarkSweep均未重载下面这个函数
    virtual CollectorType GetCollectorType() const OVERRIDE {
        //is_concurrent_为MarkSweep的成员变量,如果为true,则返回kCollectorTypeCMS
        return is_concurrent_ ? kCollectorTypeCMS : kCollectorTypeMS;
}

GetGcType

virtual GcType GetGcType() const OVERRIDE {
    return kGcTypeFull;//MarkSweep支持最强力度的GC策略
}