ART运行时Java堆创建过程分析_第1页
ART运行时Java堆创建过程分析_第2页
ART运行时Java堆创建过程分析_第3页
ART运行时Java堆创建过程分析_第4页
ART运行时Java堆创建过程分析_第5页
已阅读5页,还剩20页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

ART运行时Java堆创建过程分析

与Dalvik虚拟机一样,ART运行时内部也有一个Java堆,用来分配Java对象。当这些Java

对象不再被使用时,ART运行时需要回收它们占用的内存。在前面一文中,我们简要介绍

了ART运行时的垃圾收集机制,从中了解到ART运行时内部使用的Java堆是由四种Space

以及各种辅助数据结构共同描述的。为了后面可以更好地分析ART运行时的垃圾收集机制,

本文就对它内部使用的Java堆的创建过程进行分析。

ART运行时创建Java堆的过程,实际上就是创建在图1涉及到的各种数据结构:

ModUrvonTabe

lmag®Vp»ce

boctfcb阳ZygaeSpaceSpaceUrgeOt|«ctSpace

(bootart时

4P

M4ctMowp

图1ART运行时堆的基本概念以及蛆成

从图1可以看到,ART运行时内部使用的Java堆的主要组成包括ImageSpaceZygoteSpace、

AllocationSpace和LargeObjectSpace四个Space,两个ModUnionTable,一个CardTable,

两个HeapBitmap,两个ObjectMap,以及三个ObjectStack。这些数据结构的介绍和作用可

以参考前面一文,接下来我们主要是分析它们的创建过程。

从前面•文可以知道,ART运行时内部使用的堆是在ART运行时初始化过程中创

建的,即在Runiimc类的成员函数Inii中创舛的,如下所示:

[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片

boolRuntimc::Init(constOptions&raw_options,boolignore_unrccognizcd){

UniquePtr<ParsedOptions>options(ParsedOptions::Create(raw_options,

ignore_unrecognized));

heap_=newgc::Heap(options->heap_initial_size_,

opt.ons->hcap_growth_lijnit_,

opt:ons->heap_min_free_,

optons->heap_max_free_,

op(.ons->hcap_targct_u(ilization_,

opt.ons->heap_maxinium_size_,

optons->image_,

opt.ons->is_concurrcnt_5c_cnablcd_,

opt.ons->parallel_gc_threads_,

optons->conc_gc_threads_,

opt.ons->low_mcmory_modc_,

opt.ons->long_pause_log_threshold_,

optons->long_gc_log_threshold_,

opt.ons->ignorc_max_footprint_);

这个函数定义在文件art/runtime/runtime.cc中。

Runtime类的成员函数Init首先是调用ParsedOptions类的静态成员函数Create解析

ART运行时的启动选项,并H.保存在变量options指向的一个ParsedOptions对象的各个成员

变量中,与堆相关的各个选项的含义如下所示:

1.options->hcap_initia]_size_:堆的初始大小,通过选项・Xms指定。

2.options->heap_growth_limit_:堆允许增长的上限值,这是堆的一个软上限值,通

过选项-XX:HeapGrowthLimil指定。

3.options->heap_min_free_:堆的最小空闲值,通过选项-XX:HeapMinFree指定。

4.options->heap_max_free_:堆的最大空闲值,通过选项-XX:HeapMaxFree指定。

5.options->hcap_targct_utilization_:堆的目标利用率,通过选项

-XX:HeapTargetUtilization指定。

6.options->heap_maximum_size_:堆的最大信,这是堆的一个硬上限值,通过诜项

-Xmx指定。

7.options->image_:用来创建ImageSpace的Image文件,通过选项-Ximage指定。

8.options->is_concurrent_gc_enabled_:是否支持并行GC,通过选项-Xgc指定。

9.options->parallel_gc_threads_:GC暂停阶段用于同时执行GC任务的线程数,通过

选项-XX:ParaHclGCThrcads指定。

10.options->conc_gc_threads_:GC非暂停阶段用于同时执行GC任务的线程数,通

过选项・XX:ConcGCThrcads指定。

11.options->low_memory_mode_:是否在低内存模式运行,通过选项

XX:LowMcmoryModc指定。

12.options->long_pause_log_threshold_:GC造成应用程序暂停的时间阀值,•旦超

过该阀值,则输出警告日志,通过选项XX:LongPauscLogThrcshokl指定。

13.options->long_gc_bg_threshold_:GC时间阀值,一旦超过该阀值,则输出警告■日

志,通过选项-XX:LongGCLogThrcshold指定。

14.options->ignore_niax_footprint_:不对堆的大小进行限制标志,通过选项

-XX:IgnorcMaxFootprint指定。

在上述14个选项中,除了后面的3个选项,其余的选项在前面这个系列的文章和这

篇文章均有详细解释过。

接下来我们就继续分析Heap类的构造函数,以便可以了解堆的创建过程,如下所

示:

[cppjviewplaincopy在CODE上查看代码片派生到我的代码片

staticconstcxprboolkGCALotModc=false;

staticconstexprsize_tkGcAlotlnterval=KB;

Heap::Heap(size_tinitial_size,size_tgrowth」imit,size_tmin_free.size_tmax_free,

doubletarget_utilization.size_tcapacity,conststd::string&

original_image_file_namc,

boolconciirrent_gc,size_tparallel_gc_threads,size_tconc_gc_threads,

boollow_memory_mode,size_tlong_pause_log_threshold,size_t

long_gc_log_thrcshold.

boolignore_max_footprint)

concurrent_5c_(concurrent_gc).

parallel_gc_threads_(parallel_gc_threads),

conc_gc_threads_(conc_gc_threads),

low_mcmory_modc_(low_memory_modc),

long_pause_log_thresho.d_(long_pause_log_threshold),

long_gc_log_thresholdjlong_gc_log_thieshold).

ignore_max_footprint_(ignore_max_footprint),

capacity.(capacity),

growth_limit_(growth_limit),

max_allowed_footprint_(initial_size).

max_allocation_stack_size_(kGCALolMode?kGcAlotlntenal

:(kDesiredHeapVerification>kNoHeapVerification)?KB:MB),

,.

min_free_(niin_free),

max_free_(max_free),

iargct_u(ilization_(targct_u(ilization),

live_bitmap_.reset(newaccounling::HeapBilmap(this));

mark_bitmap_.reset(newaccounting::HeapBitmap(this));

//Requestedbeginfortheallocspace,tofollowthemappedimageandoatfiles

byte*icqucstcd_alloc_spacc_bcgin=NULL;

std::stringimagc_filc_namc(criginal_iinagc_filc_namc);

if(!image_file_name.empty()){

space::ImageSpace*image_space=space::ImageSpace::Create(image_file_name);

AddContinuousSpace(image_space);

//Oatfilesreferencedbyimagefilesimmediatelyfollowtheminmemory,ensureallocspace

//isn'tgoingtogetinthemiddle

byte*oat_file_end_addr=image_space->GetImageHeader().GetOatFileEnd();

if(oat_file_end_addr>reqjestcd_alIoc_space_begin){

requested_alloc_space_begin=

reinterpret_cast<by(e*>(RoundUp(reinterpret_cast<uintptr_t>(oat_file_end_addr),

kPageSize));

)

}

alloc_space_=space::DlMalk)cSpace::Create(Runtinie::Current()->IsZygote()?"zygote

space":"allocspace",

initiaLsize.

growth_)imit,capacity,

requestcd_alloc_space_bcgin);

alloc_space_->SetFootprintLimit(ailoc_space_->Capacity());

AddContinuousSpace(alloc_space_);

//Allocatethelargeobjectspace.

constboolkUscFrccListSpaccForLOS=false;

if(kUseFreeListSpaceForLOS){

large_object_space_=space::FreeListSpace::Create("largeobjectspace",NULL,capacity);

}else{

large_object_space_=space::LargeObjectMapSpace::Create("largeobjectspace");

AddDiscontinuousSpace(large_obiect_space_);

//Computeheapcapacity.ContinuousspacesarcsortedinorderofBcgin().

byte*heap_begin=continuous_spaces_.front()->Begin();

size_theap_capacity=continuous_spaces_.back()->End()-

continuous_spaccs_.front()->Bcgin();

if(continuous_spaces_.back()->IsDIMallocSpace()){

heap_capacity+=

con(inuous_spaces_.back()->AsDIMallocSpace()->NonGrowthLimitCapacityO;

)

//Allocatethecard(able.

card_table_.reset(accounling::CardTable::Create(heap_begin,heap_capacity));

image_mod_union_table_.res3t(newaccounting::ModUnionTableToZygoteAlk>cspace(this));

zygote_mod_union_table_.reset(newaccounting::ModUnionlableCardCache(lhis));

//Defaultmarkstacksizeinbytes.

staticconstsize_tdefault_ma-k_stack_size=64*KB;

niark_stack_.resct(accounting::ObjectStack::Crcatc("markslack".dcfault_mark_stack_size));

allocation_stack_.reset(accounting::ObjectStack::Create("alkx:ationstack',,

max_allocation_stack_sizc_));

live_stack_.reset(accounting::ObjectStack::Create("livestack",

max_allocation_stack_size_));

if(ignorc_max_fooiprint_){

SetIdealFootprint(std::numeric_liniits<size_t>::max());

concurrent_start_bytes_=max_alIowed_footprin

//Createourgarbagecollectors.

for(size_ti=0;i<2;++i){

constboolconcurrent=i!=0;

mark_swccp_collcctors_.push_back(ncwcollector::MarkSwccp(this,concurrent));

mark_sweep_colleclors_.push_back(newcollector::PartialMarkSweep(this,concunent));

mark_sweep_coHectors_.push_back(newcollector::StickyMarkSweep(this,concurrent));

这个函数定义在文件art/runtime/gc/heap.cc中。

He叩类的构造函数就负责创建上面图1所示的各种数据结构,创建过程如下所示:

1.创建LiveBitmap和MarkBitmap,它们都是使用一个HeapBitmap对象来描述,

并且分别保存在成员变量livjbitmap一和mark_bitmap_中。

2.如果指定了image文件,即参数original_image_fHe_name的值不等于空,则调

用ImagcSpacc类的静态成员函数Create创建一个hr1agicSpace,并且调用Heap类的成员函

数AddContinuousSpacc将该ImageSpace添加到一个在地址空闰上连续的Space列表中,即

ImageSpace属于地址空间连续的Spaceo在Image文件的头部,指定了与Image文件关联的

boot.aii@classes.oat文件加载到内存的结束位置,我们需要将这个位置取出来,并且将它对

齐到页面大小,保存变量rcquested_alloc_space_bcgin中,作为一会要创建的ZygoteSpace

的开始地址。这样就可以使得ImageSpace和ZygoteSpace的布局与图1所示保持一致。

3.调用DIMallocSpace类的静态成员函数Create创建一个ZygoteSpace.注意最后

一个参数requesled_alk)€_space_begin,指定了ZygoteSpace的起始地址,它刚刚好是紧跟在

boot.art@classes.oai文件的后面。这时候代码是运行在Zygote进程中,而Zygote进程中的

ART运行时刚开始的时候是没有ZygoteSpace和AllocationSpace之分的。等到Zygote进程

fork第一个子进程的时候,才会将这里创建的ZygoteSpace一分为二,得到一个ZygoteSpace

和•个AllocationSpace。这,点与前面•文分析Dalvik虚拟机堆的管理是•样的。由于这

里创建的ZygoteSpace也是一个地址空间连续的Space,因此它也会被Heap类的成员函数

AddContinuousSpace添加一个在地址空间上连续的Space列表中。

4.接下来是创建La电cObjectSpace。正如前面一文所述,ART运行时提供了两种

LargeObjectSpace.其中一种是FreeList实现FreeListSpace,另外一种是由一组相互独立的

内存块组成的LargeObjectMapSpace。这里由于kUseFreeListSpaceForLOS的值设置为false.

因此LargeObjectSpace使用的是后一种实现,通过LargeObjectMapSpacc类的静态成员函

数Create来创建。注意,这里创建的LargeObjectSpace属于地址空间不连续的Space,因

此需要调用Heap类的另外一个成员函数AddDiscominuousSpacc将它添加到内部一,个在地址

空间上不连续的Space列表中。

5.接下来是计算所有在地址空间上连续的Space占用的内存的大小。此时,地址空

间上连续的Space有两个,分别是ImageSpace和ZygoteSpace,它们按照地址从小到大的

顺序保存在Heap类的成员变量coniinuous_spaces_描述的,个向量中。由于ImageSpace的

地址小于ZygoteSpace的地址,因此,保存在Heap类的成员变量con【inuous_spacc3_描述的

向量的第一个元素是ImageSpace,第二个元素是ZygoteSpace。注意变量heap_c叩acity的

计算,它使用ZygoteSpace的结束地址减去ImageSpace的起始地址,得到的大小实际上是

包含了图1所示的boot.art@classes.oat文件映射到内存的大小。此外,变量hcap_capacity

只是包含了ZygoteSpace的初始大小,即通过conlinuous_spaces_.back()->End()得到的大小

并没有真实地反映ZygoieSpace的真实大小,因此这时候需要获得ZygoleSpace的真实大小,

并且增加到变量heap_capacity去。首先,continuous_spaces_.back()返回的是一个

ContinuousSpace指针,但是它实际上指向的是一个子类DiMallocSpace对象。其次,

DIMallocSpace提供了函数NonGrowthLimitCapacity用来获得真实大小。因此,将

coniinuous_spaccs_.back()返回的是一个ContinuousSpace指针转换为一个DIMallocSpace指

针,就可以调用其成员函数NonGrowthLimitCapacity来获得ZygoteSpace的真实大小,并且

添加到变量heap_capacily中去。从这里我们也可以看到,变量heap_capacity描述的是并不

是准确的ImageSpace和ZygctcSpace的大小之和,而是一个比它们的和要大的一个值。但

是变量heap_capacity是用来创建CardTable的,因此它的值比真实的Space的大小大一些不

会影响程序的逻辑正确性。

6.有了所有在地址空间上连续的Space的大小之和he叩.capacity,以及地址最小的

Space的起始地址hcap_bcgin之后,就可以调用CaidTablc类的静态成员函数Create来创建

一个CardTabic了。这里的CardTable的创建过程与前面一文分析的Dalvik虚拟机内部使用

的CardTable的创建过程是一样的。从这里我们也可以看出,只有地址空间连续的Space才

具有CardTable。

7.接下来是创建用来记录在并行GC阶段,在ImageSpace上分配的对象对在

ZygoteSpace和AllocationSpace上分配的对象的弓|用的ModUnionTable»以及在Zygote

Space上分配的对象对在AllocationSpace上分配的对象的引用为ModUnionTable。前一个

ModUnionTable使用ModUnionTableToZygoteAllocspace类来描述,后一个ModUnionTable

使用ModUnionTableCardCache类来描述.关于ModUnionTableToZygoteAllocspace和

ModUnionTablcCardCachc的关系和用途可以参考前面一文。

8.接下来是创建MarkStack、AllocationStack和LiveStack,分别保存在成员变量

mark_stack_、allocaiion_siack_和live_siack_中,它们均是使用——个ObjcclSiack对象来描述。

MarkStack的初始大小设置为default_mark_stack_size,即64KBoAllocationStack和LiveStack

的初始大小设置为niax_allocalion_stack_size_。max_allocation_stack_size_^Heap类的•个

成员变量,它的值在构造函数初始化列表中设置,要么等于IKB,要么等于IMB。取决于

kGCALotMode和kDesiredHeapVerification两个值。如果kGCALotMode的值等于true.那

么max_allocation_stack_size_的值就等于kGcAlotIntenral,即1KB。否则的话,如果

kDesiredHeapVerification的佰大丁kNoHcapVcrificaiion的值,即ART运行时运行在堆验证

模式|',max_allocation_slack_size_的值就等于1KB。否则的话,max_allocation_stack_size_

的值就等于1MB。从最上面的代码可以看到,kGCALotMode的值等于false,因此

max_allocaiion_siack_size_的值取决于kDesiredHeapVerification

kDesiredHeapVerification是一个常量,它的定义如下所示:

[cpplviewplaincopy在CODE上查看代码片派生到我的代码片

//Howwewanttosanitychecktheheap'scorrectness.

enumHeapVerificationMode{

kHeapVerificationNotPermitted,//Tooearlyinruntimestart-upforheaptobeverified.

kNoHcapVerification,//Prcductiondefault.

kVerifyAIIFast,//Sanitycheckallheapaccesseswithquicker)tests.

kVerifyAll//Sanitycheckallheapaccesses.

);

staticconstexprHeapVerificationModekDesiredHeapVerification=kNoHeapVerification;

这个常量定义在文件rt/runtime/gc/heap.h中。

常量kDesiredHeapVerification定义为kNoHcapVerification,即在GC过程不对堆进

行验证,因此前面值会被设置为1MB,即AllocationStack和

LiveStack的初始大小被设置为1MB.

9.如果ART运行时启动时指定了-XX:IgnoreMaxFoolprinl选项,即Heap类的成员

变量ignore_max_footprint_的值等于true,那么就需要调用Heap类的成员函数

SctklcalFootprint将Heap类的成员变量max_allowcd_fooiprinl_的值设置为size」类型的最大

值,即不对堆的大小进行限制。同时也会将Heap类的成员变量concurrent_slart_bytes_设置

为成员变量max_allowcd_footprint_的值,这意味着不会触发并行GC。

10.最后创建垃圾收集器,保存在Heap类的成员变量mark_sweep_collectors.描述的

一个向量中。这些垃圾收集器一共有两组,其中一组用来执行并行GC,另外一组用来执行

非并行GCo每一组都包含三个垃圾收集器,它们分别是MarkSwccp、PariialMarkSwccp和

StickyMarkSweepo关于这三种垃圾收集器的关系和作用,可以参考前面一文。

接下来我们就主要分析ImageSpace、ZygoteSpace、AllocationSpace和LargeObject

Space的创建过程,其它的数据结构等到后面分析对象的分配过程和垃圾回收过程时再分析。

的面提到,ImageSpace是通过调用ImagcSpacc类的静态成员函数Create来创建的,

它的实现如卜所示:

[epp]viewplaincopy在CODE上查看代码片派生到我的代码片

ImageSpace*ImageSpace::Create(constsld::string&original_image_file_name){

if(OS::FileExists(original_iinage_file_name.c_str())){

//Ifthe/systemfileexists,itshouldbeup-co-datc.don't(ry(ogenerate

returnspace::ImageSpace::Init(original_image_fiie_name,false);

}

//Ifthe/systemfiledidn'texist,weneedtouseonefromthedalvik-cachc.

//Ifthecachefileexists,trytoopen,butifitfails,regenerate.

//Ifitdoesnotexist,generate.

std::stringimagc_file_name(GctDalvikCachcFilcnaincOrDie(original_imagc_file_namc));

if(OS::FiieExists(image_file_name.c_str())){

space::ImageSpace*image_space=space::ImageSpace::Init(image_fiIe_name,true):

if(image_space!=NULL){

returnimage_space;

)

)

CHECK(GenerateImage(image_file_name))«"Failedtogenerateimage:"«

imagc_filc_namc;

relurnspace::ImageSpace::Init(image_fiIe_name,true);

)

这个函数定义在文件art/runtimc/gc/spacc/imagc_spacc.cc中。

ImageSpace类的静态成员函数Create我们在前面一文已经分析过了,它的执行逻

辑如下所示:

I.判断参数original_image_file_name指定的Image文件是否存在。如果存在,就

调用ImagcSpacc类的静态成员函数Init创建一个imageSpace<.否则的话,继续往下执行。

2.判断/data/dalvik-cache目录下是否存在一个

systcm(a)framcwork@boot.ar(@classcs.dcx文件。如果存在,就调用ImagcSpacc类的静态成

员函数Init创建一个ImageSpace。否则的话,继续往下执行。

3.调用ImagcSpacc类的静态成员函数Gcncralclmagc^/da(a/dalvik-cachc目录创建

一个system(a)framework@bool.art(a)classes.dex,作为Image文;牛,并且调用ImageSpace类

的静态成员函数Init创建一个ImageSpace0

Image文件的创建过程可以参考前面一文,这里我们主要分析ImageSpace类的静

态成员函数Init的实现,以便可以了解ImageSpace的创建过程,如下所示:

[epp]viewplaincopy在CODE上查看代码片派生到我的代码片

ImageSpace*ImageSpace::lnit(conststd::string&image_file_name.boolvalidate_oat_tlle){

UniquePtr<File>file(OS::OpenFileForReading(image_file_name.c_str()));

ImageHeaderimage_header;

boolsuccess=filc->RcadFully(&iniagc_hcadcr.sizeof(iniagc_hcadcr));

//Note:Theimageheaderispartoftheimageduetommappagealignmentrequiredofoffset.

UniquePtr<MemMap>map(MemMap::N4apFileAtAddress(image_header.GetImageBegin(),

image_header.GctImageSize().

PROT_READ|PROT_WRITE.

MAP.PR1VATE|MAP_FIXED,

file->Fd(),

0,

false)):

UniquePtr<MemMap>image_map(MeniMap::MapFileAtAddress(nullptr,

imagc_hcadcr.Gc(ImagcBitmapSizc(),

PROT.READ,

MAP_PRIVATE,

filc->Fd().

image_header.GetBitmapOffset(),

false));

size_tbitniap_index=bitniap_index_.fetch_add(1);

std::stringbitmap_name(StringPrintf("imagespace%slive-bitmap%u",

imagc_filc_namc.c_str().

bitmap_index));

UniquePtr<accounling::SpaceBitmap>bitmap(

accounting::SpaccBitinap::CrcatcFromMcmMap(bitmap_narnc,imagc_map.rclcasc(),

icintcrprct_cast<bytc*>(niap->Bcgin()),

map->Sizc()));

Runtime*runtime=Runiimc::Currcnt();

mirror::Object*resolution_method=

image_header.GetImageRoot(ImageHeader::kResolutionMethod);

runtimc->Sc(ResolutionMcthod(down_cast<mirror::Ar(Mcthod*>(rcsokition_mc(hod));

mirror::Object*callee_save_method=

imagc_headcr.Gc(ImageRoot(ImageHcader::kCalleeSaveMcthod);

runtime->SetCalleeSaveMethod(down_cast<miiTor::ArtMethod:f:>(callee_save_method),

Runtime::kSaveAll);

callce_save_method=imagc_hcadcr.GetIinagcRoot(IinagcHcadcr::kRcfsOnlySaveMethod);

rimtime->SetCalleeSaveMethod(down_cast<mirror::ArtMethod:,:>(callee_save_method),

Runtime::kRefsOnly);

callce_save_method=

image_header.GetImageRoot(ImageHeader::kRefsAndArgsSaveMeth(Ml);

runiinie->SeiCalleeSaveMeihod(down_cast<miiror::AnMethod*>(callee_save_meihod),

Runtime::kRefsAndArgs):

UniquePtr<ImageSpace>space(newImageSpace(image_file_name,map.release(),

bitmap.rcleaseO));

space->oat_file_.reset(space->OpenOatFile());

returnspace.release();

}

这个函数定义在文件art/runiimc/gc/spacc/imagjspacc.cc中。

函数首先是调用OS::OpenFileForReading函数打开参数image_file_name指定的

Image文件,目的是为了读取位于文件开始的一个Image文件头image_headeroImage文件

头使用类ImagcHcadcr来描述,它的定义如下所示:

lcpp|viewplaincopy在CODE上查看代码片派生到我的代码片

classPACKED(4)ImagcHcadcr{

private:

byteniagic_[4];

byteversion_[4];

//Requiredbaseaddressformappingtheimage.

uint32_(image_begin_;

//Imagesize,notpagealigned.

uint32_timage_size_;

//linagebitmapoffsetinthefile.

uint32_timage_bitmap_offsei_;

//Sizeoftheimagebitmap.

uint32_timage_bitmap_size^

//Checksumoftheoatfilewelinktoforloadtimesanitycheck.

uint32_toat_checksum_;

//Startaddressforoatfile.W.I1bebeforeoat_data_bcgin_for.sofiles.

uint32_toat_file_begin_;

//RequiredoataddressexpcciedbyimageMethod::GctCode()pcintcrs.

uint32_toat_data_begin_;

//Endofoatdataaddressrangeforthisimagefile.

uint32_toat_data_end_;

//Endofoatfileaddressrange,willbeafteroat_data_end_for

//.sofiles.Usedforpositioningafollowingallocspaces.

uint32_toat_filc_end_;

//AbsoluteaddressofanObject[]ofobjectsneededtoreinitializefromanimage.

uint32_timagc_roots_;

);

这个类定义在文件art/runtime/image.h中。

ImageHeader类的各个成员变量的含义如下所示:

1.niagic_:Image文件魔数,固定为,art\n;

2.version.:Image文件版本号,目前设置为'005\0'。

3.image_begin_:指定ImageSpace映射到内存的起始地址。

4.image_size_:ImageSpace的大小。

5.image_bitmap_offse:_:用来描述ImageSpace的对象的存活的Bitmap在Image文

件的偏移位置。

6.image_bitmap_size_用来描述ImageSpace的对象的存活的Bitmap的大小。

7.oat_checksum_:与Image文件关联的boot.art@classes.oat文件的检验值。

8.oat_file_begin_:与Image文件关联的b(x)t.ar(@classes.oat文件映射到内存的起始

位置。

9.oat_data_begin_:与Image文件关联的boot.art@classes.oat文件的OATDATA段映

射到内存的起始位置。

10.oat_data_end_:与Image文件关联的boot.art@classes.oat文件的OATDATA段映

射到内存的结束位置。

11.oat_file_end_:与Image文件关联的boot.art@classes.Dat文件映射到内存的结束位

置。

12.image_roots_:一个Object对象地址数组地址,这些Object对象就是在Image

Space上分配的对象。

上而第7到第11个与OAT文件相关的成员变量的具体含义可以进一步参考前面一

文。

理解了ImageHeader类的各个成员变量的含义之后,我们就可以知道Image文件头

都包含有哪些信息了。回到ImageSpace类的静态成员函数1疝中,接下来它就调用函数

MemMap::MapFileAtAddress根据前面读出来的Image文件头的image_begin_和image_size_

信息将参数image_file_name指定的Image文件里面的ImageSpace映射到内存来,并且得

到一个McmMap对象map,月来描述映射的内存。

接下来再继续调用函数MemMap::MapFileAtAddress根据Image文件头的

imagc_bi(niap_sizc_0imagc_$izc_信息将参数imagc_file_namc指定的Image文件里面的

Bitmap也映射到内存来,并且得到一个MemMap对象imaRe_map,用来描述映射的内存。

注意,Image文件里面的Bitmap刚好是位于Space的后面,因此,在调用函数

MemMap::MapFileAtAddress映射参数image_file_name指定的Image文件时,将文件偏移位

置指定为image_sizej^齐到页面大小的值,也就是调用image_header描述的ImageHeader

对象的成员函数GetBitmapOffset得到的返回值。

有了前而的image_map之后,就可以调用SpaceBilmap类的静态成员函数

CreateFromMemMap来创建一个SpaceBitmap对象bitmap了。这个SpaceBitmap对象bitmap

描述的就是ImageSpace的LiveBitm叩。

在Image文件头的成员变量imagc_roots_描述的对象数组中,有四个特殊的

AriMcihod对象,用来描述四种特殊的ART运行时方法。ART运行时方法是一种用来描述

其它ART方法的ART方法。它们具有特殊的用途,如下所示:

1.ImageHcader::kRcsolu(ionMcthod:用来描述一个还未进行解析和链接的ART方

法。

2.ImagcHeadcr::kCalleeSavcMcthod:用来描述一个由被调用者保存的r4-rll.lr和

s0-s31寄存器的ART方法,即由被调用者保存非参数使用的通用寄存器以及所有的浮点数

寄存器。

3.ImageHeader::kRef$OnlySaveMethod:用来描述一个由被调用者保存的r5-r8、

rIO-rll和lr寄存器的ART方法,即由被调用者保存非参数使月的通用寄存器。

4.ImageHeader::kRefsAndArgsSaveMethod:用来描述一个由被调用者保存的rl-r3、

r5-r8.rIO-rll和lr寄存器的ART方法,即由被调用者保存参数和非参数使用的通用寄存器。

注意,我们上面描述是针对ARM体系结构的ART方法调用约定的。其中,r()寄存

器用来保存当前调用的ART方法,rl-r3寄存器用来传递前三个参数,其它参数通过栈来传

递。栈顶由sp寄存器指定,r4寄存器用来保存一个在GC过程中使用到的线程挂起计数器,

r5-r8和rIO-rll寄存器用来分配给局部变量使用,2寄存器用来保存当前调用线程对象,lr

寄存器用来保存当前ART方法的返回地址,ip寄存器用来保存当前执行的指令地址。

上而四个特殊的ArtMethod对象从ImageSpace取出去之后,会通过调用Runtime

类的成员函数SetResolutionMeihod和SetCalleeSaveMethod保存在用来描述ART运行时的•

个Runtime对象的内部,其中,第2、3和4个ArtMethod对象在ART运行时内部对应的类

型分别为Runtime::kSaveAll>Runtime::kRefsOniy和Runtime::kRefsAndArgs«

这些ART运行时方法在调用还未进行解析和链接的ART方法时就会使用到。它们

的具体用法可以参考前面•文。

有了前面用来描述InageSpace的MemMap对象map和描述ImageSpace的对象的

存活的SpaceBitmap对象bitmap之后,就可以创建一个ImageSpace了,如下所示:

fcpp|viewplaincopy在CODE上查看代码片派生到我的代码片

1mageSpace::ImageSpace(conststd::string&name,MemMap*mem_map,

accounting::SpaccBitmap*livc_bi(map)

:MemMapSpace(name,mem_map,mem_map->Size(),kGcRetentionPolicyNeverColiect){

DCHECK(live_bitmap!=NULL);

livc_bi(map_.rcsct(livc_bitmap);

)

这个函数定义在文件art/runtime/gc/space/image_space.cc中。

从这里就可以看出:

1.ImageSpace的回收策略为kGcRctcntionPolicyNcvci<'ollcct»即永远不会进行垃圾

回收。

2.ImageSpace是•个在地址空间上连续的Space.因为它是通过父类MemMapSpace

来管理Space的。

3.ImageSpace的对象的存活是通过SpaceBitmap来标记的。注意,ImageSpace不

像其它Space一样,有Live和Mark两个Biimap。它们而是共用一个Bitmap,这是由pImage

Space永远不会进行垃圾回收。

再回到ImagcSpace类的静态成员函数Init中,在将前面创建的ImageSpace返回给

调用者之前,还会调用ImageSpace类的成员函数OpenOatFile将与前面创建的ImageSpace

关联的OAT文件也加载到内存来。OAT文件的加载过程可以参考前面•文。

这样,ImageSpace就创建完成了。接卜来我们继续分析ZygoteSpace的创建过程。

从前面分析的Heap类构造函数可以知道,ZygoteSpace是•种DIMallocSpace,通过调用

DIMallocSpace类的静态成员函数Create来创建,它的实现如下所示:

[cpplviewplaincopy在CODE上查看代码片派生到我的代码片

DIMallocSpace*DlMallocSpace::Crca(c(conststd::string&name.size_tinitial_size.size_t

growth_limit,size_tcapacity,byte*

rcquested_begin){

size_tstarting_size=kPageSize;

//Pagealigngrowthlimitandcapacitywhichwillbeusedtomanagemmappedstorage

growth_limit=RoundUp(growthJimit,kPagcSize);

capacity=RoundUp(capacity,kPageSize);

UniqucPlr<MemMap>mcm_map(McinMap::MapAnonymous(r.amc.c_str().rcqucstcd_bcgin.

capacity,

PROT-READ|PROT_WRITE));

void*mspace=CreateMallocSpace(mem_map->Begin(),starting_size,initial_size);

//Protectmemorybeyondtheinitialsize.

byte*end=mcm_map->Bcgin()+star(ing_sizc;

if(capacity-initial_size>0){

CHECK_MEMORY_CALL(mprotect,(end,capacity-initial_size,PROT_NONE),name);

)

//Everythingissetsorecordinimmutablestructureandleave

McmMap*mcm_map_p(r=incm_map.rclcasc();

DIMallocSpace*space;

if(RUNNING_ON_VALGRIND>0){

space=newValgrindDlMdlocSpace(name.mem_map_pir,mspace,mcm_niap_ptr->Bcgin(),

end,

growth_limit,initial_size);

}else{

space=newDlMallcx:Space(name,mem_map_ptr.mspace,mem_map_ptr->Begin(),end,

growth」imit);

returnspace;

)

这个函数定义在文件art/runtinie/gc/space/d1ma11oc_space.cc中。

DIMallocSpace类的静态成员函数Create创建的ZygoteS

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论