virtual GcType GetGcType() const OVERRIDE {
//ConcurrentCopying仅支持kGcTypePartial,也就是不扫描ImageSpace和
//ZygoteSpace(除了那些有dirty card的对象)
return kGcTypePartial;
}
virtual CollectorType GetCollectorType() const OVERRIDE {
return kCollectorTypeCC;//返回回收器类型
}
void SetRegionSpace(space::RegionSpace* region_space) {
//region_space_是ConcurrentCopying的成员变量
//ConcurrentCopying要回收的垃圾对象就在这个region_space_中
region_space_ = region_space;
}
void ConcurrentCopying::RunPhases() {
is_active_ = true;
Thread* self = Thread::Current();
thread_running_gc_ = self;
{
ReaderMutexLock mu(self, *Locks::mutator_lock_);
InitializePhase();//①初始化阶段
}
FlipThreadRoots();//②完成半空间Flip工作
{
ReaderMutexLock mu(self, *Locks::mutator_lock_);
MarkingPhase();//③标记
}
......
{
ReaderMutexLock mu(self, *Locks::mutator_lock_);
ReclaimPhase();//④回收
}
FinishPhase();//收尾工作,非常简单,请读者自行阅读
is_active_ = false;
thread_running_gc_ = nullptr;
}
void ConcurrentCopying::InitializePhase() {
......
CheckEmptyMarkStack();//详情见下文代码分析
//immune_spaces_类型为ImmuneSpace,保存了不需要GC的空间对象
immune_spaces_.Reset();
.....
/*下面的代码逻辑将设置force_evacuate_all_成员变量,它和RegionSpace有关,我们
后续用到该变量时再介绍其含义。*/
if (GetCurrentIteration()->GetGcCause() == kGcCauseExplicit ||
GetCurrentIteration()->GetGcCause() == kGcCauseForNativeAlloc ||
GetCurrentIteration()->GetClearSoftReferences()) {
force_evacuate_all_ = true;
} else {
force_evacuate_all_ = false;
}
BindBitmaps();//详解见下文代码分析
......
}
void ConcurrentCopying::CheckEmptyMarkStack() {
Thread* self = Thread::Current();
/*Thread tlsPtr_中有一个名为thread_local_mark_stack的成员变量,其定义如下:
AtomicStack<:Object>* thread_local_mark_stack;
thread_local_mark_stack是专门配合ConcurrentCopying而使用的,其数据类型就是
AtomicStack(和上文提到的Heap allocation_stack_、mark_stack_一样)
tlsPtr_ thread_local_mark_stack的具体用法我们后文碰到时再介绍。
MarkStackMode是枚举变量,其中定义了4个枚举值(它们的含义们下文碰到时再介绍):
enum MarkStackMode {
kMarkStackModeOff = 0, kMarkStackModeThreadLocal,
kMarkStackModeShared, kMarkStackModeGcExclusive
};
mark_stack_mode_是ConcurrentCopying成员变量,初始值为kMarkStackModeOff。
GC过程中将修改它。*/
MarkStackMode mark_stack_mode = mark_stack_mode_.LoadRelaxed();
//mark_stack_mode取值为kMarkStackModeThreadLocal的处理逻辑
if (mark_stack_mode == kMarkStackModeThreadLocal) {
/*RevokeThreadLocalMarkStack将要求各个Java Thread执行一个CheckPoint任务,
该任务有三个关键处理,笔者列举如下:
(1) 获取线程对象的tlsPtr_ thread_local_mark_stack对象(通过Thread
GetThreadLocalMarkStack)。该对象初值为空,ConcurrentCopying GC过程中
会设置它(详情见后文分析)。
(2) 如果线程的thread_local_mark_stack不为空,则将它保存到ConcurrentCopying
revoked_mark_stacks_(类型为vector<ObjectStack*>)成员变量中。
(3) 调用Thread SetThreadLocalMarkStack,将thread_local_mark_stack设置为空。
RevokeThreadLocalMarkStacks的调用结果就是将线程对象中不为空的
thread_local_mark_stack放到revoked_mark_stacks_数组中。 */
RevokeThreadLocalMarkStacks(false);
MutexLock mu(Thread::Current(), mark_stack_lock_);
//如果revoked_mark_stacks_不为空,则需要逐个清除其中所包含的Object对象
if (!revoked_mark_stacks_.empty()) {
for (accounting::AtomicStack<mirror::Object>* mark_stack : revoked_mark_stacks_) {
while (!mark_stack->IsEmpty()) {
mirror::Object* obj = mark_stack->PopBack();
......//打印信息
}
}
}
} else {//如果mark_stack_mode取值为其他值
MutexLock mu(Thread::Current(), mark_stack_lock_);
//gc_mark_stack_指向一个ObjectStack对象
CHECK(gc_mark_stack_->IsEmpty());
CHECK(revoked_mark_stacks_.empty());
}
}
void ConcurrentCopying::BindBitmaps() {
Thread* self = Thread::Current();
WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
for (const auto& space : heap_->GetContinuousSpaces()) {
//ConcurrentCopying只支持kGcTypePartial,所以ImageSpace、ZygoteSpace
//同样会被加到immune_spaces_中
if (space->GetGcRetentionPolicy() == space::kGcRetentionPolicyNeverCollect ||
space->GetGcRetentionPolicy() == space::kGcRetentionPolicyFullCollect) {
CHECK(space->IsZygoteSpace() || space->IsImageSpace());
immune_spaces_.AddSpace(space);
/*cc_heap_bitmap_类型为HeapBitmap,cc_bitamps_类型为
vector< SpaceBitmap<kObjectAlignment>*>。这两个成员变量由
ConcurrentCopying内部使用。*/
const char* bitmap_name = space->IsImageSpace() ? "cc image space bitmap" : "cc zygote space bitmap";
accounting::ContinuousSpaceBitmap* bitmap =
accounting::ContinuousSpaceBitmap::Create(bitmap_name,space->Begin(), space->Capacity());
cc_heap_bitmap_->AddContinuousSpaceBitmap(bitmap);
cc_bitmaps_.push_back(bitmap);
} else if (space == region_space_) {
accounting::ContinuousSpaceBitmap* bitmap =
accounting::ContinuousSpaceBitmap::Create( "cc region space bitmap",
space->Begin(), space->Capacity());
cc_heap_bitmap_->AddContinuousSpaceBitmap(bitmap);
cc_bitmaps_.push_back(bitmap);
region_space_bitmap_ = bitmap;
}
}
}
graph LR
subgraph RootObject
GC线程-->交换From和To空间
Mutator线程-->VisitRoots("thread->VisitRoots")
end
VisitRoots-->|callback root ref|Mark("mirror::Object* to_ref = Mark(ref);")
Mark-->|forwarding address|GetFwdPtr
Mark-->Copy
Mark-->PushOntoMarkStack
subgraph ObjectReferencedByRoot
ProcessMarkStack-->|遍历mark_stack中的根对象得到to_ref|VisitReferences("to_ref->VisitReferences")
end
VisitReferences-->|得到field ref|Mark("mirror::Object* to_ref = Mark(ref)得到ref的to_ref,标记,拷贝")-->updateRef
void ConcurrentCopying::FlipThreadRoots() {
......
Thread* self = Thread::Current();
Locks::mutator_lock_->AssertNotHeld(self);
gc_barrier_->Init(self, 0);
ThreadFlipVisitor thread_flip_visitor(this, heap_->use_tlab_);
FlipCallback flip_callback(this);
heap_->ThreadFlipBegin(self);
/*Runtime FlipThreadRoots将先暂停线程对象,然后设置它们的flip_function,
接着再恢复它们的运行。FlipThreadRoots前两个参数分别是两个闭包对象,其中:
(1) GC线程(也就是当前调用FlipThreadRoots的线程)先执行flip_callback。
(2) 其他所有Java线程对象再执行thread_flip_visitor。
根据ThreadList的注释,FlipThreadRoots只由ConcurrentCopying使用。 */
size_t barrier_count = Runtime::Current()->FlipThreadRoots(&thread_flip_visitor, &flip_callback, this);
heap_->ThreadFlipEnd(self);
......
is_asserting_to_space_invariant_ = true;
......
}
class FlipCallback : public Closure {
public:
......
virtual void Run(Thread* thread) OVERRIDE {
ConcurrentCopying* cc = concurrent_copying_;
......
Thread* self = Thread::Current();
......
/*调用RegionSpace的SetFromSpace。rb_table_为ReadBarrierTable,来自Heap的成员
变量rb_table_。ReadBarrieTable的启用需要设置前台回收器类型为
kCollectorTypeCC,并且定义编译宏kUseTableLookupReadBarrier。*/
cc->region_space_->SetFromSpace(cc->rb_table_,cc->force_evacuate_all_);
//内部调用HeapSwapStacks。交换Heap allocation_stack_和live_stack_
cc->SwapStacks();
......
cc->is_marking_ = true;
//设置mark_stack_mode_的值为kMarkStackModeThreadLocal
cc->mark_stack_mode_.StoreRelaxed(ConcurrentCopying::kMarkStackModeThreadLocal);
.......
}
......
};
region_space.cc
void RegionSpace::SetFromSpace(accounting::ReadBarrierTable* rb_table,
bool force_evacuate_all) {
/*回顾13.3.2节的内容可知,RegionSpace把内存资源划分成数个块,每一个块由一个Region对象
描述。num_regions_是Region的个数,而region_数组保存了各个内存块对应的Region信息。*/
......
for (size_t i = 0; i <num_regions_; ++i) {
Region* r = ®ions_[i];
/*RegionState枚举变量描述了一个Region的状态,我们重点看前两个枚举值的含义:
(1) kRegionStateFree:表示Region为空闲待使用状态
(2) kRegionStateAllocated:表示Region已经有一部分内存被分配了。
RegionType枚举变量描述了一个Region的类型,它有如下五种取值:
(1) kRegionTypeAll:代码中没有明确使用它的地方,读者可不考虑
(2) kRegionTypeFromSpace:Region位于From Space中,需要被清除(evacuate)
(3) kRegionTypeUnevacFromSpace:该Region位于From Space,但是不需要被清除
(4) kRegionTypeToSpace:Region位于To Space中。
(5) kRegionTypeNone:Region的默认类型。
如果一个Region首先被使用,其类型将从kRegionTypeNone转换为 kRegionTypeToSpace。相关代码见Region Unfree函数。 */
RegionState state = r->State();
RegionType type = r->Type();
if (!r->IsFree()) {//IsFree返回false,说明该Region已经被使用
if (LIKELY(num_expected_large_tails == 0U)) {
/*ShouldBeEvacuated用于判断一个Region是否需要被清除。Region中有两个成员变量
与之相关:
(1) is_newly_allocated_:bool型。一个Region从kRegionStateFree到kRegion-
StateAllocated时,该成员变量被设置为true(通过调用Region SetNewlyAllocated
函数来完成)。如果is_newly_allocated_为true,ShouldBeEvacuated返回也为true。
(2) live_bytes_:非垃圾对象所占内存的字节数。如果它和该Region中所分配的总内存字节数
之比小于75%(kEvaculateLivePercentThreshold),则ShouldBeEvacuated也返
回true。*/
bool should_evacuate = force_evacuate_all || r->ShouldBeEvacuated();
if (should_evacuate) {
r->SetAsFromSpace();//设置Region的类型为kRegionTypeFromSpace
} else {
//设置Region的类型为kRegionTypeUnevacFromSpace
r->SetAsUnevacFromSpace();
}
........
}.......
} else {
......
}
}
current_region_ = &full_region_;
evac_region_ = &full_region_;
}
class ThreadFlipVisitor : public Closure {
public:
......
virtual void Run(Thread* thread) OVERRIDE {
Thread* self = Thread::Current();
//设置线程对象tls32_is_gc_marking为true
thread->SetIsGcMarking(true);
if (use_tlab_ && thread->HasTlab()) {
if (ConcurrentCopying::kEnableFromSpaceAccountingCheck) {
......
} else {
//撤销RegionSpace为线程thread分配的TLAB
concurrent_copying_->region_space_->RevokeThreadLocalBuffers(thread);
}
}
if (kUseThreadLocalAllocationStack) {
//撤销线程本地Allocation Stack
thread->RevokeThreadLocalAllocationStack();
}
ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
//访问线程根对象。ConcurrentCopying的VisitRoots函数将被调用,其内部调用
//MarkRoot。我们下文将重点分析MarkRoot函数
thread->VisitRoots(concurrent_copying_);
concurrent_copying_->GetBarrier().Pass(self);
}
......
};
// Process some roots.
inline void ConcurrentCopying::VisitRoots(
mirror::Object*** roots, size_t count, const RootInfo& info ATTRIBUTE_UNUSED) {
for (size_t i = 0; i < count; ++i) {
mirror::Object** root = roots[i];
mirror::Object* ref = *root;
mirror::Object* to_ref = Mark(ref);
......
}
}
inline void ConcurrentCopying::VisitRoots(
mirror::CompressedReference<mirror::Object>** roots, size_t count,
const RootInfo& info ATTRIBUTE_UNUSED) {
for (size_t i = 0; i < count; ++i) {
mirror::CompressedReference<mirror::Object>* const root = roots[i];
if (!root->IsNull()) {
// kGrayImmuneObject is true because this is used for the thread flip.
MarkRoot</*kGrayImmuneObject*/true>(root);
}
}
}
inline void ConcurrentCopying::MarkRoot(CompressedReference<Object>* root) {
//ref是当前正在被访问的某个线程根对象
mirror::Object* const ref = root->AsMirrorPtr();
/*调用ConcurrentCopying Mark,返回一个to_ref对象。to_ref的内容和ref一样,
但它可能位于其他空间中(这就是拷贝的含义,详情见下文对Mark的分析)。
如果to_ref和ref不相同,则需要修改存储ref的内存,使得它指向新的to_ref。
具体的修改方式是先将root转换为一个Atomic<CompressedReference<Object>>*对象,
然后进行原子操作。总之,在Mark函数后,原线程根对象可能被更新为位于另外一个空间中的对象。*/
mirror::Object* to_ref = Mark(ref);
if (to_ref != ref) {
auto* addr = reinterpret_cast<Atomic<CompressedReference<Object>>*> (root);
auto expected_ref = CompressedReference<Object>::FromMirrorPtr(ref);
auto new_ref = CompressedReference<Object>::FromMirrorPtr(to_ref);
do {
if (ref != addr->LoadRelaxed().AsMirrorPtr()) {
break;
}
} while (!addr->CompareExchangeWeakRelaxed(expected_ref, new_ref));
}
}
inline mirror::Object* ConcurrentCopying::Mark(mirror::Object* from_ref) {
......
//获取from_ref所在的Region的类型。注意,如果from_ref不是region_space_的对象,
//则GetRegionType返回kRegionTypeNone
space::RegionSpace::RegionType rtype = region_space_->GetRegionType(from_ref);
switch (rtype) {
case space::RegionSpace::RegionType::kRegionTypeToSpace:
//如果from_ref已经在To Space中,则直接返回它。不需要后续的拷贝
return from_ref;
case space::RegionSpace::RegionType::kRegionTypeFromSpace: {
/*如果from_ref位于From Space中(由Region ShouldEvacuate函数决定),则调用
GetFwdPtr找到from_ref的拷贝对象。下文将介绍GetFwdPtr函数。main*/
mirror::Object* to_ref = GetFwdPtr(from_ref);
......
if (to_ref == nullptr) {
//如果from_ref不存在对应的拷贝对象,则调用Copy生成一个拷贝对象
to_ref = Copy(from_ref);
}
return to_ref;
}
case space::RegionSpace::RegionType::kRegionTypeUnevacFromSpace: {
mirror::Object* to_ref = from_ref;
//如果from_ref位于from space中不需要清理的Region的话,则对该对象进行标记
if (region_space_bitmap_->AtomicTestAndSet(from_ref)) {
} else {
//如果from_ref是初次标记,则调用PushOntoMarkStack,下文将介绍该函数,main
PushOntoMarkStack(to_ref);
}
return to_ref;
}
case space::RegionSpace::RegionType::kRegionTypeNone:
/*如果Region类型为kRegionTypeNone,说明from_ref不是region_space_中的
对象(有可能是ImageSpace或ZygoteSpace中的对象),则调用MarkNonMoving
函数。这种情况下无须拷贝from_ref。但它的引用型成员变量所指向的对象可能被拷贝
了,我们需要做对应的处理。读者不妨自行阅读MarkNonMoving函数。 */
return MarkNonMoving(from_ref);
default:
UNREACHABLE();
}
}
inline mirror::Object* ConcurrentCopying::GetFwdPtr( mirror::Object* from_ref) {
//先拿到from_ref monitor_对应的LockWord对象
LockWord lw = from_ref->GetLockWord(false);
/*如果lw的状态为kForwardingAddress,说明lw包含了一个mirror Object对象的地址
信息。对Copying Collection而言,这个地址就是from_ref对应的拷贝对象的地址,
GC理论称之为Forwarding Address。*/
if (lw.GetState() == LockWord::kForwardingAddress) {
Object* fwd_ptr = reinterpret_cast<Object*>(lw.ForwardingAddress());
return fwd_ptr; //fwd_ptr就是from_ref的拷贝对象
} else {
return nullptr;
}
}
//Copy函数拷贝from_ref对象的信息到一个新的对象to_ref中,然后将to_ref的地址存储到from_ref monitor_成员变量中。在GC理论中,这个地址叫Forwading Address。
mirror::Object* ConcurrentCopying::Copy(mirror::Object* from_ref) {
//获取from_ref对象的内存大小
size_t obj_size = from_ref->SizeOf<...>();
//按Region的要求进行对齐
size_t region_space_alloc_size = RoundUp(obj_size, space::RegionSpace::kAlignment);
......
//从region_space_中分配一块内存用来存储from_ref的内容。这块内存的起始地址为
//to_ref
mirror::Object* to_ref = region_space_->AllocNonvirtual<true>(....);
......//region_space_分配失败的处理,这部分逻辑比较复杂,读者可先不关注它
while (true) {
//拷贝:将from_ref的信息拷贝到to_ref
memcpy(to_ref, from_ref, obj_size);
/*下面这段代码比较复杂,但功能很简单,设置from_ref的monitor_,就是把to_ref的地址
值设置到from_ref monitor_中。*/
LockWord old_lock_word = to_ref->GetLockWord(false);
......
//构造新的LockWord对象
LockWord new_lock_word = LockWord::FromForwardingAddress(
reinterpret_cast<size_t>(to_ref));
//原子操作,设置到from_ref里去。所以这段逻辑会比较复杂
bool success = from_ref->CasLockWordWeakSequentiallyConsistent(
old_lock_word, new_lock_word);
if (LIKELY(success)) {
......
PushOntoMarkStack(to_ref);//保存to_ref
return to_ref;
}
.....
}
}
void ConcurrentCopying::PushOntoMarkStack(mirror::Object* to_ref) {
Thread* self = Thread::Current();
MarkStackMode mark_stack_mode = mark_stack_mode_.LoadRelaxed();
//在FlipCallback中,mark_stack_mode_已经设置为kMarkStackModeThreadLocal了
if (LIKELY(mark_stack_mode == kMarkStackModeThreadLocal)) {
if (LIKELY(self == thread_running_gc_)) {
......
//根据上文的介绍可知,PushOntoMarkStack可能由不同的Java线程调用。如果
//调用者是GC线程自己,则把to_ref加到ConcurrentCopying gc_mark_stack_中
gc_mark_stack_->PushBack(to_ref);
} else {
/*如果是非GC线程调用PushOntoMarkStack,则需要使用线程对象tlsPtr_
thread_local_mark_stack。注意,如果线程对象还没有这个容器或者它已经存满的话,下
面的代码将从ConcurrentCopying pooled_mark_stacks_容器中取一个空闲的容器给线程。
pooled_mark_stacks_是一个数组,保存了256个ObjectStack对象,每一个ObjectStack只
能保存最多4096个Object指针。*/
accounting::AtomicStack<mirror::Object>* tl_mark_stack = self->GetThreadLocalMarkStack();
//tl_mark_stack不存在或者tl_mark_stack已满的情况
if (UNLIKELY(tl_mark_stack == nullptr || tl_mark_stack->IsFull())) {
MutexLock mu(self, mark_stack_lock_);
accounting::AtomicStack<mirror::Object>* new_tl_mark_stack;
if (!pooled_mark_stacks_.empty()) {
new_tl_mark_stack = pooled_mark_stacks_.back();
pooled_mark_stacks_.pop_back();
} else {
//如果pooled_mark_stacks_被用完,则新建一个ObjectStack
new_tl_mark_stack =
accounting::AtomicStack<mirror::Object>::Create(
"thread local mark stack", 4 * KB, 4 * KB);
}
new_tl_mark_stack->PushBack(to_ref);
self->SetThreadLocalMarkStack(new_tl_mark_stack);
if (tl_mark_stack != nullptr) {
revoked_mark_stacks_.push_back(tl_mark_stack);
}
} else {
tl_mark_stack->PushBack(to_ref);
}
}
}
/*mark_stack_mode取值为非kMarkStackModeThreadLocal的处理,也是将对象
存储到ConcurrentCopying gc_mark_stack_中。*/
......
}
void ConcurrentCopying::MarkingPhase() {
/*MarkingPhase调用前,我们只对线程根对象进行了Mark(注意,此处使用Mark这个词一方
面代表它是ConcurrentCopying中的一个函数。另一方面,根据上文相关函数的代码分析可
知,ConcurrentCopying中的Mark除了做标记之外,还会根据需要生成拷贝对象)。*/
......
{
......
/*扫描ImageSpace中的根对象。这里我们要多说几句。在MarkSweep中,对ImageSpace的扫描是
基于Write Barrier以及CardTable的。但Write Barrier这种技术却不能用于会移动对象的垃圾
回收算法。比如Copying collection。原因很简单,因为对象被移动后,它在card table中对
应card的位置也会发生变化。所以,对Copying Collection来说,Read Barrier就派上了用
场。Read Barrier有好几种比较经典的实现。ART中有三种,如TableLookup RB、Baker RB以
及Brooks RB。
笔者简单介绍下RB的大致作用:当mutator读取一个对象A的引用型成员变量a时,如果a所指向的对
象B携有forwarding address(B的拷贝对象B'),则转去读取B'。因为B有了拷贝对象B',我们
自然希望凡是读取B的地方都改成读取B'。*/
for (space::ContinuousSpace* space : heap_->GetContinuousSpaces()) {
if (space->IsImageSpace()) {
gc::space::ImageSpace* image = space->AsImageSpace();
if (image != nullptr) {
mirror::ObjectArray<mirror::Object>* image_root =
image->GetImageHeader().GetImageRoots();
//ImageSpace中的根对象不会被拷贝,所以marked_image_root等于image_root,
//这段代码有些类似校验的作用
mirror::Object* marked_image_root = Mark(image_root);
......//一些校验相关的工作
}
}
}
}
{//访问其他类型的根对象
......
Runtime::Current()->VisitConcurrentRoots(this, kVisitRootFlagAllRoots);
}
{//访问其他类型的根对象
......
Runtime::Current()->VisitNonThreadRoots(this);
}
//访问immune_spaces_中的空间
for (auto& space : immune_spaces_.GetSpaces()) {
accounting::ContinuousSpaceBitmap* live_bitmap = space->GetLiveBitmap();
/*ConcurrentCopyingImmuneSpaceObjVisitor内部将在cc_heap_bitmap_中对扫描到
的对象进行标记,同时调用PushOntoMarkStack*/
ConcurrentCopyingImmuneSpaceObjVisitor visitor(this);
live_bitmap->VisitMarkedRange(
reinterpret_cast<uintptr_t>(space->Begin()),
reinterpret_cast<uintptr_t>(space->Limit()),
visitor);
}
/*到此,所有根对象(包括immune_space_中的对象)都进行了标记。并且,根对象如果发生了
拷贝,则原始根对象将被替换为新的拷贝对象。接下来的工作就比较简单了,我们要遍历这些根
对象,将它们所引用的对象进行Mark(标记、拷贝)。同时,我们还要更新引用值。*/
Thread* self = Thread::Current();
{/*下面这段代码中包含三次ProcessMarkStack,这和ConcurrentCopying中的mark_stack_
mode_有关,它有四种取值。此次调用ProcessMarkStack时,mark_stack_mode_取值为
kMarkStackModeThreadLocal。*/
ProcessMarkStack();
//切换mark_stack_mode_为kMarkStackModeShared
SwitchToSharedMarkStackMode();
ProcessMarkStack();
//切换mark_stack_mode_为kMarkStackModeGcExclusive
SwitchToGcExclusiveMarkStackMode();
//对Java Reference对象的处理,各种回收器的处理都一样。我们后续统一介绍
ProcessReferences(self);
......
ProcessMarkStack();
......;
Runtime::Current()->GetClassLinker()->CleanupClassLoaders();
DisableMarking();
......
}
......
}
//ProcessMarkStack内部将遍历通过PushOntoMarkStack保存下来的对象(这些对象都是拷贝后得到的对象,代码中用to_ref来表示)。其中最关键函数的是Scan。
inline void ConcurrentCopying::Scan(mirror::Object* to_ref) {
//Scan很简单,就是遍历to_ref的引用型成员变量,内部调用ConcurrentCopying的Process函数进行处理。 */
ConcurrentCopyingRefFieldsVisitor visitor(this);
to_ref->VisitReferences<...>(visitor, visitor);
}
inline void ConcurrentCopying::Process(mirror::Object* obj, MemberOffset offset) {
//obj是上面Scan中的to_ref,而offset是obj的某个引用型成员变量(由下面的ref表示)
mirror::Object* ref = obj->GetFieldObject<....>(offset);
//对ref进行Mark,得到ref的to_ref,如果两个一样,则不需要更新obj offset的内容
mirror::Object* to_ref = Mark(ref);
if (to_ref == ref) { return; }
/*到此,更新obj offset的内容,使得它指向to_ref。由于使用的是原子操作,所以下面的
代码逻辑中会使用循环。*/
mirror::Object* expected_ref = ref;
mirror::Object* new_ref = to_ref;
do {
if (expected_ref != obj->GetFieldObject<......>(offset)) {
break;
}
} while (!obj->CasFieldWeakRelaxedObjectWithoutWriteBarrier<...>(
offset, expected_ref, new_ref));
}
graph LR
Clear("region_space_->ClearFromSpace()")
Sweep过程和MarkSweepl类似
void ConcurrentCopying::ReclaimPhase() {
......
{
.....
ComputeUnevacFromSpaceLiveRatio();//详情见下文代码分析
}
{
.....
region_space_->ClearFromSpace();//详情见下文代码分析
}
{
WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
......
/*清空除immune_spaces_、region_space_外的空间中其他的垃圾对象。代码逻辑和
MarkSweep Sweep的类似。内部调用ContinuousMemMapAllocSpace的Sweep函数进
行处理。*/
Sweep(false);
//调用GarbageCollector的SwapBitmaps函数,和MarkSweep的处理一样
SwapBitmaps();
heap_->UnBindBitmaps();
......
}
void ConcurrentCopying::ComputeUnevacFromSpaceLiveRatio() {
......
//对RegionSpace中的标记对象进行统计
ConcurrentCopyingComputeUnevacFromSpaceLiveRatioVisitor visitor(this);
region_space_bitmap_->VisitMarkedRange(
reinterpret_cast<uintptr_t>(region_space_->Begin()),
reinterpret_cast<uintptr_t>(region_space_->Limit()),
visitor);
}