主要参考:http://blog.csdn.net/luoshengyang/article/details/42379729 罗老师的 《ART运行时Java堆创建过程分析 》一文,将其中安卓4.4的代码和具体实现替换成Android6.0
//art/runtime/runtime.cc
782 bool Runtime::Init(const RuntimeOptions& raw_options, bool ignore_unrecognized) {
...
788 using Opt = RuntimeArgumentMap;//即Opt是RuntimeArgumentMap的别名
789 RuntimeArgumentMap runtime_options;//RuntimeArgumentMap是一个key->value map
...
849 XGcOption xgc_option = runtime_options.GetOrDefault(Opt::GcOption);
850 ATRACE_BEGIN("CreateHeap");
851 heap_ = new gc::Heap(runtime_options.GetOrDefault(Opt::MemoryInitialSize),
//gc::Heap::kDefaultInitialSize 堆的初始大小,由-Xms指定
852 runtime_options.GetOrDefault(Opt::HeapGrowthLimit),
//Default is 0 for unlimited,堆允许增长的上限值,这是堆的一个软上限值,通过选项-XX:HeapGrowthLimit指定
853 runtime_options.GetOrDefault(Opt::HeapMinFree),
//gc::Heap::kDefaultMinFree,堆的最小空闲值,通过选项-XX:HeapMinFree指定。
854 runtime_options.GetOrDefault(Opt::HeapMaxFree),
//gc::Heap::kDefaultMaxFree,堆的最大空闲值,通过选项-XX:HeapMaxFree指定。
855 runtime_options.GetOrDefault(Opt::HeapTargetUtilization),
//gc::Heap::kDefaultTargetUtilization
856 runtime_options.GetOrDefault(Opt::ForegroundHeapGrowthMultiplier),
//gc::Heap::kDefaultHeapGrowthMultiplier
857 runtime_options.GetOrDefault(Opt::MemoryMaximumSize),
//gc::Heap::kDefaultMaximumSize,由-Xmx指定
858 runtime_options.GetOrDefault(Opt::NonMovingSpaceCapacity),
//gc::Heap::kDefaultNonMovingSpaceCapacity
859 runtime_options.GetOrDefault(Opt::Image),
//用来创建Image Space的Image文件,通过选项-Ximage指定。
860 runtime_options.GetOrDefault(Opt::ImageInstructionSet),
//kRuntimeISA
861 xgc_option.collector_type_,
862 runtime_options.GetOrDefault(Opt::BackgroundGc),
//类型为BackgroundGcOption
863 runtime_options.GetOrDefault(Opt::LargeObjectSpace),
// gc::Heap::kDefaultLargeObjectSpaceType,类型为gc::space::LargeObjectSpaceType
864 runtime_options.GetOrDefault(Opt::LargeObjectThreshold),
//gc::Heap::kDefaultLargeObjectThreshold,类型为Memory<1>
865 runtime_options.GetOrDefault(Opt::ParallelGCThreads),
//0u ,类型为unsigned int。GC暂停阶段用于同时执行GC任务的线程数,通过选项-XX:ParallelGCThreads指定。
866 runtime_options.GetOrDefault(Opt::ConcGCThreads),
//类型为unsigned int。GC非暂停阶段用于同时执行GC任务的线程数,通过选项-XX:ConcGCThreads指定。
867 runtime_options.Exists(Opt::LowMemoryMode),
//是否在低内存模式运行,通过选项XX:LowMemoryMode指定。
868 runtime_options.GetOrDefault(Opt::LongPauseLogThreshold),
//GC造成应用程序暂停的时间阀值,一旦超过该阀值,则输出警告日志,通过选项XX:LongPauseLogThreshold指定。
869 runtime_options.GetOrDefault(Opt::LongGCLogThreshold),
//GC时间阀值,一旦超过该阀值,则输出警告日志,通过选项-XX:LongGCLogThreshold指定。
870 runtime_options.Exists(Opt::IgnoreMaxFootprint),
//不对堆的大小进行限制标志,通过选项-XX:IgnoreMaxFootprint指定。
871 runtime_options.GetOrDefault(Opt::UseTLAB),
872 xgc_option.verify_pre_gc_heap_,
873 xgc_option.verify_pre_sweeping_heap_,
874 xgc_option.verify_post_gc_heap_,
875 xgc_option.verify_pre_gc_rosalloc_,
876 xgc_option.verify_pre_sweeping_rosalloc_,
877 xgc_option.verify_post_gc_rosalloc_,
878 xgc_option.gcstress_,
879 runtime_options.GetOrDefault(Opt::EnableHSpaceCompactForOOM),
880 runtime_options.GetOrDefault(Opt::HSpaceCompactForOOMMinIntervalsMs));
...
1125 }
根据RuntimeArgumentMap的定义,其中#include “runtime_options.def”,该文件中存了Parse-able keys from the command line。
59 // Defines a type-safe heterogeneous key->value map.
60 // Use the VariantMap interface to look up or to store a RuntimeArgumentMapKey,Value pair.
61 //
62 // Example:
63 // auto map = RuntimeArgumentMap();
64 // map.Set(RuntimeArgumentMap::HeapTargetUtilization, 5.0);
65 // double *target_utilization = map.Get(RuntimeArgumentMap);
66 //
67 struct RuntimeArgumentMap : VariantMap<RuntimeArgumentMap, RuntimeArgumentMapKey> {
68 // This 'using' line is necessary to inherit the variadic constructor.
69 using VariantMap<RuntimeArgumentMap, RuntimeArgumentMapKey>::VariantMap;
70
71 // Make the next many usages of Key slightly shorter to type.
72 template <typename TValue>
73 using Key = RuntimeArgumentMapKey<TValue>;
74
75 // List of key declarations, shorthand for 'static const Key<T> Name'
76 #define RUNTIME_OPTIONS_KEY(Type, Name, ...) static const Key<Type> Name;
77 #include "runtime_options.def"
78 };
其中的XGcOption的定义为:
//~/android-6.0.1_r62/art/cmdline/cmdline_types.h
461 struct XGcOption {
462 // These defaults are used when the command line arguments for -Xgc:
463 // are either omitted completely or partially.
464 gc::CollectorType collector_type_ = kUseReadBarrier ?
465 // If RB is enabled (currently a build-time decision),
466 // use CC as the default GC.
467 gc::kCollectorTypeCC :
468 gc::kCollectorTypeDefault;
469 bool verify_pre_gc_heap_ = false;
470 bool verify_pre_sweeping_heap_ = kIsDebugBuild;
471 bool verify_post_gc_heap_ = false;
472 bool verify_pre_gc_rosalloc_ = kIsDebugBuild;
473 bool verify_pre_sweeping_rosalloc_ = false;
474 bool verify_post_gc_rosalloc_ = false;
475 bool gcstress_ = false;
476 };
以下为Android4.4中剩余无法对应的部分:
Runtime类的成员函数Init首先是调用ParsedOptions类的静态成员函数Create解析ART运行时的启动选项,并且保存在变量options指向的一个ParsedOptions对象的各个成员变量中,与堆相关的各个选项的含义如下所示:
5. options->heap_target_utilization_: 堆的目标利用率,通过选项-XX:HeapTargetUtilization指定。
8. options->is_concurrent_gc_enabled_: 是否支持并行GC,通过选项-Xgc指定。
接下来我们就继续分析Heap类的构造函数,以便可以了解堆的创建过程,如下所示:
105 static constexpr bool kGCALotMode = false;
106 // GC alot mode uses a small allocation stack to stress test a lot of GC.
107 static constexpr size_t kGcAlotAllocationStackSize = 4 * KB /
...
118 Heap::Heap(size_t initial_size, size_t growth_limit, size_t min_free, size_t max_free,
119 double target_utilization, double foreground_heap_growth_multiplier,
120 size_t capacity, size_t non_moving_space_capacity, const std::string& image_file_name,
121 const InstructionSet image_instruction_set, CollectorType foreground_collector_type,
122 CollectorType background_collector_type,
123 space::LargeObjectSpaceType large_object_space_type, size_t large_object_threshold,
124 size_t parallel_gc_threads, size_t conc_gc_threads, bool low_memory_mode,
125 size_t long_pause_log_threshold, size_t long_gc_log_threshold,
126 bool ignore_max_footprint, bool use_tlab,
127 bool verify_pre_gc_heap, bool verify_pre_sweeping_heap, bool verify_post_gc_heap,
128 bool verify_pre_gc_rosalloc, bool verify_pre_sweeping_rosalloc,
129 bool verify_post_gc_rosalloc, bool gc_stress_mode,
130 bool use_homogeneous_space_compaction_for_oom,
131 uint64_t min_interval_homogeneous_space_compaction_by_oom)
132 : non_moving_space_(nullptr),
133 rosalloc_space_(nullptr),
134 dlmalloc_space_(nullptr),
135 main_space_(nullptr),
136 collector_type_(kCollectorTypeNone),
...
141 parallel_gc_threads_(parallel_gc_threads),
142 conc_gc_threads_(conc_gc_threads),
143 low_memory_mode_(low_memory_mode),
144 long_pause_log_threshold_(long_pause_log_threshold),
145 long_gc_log_threshold_(long_gc_log_threshold),
146 ignore_max_footprint_(ignore_max_footprint),
...
153 capacity_(capacity),
154 growth_limit_(growth_limit),
155 max_allowed_footprint_(initial_size),
...
176 /* For GC a lot mode, we limit the allocations stacks to be kGcAlotInterval allocations. This
177 * causes a lot of GC since we do a GC for alloc whenever the stack is full. When heap
178 * verification is enabled, we limit the size of allocation stacks to speed up their
179 * searching.
180 */
181 max_allocation_stack_size_(kGCALotMode ? kGcAlotAllocationStackSize
182 : (kVerifyObjectSupport > kVerifyObjectModeFast) ? kVerifyObjectAllocationStackSize :
183 kDefaultAllocationStackSize),
184 current_allocator_(kAllocatorTypeDlMalloc),
185 current_non_moving_allocator_(kAllocatorTypeNonMoving),
186 bump_pointer_space_(nullptr),
187 temp_space_(nullptr),
188 region_space_(nullptr),
189 min_free_(min_free),
190 max_free_(max_free),
191 target_utilization_(target_utilization),
...
{
219 if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
220 LOG(INFO) << "Heap() entering";
221 }
...
234 live_bitmap_.reset(new accounting::HeapBitmap(this));
235 mark_bitmap_.reset(new accounting::HeapBitmap(this));
236 // Requested begin for the alloc space, to follow the mapped image and oat files
237 uint8_t* requested_alloc_space_begin = nullptr;
238 if (foreground_collector_type_ == kCollectorTypeCC) {
239 // Need to use a low address so that we can allocate a contiguous
240 // 2 * Xmx space when there's no image (dex2oat for target).
241 CHECK_GE(300 * MB, non_moving_space_capacity);
242 requested_alloc_space_begin = reinterpret_cast<uint8_t*>(300 * MB) - non_moving_space_capacity;
243 }
244 if (!image_file_name.empty()) {
245 ATRACE_BEGIN("ImageSpace::Create");
246 std::string error_msg;
247 auto* image_space = space::ImageSpace::Create(image_file_name.c_str(), image_instruction_set,
248 &error_msg);
249 ATRACE_END();
250 if (image_space != nullptr) {
251 AddSpace(image_space);
252 // Oat files referenced by image files immediately follow them in memory, ensure alloc space
253 // isn't going to get in the middle
254 uint8_t* oat_file_end_addr = image_space->GetImageHeader().GetOatFileEnd();
255 CHECK_GT(oat_file_end_addr, image_space->End());
256 requested_alloc_space_begin = AlignUp(oat_file_end_addr, kPageSize);
257 } else {
258 LOG(ERROR) << "Could not create image space with image file '" << image_file_name << "'. "
259 << "Attempting to fall back to imageless running. Error was: " << error_msg;
260 }
261 }
262 /*
263 requested_alloc_space_begin -> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
264 +- nonmoving space (non_moving_space_capacity)+-
265 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
266 +-????????????????????????????????????????????+-
267 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
268 +-main alloc space / bump space 1 (capacity_) +-
269 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
270 +-????????????????????????????????????????????+-
271 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
272 +-main alloc space2 / bump space 2 (capacity_)+-
273 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
274 */
...
301 ATRACE_BEGIN("Create heap maps");
302 if (separate_non_moving_space) {
303 // If we are the zygote, the non moving space becomes the zygote space when we run
304 // PreZygoteFork the first time. In this case, call the map "zygote space" since we can't
305 // rename the mem map later.
306 const char* space_name = is_zygote ? kZygoteSpaceName: kNonMovingSpaceName;
307 // Reserve the non moving mem map before the other two since it needs to be at a specific
308 // address.
309 non_moving_space_mem_map.reset(
310 MemMap::MapAnonymous(space_name, requested_alloc_space_begin,
311 non_moving_space_capacity, PROT_READ | PROT_WRITE, true, false,
312 &error_str));
313 CHECK(non_moving_space_mem_map != nullptr) << error_str;
314 // Try to reserve virtual memory at a lower address if we have a separate non moving space.
315 request_begin = reinterpret_cast<uint8_t*>(300 * MB);
316 }
...
340 // Create the non moving space first so that bitmaps don't take up the address range.
341 if (separate_non_moving_space) {
342 // Non moving space is always dlmalloc since we currently don't have support for multiple
343 // active rosalloc spaces.
344 const size_t size = non_moving_space_mem_map->Size();
345 non_moving_space_ = space::DlMallocSpace::CreateFromMemMap(
346 non_moving_space_mem_map.release(), "zygote / non moving space", kDefaultStartingSize,
347 initial_size, size, size, false);
348 non_moving_space_->SetFootprintLimit(non_moving_space_->Capacity());
349 CHECK(non_moving_space_ != nullptr) << "Failed creating non moving space "
350 << requested_alloc_space_begin;
351 AddSpace(non_moving_space_);
352 }
...
348 non_moving_space_->SetFootprintLimit(non_moving_space_->Capacity());
...
351 AddSpace(non_moving_space_);
...
418 // Compute heap capacity. Continuous spaces are sorted in order of Begin().
419 CHECK(!continuous_spaces_.empty());
420 // Relies on the spaces being sorted.
421 uint8_t* heap_begin = continuous_spaces_.front()->Begin();
422 uint8_t* heap_end = continuous_spaces_.back()->Limit();
423 size_t heap_capacity = heap_end - heap_begin;
...
430 // Allocate the card table.
431 ATRACE_BEGIN("Create card table");
432 card_table_.reset(accounting::CardTable::Create(heap_begin, heap_capacity));
433 CHECK(card_table_.get() != nullptr) << "Failed to create card table";
434 ATRACE_END();
...
454 num_bytes_allocated_.StoreRelaxed(0);
455 mark_stack_.reset(accounting::ObjectStack::Create("mark stack", kDefaultMarkStackSize,
456 kDefaultMarkStackSize));
457 const size_t alloc_stack_capacity = max_allocation_stack_size_ + kAllocationStackReserveSize;
458 allocation_stack_.reset(accounting::ObjectStack::Create(
459 "allocation stack", max_allocation_stack_size_, alloc_stack_capacity));
460 live_stack_.reset(accounting::ObjectStack::Create(
461 "live stack", max_allocation_stack_size_, alloc_stack_capacity));
...
470 if (ignore_max_footprint_) {
471 SetIdealFootprint(std::numeric_limits<size_t>::max());
472 concurrent_start_bytes_ = std::numeric_limits<size_t>::max();
473 }
...
475 // Create our garbage collectors.
476 for (size_t i = 0; i < 2; ++i) {
477 const bool concurrent = i != 0;
478 if ((MayUseCollector(kCollectorTypeCMS) && concurrent) ||
479 (MayUseCollector(kCollectorTypeMS) && !concurrent)) {
480 garbage_collectors_.push_back(new collector::MarkSweep(this, concurrent));
481 garbage_collectors_.push_back(new collector::PartialMarkSweep(this, concurrent));
482 garbage_collectors_.push_back(new collector::StickyMarkSweep(this, concurrent));
483 }
484 }
这个函数定义在文件art/runtime/gc/heap.cc中。
Heap类的构造函数就负责创建上面图1所示的各种数据结构,创建过程如下所示:
1. 创建Live Bitmap和Mark Bitmap,它们都是使用一个ContinuousSpaceBitmap对象来描述,并且分别保存在成员变量live_bitmap_和mark_bitmap_中。
2. 如果指定了image文件,即参数original_image_file_name的值不等于空,则调用ImageSpace类的静态成员函数Create创建一个Image Space,并且调用Heap类的成员函数AddSpace将该Image Space添加到一个在地址空间上连续的Space列表中,即Image Space属于地址空间连续的Space。在Image文件的头部,指定了与Image文件关联的boot.art@classes.oat文件加载到内存的结束位置,我们需要将这个位置取出来,并且将它对齐到页面大小,保存变量requested_alloc_space_begin中,作为一会要创建的Zygote Space的开始地址。这样就可以使得Image Space和Zygote Space的布局与图1所示保持一致。
3. 调用DlMallocSpaced的CreateFromMemMap函数创建一个Zygote Space(如果is_ zygote为假,则名为NonMovingSpace),注意第二个参数requested_alloc_space_begin,指定了Zygote Space的起始地址,它刚刚好是紧跟在boot.art@classes.oat文件的后面。这时候代码是运行在Zygote进程中,而Zygote进程中的ART运行时刚开始的时候是没有Zygote Space和Allocation Space之分的。等到Zygote进程fork第一个子进程的时候,才会将这里创建的Zygote Space一分为二,得到一个Zygote Space和一个Allocation Space。这一点与前面Dalvik虚拟机Java堆创建过程分析一文分析Dalvik虚拟机堆的管理是一样的。由于这里创建的Zygote Space也是一个地址空间连续的Space,因此它也会被Heap类的成员函数AddSpace添加一个在地址空间上连续的Space列表中。
4. 接下来是创建Large Object Space。正如前面ART运行时垃圾收集机制简要介绍和学习计划一文所述,ART运行时提供了两种Large Object Space,其中一种是Free List实现FreeListSpace,另外一种是由一组相互独立的内存块组成的LargeObjectMapSpace。这里由于kUseFreeListSpaceForLOS的值设置为false,因此Large Object Space使用的是后一种实现,通过LargeObjectMapSpace类的静态成员函数Create来创建。注意,这里创建的Large Object Space属于地址空间不连续的Space,因此需要调用Heap类的另外一个成员函数AddDiscontinuousSpace将它添加到内部一个在地址空间上不连续的Space列表中。
5. 接下来是计算所有在地址空间上连续的Space占用的内存的大小。此时,地址空间上连续的Space有两个,分别是Image Space和Zygote Space,它们按照地址从小到大的顺序保存在Heap类的成员变量continuous_spaces_描述的一个向量中。由于Image Space的地址小于Zygote Space的地址,因此,保存在Heap类的成员变量continuous_spaces_描述的向量的第一个元素是Image Space,第二个元素是Zygote Space。注意变量heap_capacity的计算,它使用Zygote Space的结束地址减去Image Space的起始地址,得到的大小实际上是包含了图1所示的boot.art@classes.oat文件映射到内存的大小。此外,变量heap_ capacity只是包含了Zygote Space的初始大小,即通过continuous_spaces_.back()->End()得到的大小并没有真实地反映Zygote Space的真实大小,因此这时候需要获得Zygote Space的真实大小,并且增加到变量heap_capacity去。首先,continuous_spaces_ .back()返回的是一个ContinuousSpace指针,但是它实际上指向的是一个子类DlMallocSpace对象。其次,DlMallocSpace提供了函数NonGrowthLimitCapacity用来获得真实大小。因此,将continuous_spaces_.back()返回的是一个ContinuousSpace指针转换为一个DlMallocSpace指针,就可以调用其成员函数NonGrowthLimitCapacity来获得Zygote Space的真实大小,并且添加到变量heap_capacity中去。从这里我们也可以看到,变量heap_capacity描述的是并不是准确的Image Space和Zygote Space的大小之和,而是一个比它们的和要大的一个值。但是变量heap_capacity是用来创建Card Table的,因此它的值比真实的Space的大小大一些不会影响程序的逻辑正确性。
6. 有了所有在地址空间上连续的Space的大小之和heap_capacity,以及地址最小的Space的起始地址heap_begin之后,就可以调用CardTable类的静态成员函数Create来创建一个Card Table了。这里的Card Table的创建过程与前面Dalvik虚拟机Java堆创建过程分析一文分析的Dalvik虚拟机内部使用的Card Table的创建过程是一样的。从这里我们也可以看出,只有地址空间连续的Space才具有Card Table。
7. 接下来是创建用来记录在并行GC阶段,在Image Space上分配的对象对在Zygote Space和Allocation Space上分配的对象的引用的Mod Union Table,以及在Zygote Space上分配的对象对在Allocation Space上分配的对象的引用的Mod Union Table。前一个Mod Union Table使用ModUnionTableToZygoteAllocspace类来描述,后一个Mod Union Table使用ModUnionTableCardCache类来描述。关于ModUnionTableToZygoteAllocspace和ModUnionTableCardCache的关系和用途可以参考前面ART运行时垃圾收集机制简要介绍和学习计划一文。
8. 接下来是创建Mark Stack、Allocation Stack和Live Stack,分别保存在成员变量mark_stack_、allocation_stack_和live_stack_中,它们均是使用一个ObjectStack对象来描述。Mark Stack的初始大小设置为default_ mark_ stack_ size,即64KB。Allocation Stack和Live Stack的初始大小设置为max_ allocation_stack_size_。其值与以下语句有关。kGcAlotAllocationStackSize为4KB,kVerifyObjectAllocationStackSize为16KB,kDefaultAllocationStackSize为8MB。
181 max_allocation_stack_size_(kGCALotMode ? kGcAlotAllocationStackSize
182 : (kVerifyObjectSupport > kVerifyObjectModeFast) ? kVerifyObjectAllocationStackSize :
183 kDefaultAllocationStackSize)
9. 如果ART运行时启动时指定了-XX:IgnoreMaxFootprint选项,即Heap类的成员变量ignore_max_footprint_的值等于true,那么就需要调用Heap类的成员函数SetIdealFootprint将Heap类的成员变量max_allowed_footprint_的值设置为size_t类型的最大值,即不对堆的大小进行限制。同时也会将Heap类的成员变量concurrent_start_bytes_设置为成员变量max_allowed_footprint_的值,这意味着不会触发并行GC。
10. 最后创建垃圾收集器,保存在Heap类的成员变量garbage_collectors_描述的一个向量中。这些垃圾收集器一共有两组,其中一组用来执行并行GC,另外一组用来执行非并行GC。每一组都包含三个垃圾收集器,它们分别是MarkSweep、PartialMarkSweep和StickyMarkSweep。关于这三种垃圾收集器的关系和作用,可以参考前面ART运行时垃圾收集机制简要介绍和学习计划一文。
imageheader的内容:
55 // header of image files written by ImageWriter, read and validated by Space.
56 class PACKED(4) ImageHeader {
57 public:
...
125 enum ImageMethod {
126 kResolutionMethod,//用来描述一个还未进行解析和链接的ART方法。0
127 kImtConflictMethod,//1 -imt(interface method table)
128 kImtUnimplementedMethod,//2
129 kCalleeSaveMethod,//用来描述一个由被调用者保存非参数使用的通用寄存器以及所有的浮点数寄存器。3
130 kRefsOnlySaveMethod,//用来描述一个由被调用者保存非参数使用的通用寄存器。4
131 kRefsAndArgsSaveMethod,//用来描述一个由被调用者保存参数和非参数使用的通用寄存器。5
132 kImageMethodsCount, // Number of elements in enum.
133 };
//上面几个特殊的ArtMethod对象从Image Space取出来之后,会通过调用Runtime类的成员函数SetResolutionMethod和SetCalleeSaveMethod保存在用来描述ART运行时的一个Runtime对象的内部,其中,第3/4/5个ArtMethod对象在ART运行时内部对应的类型分别为Runtime::kSaveAll、Runtime::kRefsOnly和Runtime::kRefsAndArgs。
134
135 enum ImageRoot {
136 kDexCaches,
137 kClassRoots,
138 kImageRootsMax,
139 };
140
141 enum ImageSections {
142 kSectionObjects,
143 kSectionArtFields,
144 kSectionArtMethods,
145 kSectionInternedStrings,
146 kSectionImageBitmap,
147 kSectionCount, // Number of elements in enum.
148 };
...
169 private:
170 static const uint8_t kImageMagic[4];
171 static const uint8_t kImageVersion[4];
172
173 uint8_t magic_[4];//image文件魔数,固定为"art\n"
174 uint8_t version_[4];//版本号,固定为"017\0"
175
176 // Required base address for mapping the image.
177 uint32_t image_begin_;//指定Image Space映射到内存的起始地址。
178
179 // Image size, not page aligned.
180 uint32_t image_size_;//image Space大小
181
182 // Checksum of the oat file we link to for load time sanity check.
183 uint32_t oat_checksum_;//与Image文件关联的boot.art@classes.oat文件的检验值。
184
185 // Start address for oat file. Will be before oat_data_begin_ for .so files.
186 uint32_t oat_file_begin_;//与Image文件关联的boot.art@classes.oat文件映射到内存的起始位置。
187
188 // Required oat address expected by image Method::GetCode() pointers.
189 uint32_t oat_data_begin_;//
190
191 // End of oat data address range for this image file.
192 uint32_t oat_data_end_;
193
194 // End of oat file address range. will be after oat_data_end_ for
195 // .so files. Used for positioning a following alloc spaces.
196 uint32_t oat_file_end_;//与Image文件关联的boot.art@classes.oat文件映射到内存的结束位置。
197
198 // The total delta that this image has been patched.
199 int32_t patch_delta_;
200
201 // Absolute address of an Object[] of objects needed to reinitialize from an image.
202 uint32_t image_roots_;
203
204 // Pointer size, this affects the size of the ArtMethods.
205 uint32_t pointer_size_;
206
207 // Boolean (0 or 1) to denote if the image was compiled with --compile-pic option
208 const uint32_t compile_pic_;
209
210 // Image sections
211 ImageSection sections_[kSectionCount];
212
213 // Image methods.
214 uint64_t image_methods_[kImageMethodsCount];
215
216 friend class ImageWriter;
217 };
关于Image Space:
1. Image Space的回收策略为kGcRetentionPolicyNeverCollect,即永远不会进行垃圾回收。
2. Image Space是一个在地址空间上连续的Space,因为它是通过父类MemMapSpace来管理Space的。
3. Image Space的对象的存活是通过Space Bitmap来标记的。注意,Image Space不像其它Space一样,有Live和Mark两个Bitmap。它们而是共用一个Bitmap,这是由于Image Space永远不会进行垃圾回收。
上面在创建imageSpace时用到了ImageSpace::Create,而该函数中用到了space = ImageSpace::Init(cache_filename.c_str(), image_location, true, error_msg);
而init函数中用到了 space->oat_file_.reset(space->OpenOatFile(image_filename, error_msg)); 打开oatfile时用到了OatFile类的方法Open,将与前面创建的Image Space关联的OAT文件也加载到内存来。可参见前面的文章。
792 OatFile* oat_file = OatFile::Open(oat_filename, oat_filename, image_header.GetOatDataBegin(),
793 image_header.GetOatFileBegin(),
794 !Runtime::Current()->IsAotCompiler(),
795 nullptr, error_msg);