GC

类设计

image-20210214112301527

runtime.cc

Runtime::VisitRoots

void Runtime::VisitRoots(RootVisitor* visitor, VisitRootFlags flags) {
    /*RootVisitor是一个纯虚类,其定义了几个函数,供root访问时调用。参数flags有一个默认
      值,为kVisitRootFlagAllRoots,表示要访问所有的root。*/
    VisitNonConcurrentRoots(visitor);
    VisitConcurrentRoots(visitor, flags);
}

Runtime::VisitNonConcurrentRoots

void Runtime::VisitNonConcurrentRoots(RootVisitor* visitor) {
    //1:调用所有Thread对象的VisitRoots函数
    thread_list_->VisitRoots(visitor);
    VisitNonThreadRoots(visitor);//接着看该函数的代码
}

Thread::VisitRoots

void Thread::VisitRoots(RootVisitor* visitor) {
    /*GetThreadId返回的是Thread tlsPtr_ thin_lock_thread_id thin_lock_id。
      我们在12.2.1节中介绍过它。该id并不是代表操作系统里线程的tid,而是由虚拟机自己维护的用
      于线程同步的id。*/
    const uint32_t thread_id = GetThreadId();
    //tlsPtr_opeer指向一个Java层Thread对象,它是一个mirror Thread对象在Java层
    //的对应物。这类根对象的类型为kRootThreadObject
    visitor->VisitRootIfNonNull(&tlsPtr_.opeer, RootInfo(kRootThreadObject, thread_id));

    /*tlsPtr_ exception指向一个Java异常对象。注意,GetDeoptimizationException返
      回的值非常特殊(为-1)。所以,它并不是一个真正的Java异常对象,只是用-1来表示和
      HDeoptimize有关的处理(详情可参考10.4节的内容) */
    if (tlsPtr_.exception != nullptr && tlsPtr_.exception != GetDeoptimizationException()) {
        //使用kRootNativeStack作为tlsPtr_ exception的root类型
        visitor->VisitRoot(reinterpret_cast<mirror::Object**>(
                            &tlsPtr_.exception), RootInfo(kRootNativeStack, thread_id));
    }
    //tlsPtr_ monitor_enter_object指向用于monitor-enter的那个Java对象。详情可参考
    //12.3.2.1.1节的内容
    visitor->VisitRootIfNonNull(&tlsPtr_.monitor_enter_object,RootInfo(kRootNativeStack, thread_id));
  
    /*tlsPtr_ jni_env locals的类型为IndirectReferenceTable(简写为IRTable),
      而tlsPtr_ jni_env monitors与synchronized修饰的java native函数的调用有关,
      用于同步native函数的调用。本书关于JNI的部分中并未对synchronized修饰的native
      函数做过讲解,读者可结合第11章的内容自行研究它。*/
    tlsPtr_.jni_env->locals.VisitRoots(visitor, RootInfo(kRootJNILocal,thread_id));
    tlsPtr_.jni_env->monitors.VisitRoots(visitor, RootInfo(kRootJNIMonitor, thread_id));
    
    /*HandleScopeVisitRoots也和JNI有关,读者可回顾9.5.3节的内容。调用jni函数时,引用型参
      数会借助一个HandleScope保存在栈上。而HandleScopeVisitRoots函数将遍历tlsPtr_top_
      handle_scope链表,然后访问其中的引用型对象。简单点说,下面这个函数将找到那些传递
      给了native函数的引用型对象。  */
    HandleScopeVisitRoots(visitor, thread_id);

    .....//其他一些情况下root Object的遍历。与之相关的内容建议读者在本书基础上自行研究

    /*下面来看最关键的一个知识。我们先举个例子,假设有这样一段代码,funcA函数中创建一个
      Object对象obj,然后用它作为参数调用funcB:
      void funcA(){
      Object obj= new Object();//创建一个对象
      funcB(obj);//如果屏蔽这行代码,那么obj就是垃圾对象
    }
    在上述代码中,如果没有funcB调用的那行代码,obj就是一个没有人用的垃圾对象,否则,我们就需
    要特殊考虑。因为对funcB调用而言,obj被用到了。但这种被用的方式显然和对象的某个引用型成员
    变量的引用方式不同,它是通过作为函数调用的引用型参数来引用的。从某种意义上说,它和JNI HandleScope
    里的引用型参数一样。对于这种和函数调用有关的对象,就需要遍历线程的调用栈帧,找到其中所有引
    用型的参数,把它们视为根对象。下面几行代码就是干这个工作的,我们重点介绍它们。 */
    Context* context = GetLongJumpContext();
    RootCallbackVisitor visitor_to_callback(visitor, thread_id);
    ReferenceMapVisitor<RootCallbackVisitor> mapper(this, context,visitor_to_callback);
    //ReferenceMapVisitor派生自StackVisitor类。10.2.4节曾详细介绍过StackVisitor。
    mapper.WalkStack();
    ReleaseLongJumpContext(context);
    ......
}

Runtime::VisitNonThreadRoots

void Runtime::VisitNonThreadRoots(RootVisitor* visitor) {
    //java_vm_类型为JavaVmExt,2:调用它的VisitRoots函数
    java_vm_->VisitRoots(visitor);
    /*3: sentinel_是Runtime的成员变量,类型为GcRoot<Object>,它对应一个Java层的java.lang.
      Object对象。其作用我们后续碰到时再介绍。  */
    sentinel_.VisitRootIfNonNull(visitor, RootInfo(kRootVMInternal));
    /*:3: preallocated_OutOfMemoryError_以及pre_allocated_NoClassDefFoundError_是Runtime
      的成员变量,类型为GcRoot<Throwable>。它们属于由虚拟机直接创建的JavaObject对象。创建
      它们的代码可参考7.2.2节所示Runtime Init函数的最后几行。  */
    pre_allocated_OutOfMemoryError_.VisitRootIfNonNull(visitor, RootInfo(kRootVMInternal));
    pre_allocated_NoClassDefFoundError_.VisitRootIfNonNull(visitor,RootInfo(kRootVMInternal));
    //4:  调用RegTypeCache的VisitStaticRoots函数
    verifier::MethodVerifier::VisitStaticRoots(visitor);

    //下面这个函数的内容和dex2oat的编译流程有关,我们不拟介绍它
    VisitTransactionRoots(visitor);
}

Runtime::VisitConcurrentRoots

void Runtime::VisitConcurrentRoots(RootVisitor* visitor,
        VisitRootFlags flags) {
    //5: intern_table_的类型为InternTable,和Intern String有关
    intern_table_->VisitRoots(visitor, flags);
    //6: 调用ClassLinker的VisitRoots函数
    class_linker_->VisitRoots(visitor, flags);
    ....
    if ((flags & kVisitRootFlagNewRoots) == 0) {
        VisitConstantRoots(visitor);//7
    }
    Dbg::VisitRoots(visitor);//和调试有关,本书不拟介绍它
}

heap.cc

Heap初始化时对Collector的设置

Heap::Heap(...
            CollectorType foreground_collector_type,
            CollectorType background_collector_type,
            ...)
    : ...
    foreground_collector_type_(foreground_collector_type),
    background_collector_type_(background_collector_type),
    desired_collector_type_(foreground_collector_type_),
    ...{
    //设置回收器类型和回收策略,详情见下文代码分析
    ChangeCollector(desired_collector_type_);
    //创建Space对象等工作,比较复杂,这也是Heap难度较大的原因之一。Android后续版本
    //对此处的代码逻辑做了一些优化和调整
    ......
    /*创建回收器。garbage_collectors_是一个数组,元素类型为GarbageCollector*。
      下面的MayUseCollector函数将检查前台回收器类型(foreground_collector_type_)或后台
      回收器类型(background_collector_type_)是否为输入的回收器类型,只要有一个回收器类型
      满足条件,则MayUseCollector返回true。如果回收器类型为CMS或MS,下面这段for循环代码中
      的if代码块只会执行一次,不论哪一次执行都会创建三个垃圾回收器对象,它们分别是MarkSweep、
      PartialMarkSweep和StickyMarkSweep。CMS和MS区别之处在于这三个回收器对象是否用
      concurrent gc功能。*/
    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_) {
        //前台回收器类型为GSS时,generational才为true
        const bool generational = foreground_collector_type_ ==  kCollectorTypeGSS;
        //如果使用SS、GSSS或HSC,则再创建一个SemiSpace collector对象
        semi_space_collector_ = new collector::SemiSpace(this, generational,  generational ? "generational" : "");
        garbage_collectors_.push_back(semi_space_collector_);
        }
        ......//其他回收器类型的处理,读者可自行阅读
    }
    ......
}
void Heap::ChangeCollector(CollectorType collector_type) {
    if (collector_type != collector_type_) {
    ......
    //collector_tyoe_和gc_plan_均为Heap成员变量
    collector_type_ = collector_type;//设置回收器类型
    gc_plan_.clear();
    switch (collector_type_) {
        ......
        case kCollectorTypeMC:  // Fall-through.
        case kCollectorTypeSS:  // Fall-through.
        case kCollectorTypeGSS: {
            //gc_plan_为数组,保存了回收策略。ART在GC时将用到它
            gc_plan_.push_back(collector::kGcTypeFull);
            ......//设置内存分配器的类型为kAllocatorTypeBumpPointer
            break;
        }
        ......
        case kCollectorTypeCMS: {
            gc_plan_.push_back(collector::kGcTypeSticky);
            gc_plan_.push_back(collector::kGcTypePartial);
            gc_plan_.push_back(collector::kGcTypeFull);
            .....//设置内存分配器的类型为kAllocatorTypeRosAlloc
            break;
        }
        ......
    }
    // IsGcConcurrent判断collector_type_是否为CMS或CC(kCollectorTypeCC,意为Concurrent Copying)
    if (IsGcConcurrent()) {
        //concurrent_start_bytes_和concurrent gc有关。其用途我们后续代码分析时候
        //将看到。kMinConcurrentRemainingBytes取值为128KB
        concurrent_start_bytes_ =
            std::max(max_allowed_footprint_, kMinConcurrentRemainingBytes)   kMinConcurrentRemainingBytes;
        } else {
            concurrent_start_bytes_ = std::numeric_limits<size_t>::max();
        }
    }
}

garbage_collector.cc

GarbageCollector::Run

void GarbageCollector::Run(GcCause gc_cause, bool clear_soft_references) {
    //GcCause为枚举变量,表示触发本次gc的原因。后文介绍相关代码时将了解到不同的Gc原因
    .....
    Thread* self = Thread::Current();
    uint64_t start_time = NanoTime();//本次GC的GC开始时间
    /*GetCurrentIteration返回Heap current_gc_iteration_成员变量。由上文所述可知,
      它用于统计GC的执行效果。Iteration Reset将重新设置相关的统计参数。*/
    Iteration* current_iteration = GetCurrentIteration();
    current_iteration->Reset(gc_cause, clear_soft_references);
    RunPhases();  // RunPhase由GarbageCollector子类实现,它将完成真正的GC工作,main
    //RunPhases之后,本次GC也就算执行完了。下面的代码用于统计此次GC的执行效果
    cumulative_timings_.AddLogger(*GetTimings());
    /*total_freed_objects_和total_freed_bytes_GarbageCollector的成员变量,代表虚拟机
      从运行开始所有GC操作释放的对象总个数以及内存大小总数。Iteration的GetFreedObjects和
      GetFreedLargeObjects、GetFreedBytes和GetFreedLargeObjectBytes返回一次GC
      (也就是调用每次调用Run函数)所释放的对象个数以及内存大小(包括非大内存对象以及大内存对
      象)。   */
    total_freed_objects_ += current_iteration->GetFreedObjects() +
                            current_iteration->GetFreedLargeObjects();
    total_freed_bytes_ += current_iteration->GetFreedBytes() +
            _iteration->GetFreedLargeObjectBytes();

    uint64_t end_time = NanoTime(); //本次GC的结束时间
    //设置本次GC的耗时时间
    current_iteration->SetDurationNs(end_time - start_time);
    //更新暂停时间以及总的GC运行时间等统计信息。这里省略部分代码,建议读者学习完本章后,再
    //来看它。
    .....
    total_time_ns_ += current_iteration->GetDurationNs();
    ......
}

其他:

gc_root.h

Root

enum RootType

enum RootType {
    kRootUnknown = 0,
    kRootJNIGlobal,kRootJNILocal,
    kRootJavaFrame,  kRootNativeStack,
    kRootStickyClass,  kRootThreadBlock,  kRootMonitorUsed,
    kRootThreadObject, kRootInternedString,

    //下面三种root类型和HPROF(A Heap/CPU Profiling Tool,性能调优工具)以及调试有关,
    //本书不拟介绍它们
    kRootFinalizing, kRootDebugger,kRootReferenceCleanup,

    //最后两种root的类型
    kRootVMInternal,
    kRootJNIMonitor,
};

RootInfo

//RootInfo用于描述一个root的信息。具体而言,root信息包括该root的类型以及它所在的
//线程id。
class RootInfo {
    public:
    //由于不是所有root信息都和线程有关系,所有下面这个构造函数中,thread_id默认值为0
    explicit RootInfo(RootType type, uint32_t thread_id = 0)
        : type_(type), thread_id_(thread_id) {
    }
    ....
    private:
        const RootType type_;//该root的类型
        const uint32_t thread_id_;//该root所在的线程
};

GcRootSource

class GcRootSource {//它仅包含两个成员变量。
    .....
private:
    ArtField* const field_;
    ArtMethod* const method_;
};

GcRoot

template<class MirrorType>
class GcRoot {      //一个GcRoot实例就代表一个被认为是根的Object对象
    private:
        /*GcRoot只有下面一个成员变量,其类型为CompressedReference。CompressedReference  中只有一个reference_(类型为uint32_t)成员。这个成员也就是某个Object对象的内存 地址。所以,简单来说,root_也就是代表某个Object对象。*/
        mutable mirror::CompressedReference<mirror::Object>root_;
    public:
        /*GcRoot提供了几个成员函数用于很方便地访问root_。如上文所述,一个GcRoot对象代表一个
          被认为是根的Object对象(以后我们称之为root Object或根Object)。所以,下面的几个
          root访问函数其实访问的就是root_的一个对象。*/
    void VisitRoot(RootVisitor* visitor, const RootInfo& info) const{
        mirror::CompressedReference<mirror::Object>* roots[1] = { &root_ };
        visitor->VisitRoots(roots, 1u, info);
    }
    void VisitRootIfNonNull(RootVisitor* visitor,
                            const RootInfo& info) const   {
        if (!IsNull()) {//如果root_不为空指针,则访问它
            VisitRoot(visitor, info);
        }
    }
    bool IsNull() const { return root_.IsNull(); }
    .....
};

RootVisitor

class RootVisitor {
    public:
    virtual ~RootVisitor() { }
    //下面两个VisitRoots为虚函数,由RootVisitor的子类实现。它们用于访问一组root Object对象
    virtual void VisitRoots(mirror::Object*** roots, size_t count,
                const RootInfo& info) = 0;
    virtual void VisitRoots(mirror::CompressedReference<mirror::Object>** roots,
        size_t count, const RootInfo& info) = 0;

    //下面两个函数为辅助函数,用于访问单个root Object对象
    void VisitRoot(mirror::Object** root, const RootInfo& info) {
        VisitRoots(&root, 1, info);
    }
    void VisitRootIfNonNull(mirror::Object** root, const RootInfo& info) {
        if (*root != nullptr) {
            VisitRoot(root, info);
        }
    }
    ......
};

BufferedRootVisitor

template <size_t kBufferSize>
class BufferedRootVisitor {
    private:
        RootVisitor* const visitor_;
        //roots_数组,数组最大容量由模板参数kBufferSize决定。该数组中的root Object对应
        //同一种RootType(由root_info_的type_表示)
        mirror::CompressedReference<mirror::Object>* roots_[kBufferSize];
        RootInfo root_info_;
        size_t buffer_pos_;//roots_数组中元素的个数
    public:
    template <class MirrorType>
    void VisitRoot(mirror::CompressedReference<MirrorType>* root){
        if (UNLIKELY(buffer_pos_ >= kBufferSize)) {
            Flush();//如果roots_数组已满,则调用Flush
        }
        //如果roots_数组还没有填满,则仅仅是把root存到roots_数组中
        roots_[buffer_pos_++] = root;
    }

    void Flush() {
        //一次性访问roots_数组中的root Object内容
        visitor_->VisitRoots(roots_, buffer_pos_, root_info_);
        buffer_pos_ = 0;
    }
    //其他访问函数
    template <class MirrorType>
    void VisitRootIfNonNull(GcRoot<MirrorType>& root) {
        if (!root.IsNull()) { VisitRoot(root); }
    }
    template <class MirrorType>
    void VisitRootIfNonNull(mirror::CompressedReference<MirrorType>* root) {
        if (!root->IsNull()) { VisitRoot(root); }
    }
    ....
};

collector_type.h

enum CollectorType

enum CollectorType {
    kCollectorTypeNone,
    //下面两个枚举值和MarkSweep类有关。详情见本章对应小节的分析
    kCollectorTypeMS,kCollectorTypeCMS,
    //下面两个枚举值和SemiSpace类有关
    kCollectorTypeSS,kCollectorTypeGSS,
    //和MarkCompact类有关
    kCollectorTypeMC,
    //和GarbageCollector类家族无关,其作用见后续代码分析
    kCollectorTypeHeapTrim,
    //和ConcurrentCopying类有关
    kCollectorTypeCC,
    kCollectorTypeInstrumentation,
    //和GarbageCollector类家族无关,其作用见后续代码分析
    kCollectorTypeAddRemoveAppImageSpace,
    //和CMS有关。详情见后续代码分析
    kCollectorTypeHomogeneousSpaceCompact,
    //和GarbageCollector类家族无关,其作用见后续代码分析
    kCollectorTypeClassLinker,
};

gc_type.h

enum GcType

//从某种意义上来说,GcType反应的是回收工作的力度。枚举值越大,力度越高,工作也越“辛苦”
enum GcType {
    kGcTypeNone,
    //表示仅扫描和回收上次GC到本次GC这个时间段内所创建的对象
    kGcTypeSticky,
    /*仅扫描和回收应用进程自己的堆,不处理zygote的堆。这种方式和Android中Java应用程序的创建
      方式有关。在Android中,应用进程是zygote进程fork出来的。*/
    kGcTypePartial,
    //力度最大的一种回收策略,扫描APP自己以及它从父进程zygote继承得到的堆
    kGcTypeFull,
    kGcTypeMax,
};

Mutator

the program that modifies the objects in heap (simply, the user program)

mutator和collector:我们在第13章中曾提到过它们。这两个词是由已故世界级计算机科学先驱Edsger W.Dijkstra于1976年左右提出的。简单来说,collector表示内存回收相关的功能模块。而mutator和collector相对,一般情况下代表应用程序中除collector之外的其他部分。