runtime.cc
void Runtime::VisitRoots(RootVisitor* visitor, VisitRootFlags flags) {
/*RootVisitor是一个纯虚类,其定义了几个函数,供root访问时调用。参数flags有一个默认
值,为kVisitRootFlagAllRoots,表示要访问所有的root。*/
VisitNonConcurrentRoots(visitor);
VisitConcurrentRoots(visitor, flags);
}
void Runtime::VisitNonConcurrentRoots(RootVisitor* visitor) {
//1:调用所有Thread对象的VisitRoots函数
thread_list_->VisitRoots(visitor);
VisitNonThreadRoots(visitor);//接着看该函数的代码
}
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);
......
}
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);
}
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::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
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
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用于描述一个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所在的线程
};
class GcRootSource {//它仅包含两个成员变量。
.....
private:
ArtField* const field_;
ArtMethod* const method_;
};
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(); }
.....
};
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);
}
}
......
};
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 {
kCollectorTypeNone,
//下面两个枚举值和MarkSweep类有关。详情见本章对应小节的分析
kCollectorTypeMS,kCollectorTypeCMS,
//下面两个枚举值和SemiSpace类有关
kCollectorTypeSS,kCollectorTypeGSS,
//和MarkCompact类有关
kCollectorTypeMC,
//和GarbageCollector类家族无关,其作用见后续代码分析
kCollectorTypeHeapTrim,
//和ConcurrentCopying类有关
kCollectorTypeCC,
kCollectorTypeInstrumentation,
//和GarbageCollector类家族无关,其作用见后续代码分析
kCollectorTypeAddRemoveAppImageSpace,
//和CMS有关。详情见后续代码分析
kCollectorTypeHomogeneousSpaceCompact,
//和GarbageCollector类家族无关,其作用见后续代码分析
kCollectorTypeClassLinker,
};
gc_type.h
//从某种意义上来说,GcType反应的是回收工作的力度。枚举值越大,力度越高,工作也越“辛苦”
enum GcType {
kGcTypeNone,
//表示仅扫描和回收上次GC到本次GC这个时间段内所创建的对象
kGcTypeSticky,
/*仅扫描和回收应用进程自己的堆,不处理zygote的堆。这种方式和Android中Java应用程序的创建
方式有关。在Android中,应用进程是zygote进程fork出来的。*/
kGcTypePartial,
//力度最大的一种回收策略,扫描APP自己以及它从父进程zygote继承得到的堆
kGcTypeFull,
kGcTypeMax,
};
the program that modifies the objects in heap (simply, the user program)
mutator和collector:我们在第13章中曾提到过它们。这两个词是由已故世界级计算机科学先驱Edsger W.Dijkstra于1976年左右提出的。简单来说,collector表示内存回收相关的功能模块。而mutator和collector相对,一般情况下代表应用程序中除collector之外的其他部分。