ART運(yùn)行時(shí)Java堆創(chuàng)建過程分析_第1頁
ART運(yùn)行時(shí)Java堆創(chuàng)建過程分析_第2頁
ART運(yùn)行時(shí)Java堆創(chuàng)建過程分析_第3頁
ART運(yùn)行時(shí)Java堆創(chuàng)建過程分析_第4頁
ART運(yùn)行時(shí)Java堆創(chuàng)建過程分析_第5頁
已閱讀5頁,還剩20頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

ART運(yùn)行時(shí)Java堆創(chuàng)建過程分析

與Dalvik虛擬機(jī)一樣,ART運(yùn)行時(shí)內(nèi)部也有一個(gè)Java堆,用來分配Java對(duì)象。當(dāng)這些Java

對(duì)象不再被使用時(shí),ART運(yùn)行時(shí)需要回收它們占用的內(nèi)存。在前面一文中,我們簡(jiǎn)要介紹

了ART運(yùn)行時(shí)的垃圾收集機(jī)制,從中了解到ART運(yùn)行時(shí)內(nèi)部使用的Java堆是由四種Space

以及各種輔助數(shù)據(jù)結(jié)構(gòu)共同描述的。為了后面可以更好地分析ART運(yùn)行時(shí)的垃圾收集機(jī)制,

本文就對(duì)它內(nèi)部使用的Java堆的創(chuàng)建過程進(jìn)行分析。

ART運(yùn)行時(shí)創(chuàng)建Java堆的過程,實(shí)際上就是創(chuàng)建在圖1涉及到的各種數(shù)據(jù)結(jié)構(gòu):

ModUrvonTabe

lmag?Vp?ce

boctfcb陽ZygaeSpaceSpaceUrgeOt|?ctSpace

(bootart時(shí)

4P

M4ctMowp

圖1ART運(yùn)行時(shí)堆的基本概念以及蛆成

從圖1可以看到,ART運(yùn)行時(shí)內(nèi)部使用的Java堆的主要組成包括ImageSpaceZygoteSpace、

AllocationSpace和LargeObjectSpace四個(gè)Space,兩個(gè)ModUnionTable,一個(gè)CardTable,

兩個(gè)HeapBitmap,兩個(gè)ObjectMap,以及三個(gè)ObjectStack。這些數(shù)據(jù)結(jié)構(gòu)的介紹和作用可

以參考前面一文,接下來我們主要是分析它們的創(chuàng)建過程。

從前面?文可以知道,ART運(yùn)行時(shí)內(nèi)部使用的堆是在ART運(yùn)行時(shí)初始化過程中創(chuàng)

建的,即在Runiimc類的成員函數(shù)Inii中創(chuàng)舛的,如下所示:

[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_);

這個(gè)函數(shù)定義在文件art/runtime/runtime.cc中。

Runtime類的成員函數(shù)Init首先是調(diào)用ParsedOptions類的靜態(tài)成員函數(shù)Create解析

ART運(yùn)行時(shí)的啟動(dòng)選項(xiàng),并H.保存在變量options指向的一個(gè)ParsedOptions對(duì)象的各個(gè)成員

變量中,與堆相關(guān)的各個(gè)選項(xiàng)的含義如下所示:

1.options->hcap_initia]_size_:堆的初始大小,通過選項(xiàng)?Xms指定。

2.options->heap_growth_limit_:堆允許增長(zhǎng)的上限值,這是堆的一個(gè)軟上限值,通

過選項(xiàng)-XX:HeapGrowthLimil指定。

3.options->heap_min_free_:堆的最小空閑值,通過選項(xiàng)-XX:HeapMinFree指定。

4.options->heap_max_free_:堆的最大空閑值,通過選項(xiàng)-XX:HeapMaxFree指定。

5.options->hcap_targct_utilization_:堆的目標(biāo)利用率,通過選項(xiàng)

-XX:HeapTargetUtilization指定。

6.options->heap_maximum_size_:堆的最大信,這是堆的一個(gè)硬上限值,通過詵項(xiàng)

-Xmx指定。

7.options->image_:用來創(chuàng)建ImageSpace的Image文件,通過選項(xiàng)-Ximage指定。

8.options->is_concurrent_gc_enabled_:是否支持并行GC,通過選項(xiàng)-Xgc指定。

9.options->parallel_gc_threads_:GC暫停階段用于同時(shí)執(zhí)行GC任務(wù)的線程數(shù),通過

選項(xiàng)-XX:ParaHclGCThrcads指定。

10.options->conc_gc_threads_:GC非暫停階段用于同時(shí)執(zhí)行GC任務(wù)的線程數(shù),通

過選項(xiàng)?XX:ConcGCThrcads指定。

11.options->low_memory_mode_:是否在低內(nèi)存模式運(yùn)行,通過選項(xiàng)

XX:LowMcmoryModc指定。

12.options->long_pause_log_threshold_:GC造成應(yīng)用程序暫停的時(shí)間閥值,?旦超

過該閥值,則輸出警告日志,通過選項(xiàng)XX:LongPauscLogThrcshokl指定。

13.options->long_gc_bg_threshold_:GC時(shí)間閥值,一旦超過該閥值,則輸出警告■日

志,通過選項(xiàng)-XX:LongGCLogThrcshold指定。

14.options->ignore_niax_footprint_:不對(duì)堆的大小進(jìn)行限制標(biāo)志,通過選項(xiàng)

-XX:IgnorcMaxFootprint指定。

在上述14個(gè)選項(xiàng)中,除了后面的3個(gè)選項(xiàng),其余的選項(xiàng)在前面這個(gè)系列的文章和這

篇文章均有詳細(xì)解釋過。

接下來我們就繼續(xù)分析Heap類的構(gòu)造函數(shù),以便可以了解堆的創(chuàng)建過程,如下所

示:

[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));

這個(gè)函數(shù)定義在文件art/runtime/gc/heap.cc中。

He叩類的構(gòu)造函數(shù)就負(fù)責(zé)創(chuàng)建上面圖1所示的各種數(shù)據(jù)結(jié)構(gòu),創(chuàng)建過程如下所示:

1.創(chuàng)建LiveBitmap和MarkBitmap,它們都是使用一個(gè)HeapBitmap對(duì)象來描述,

并且分別保存在成員變量livjbitmap一和mark_bitmap_中。

2.如果指定了image文件,即參數(shù)original_image_fHe_name的值不等于空,則調(diào)

用ImagcSpacc類的靜態(tài)成員函數(shù)Create創(chuàng)建一個(gè)hr1agicSpace,并且調(diào)用Heap類的成員函

數(shù)AddContinuousSpacc將該ImageSpace添加到一個(gè)在地址空閏上連續(xù)的Space列表中,即

ImageSpace屬于地址空間連續(xù)的Spaceo在Image文件的頭部,指定了與Image文件關(guān)聯(lián)的

boot.aii@classes.oat文件加載到內(nèi)存的結(jié)束位置,我們需要將這個(gè)位置取出來,并且將它對(duì)

齊到頁面大小,保存變量rcquested_alloc_space_bcgin中,作為一會(huì)要?jiǎng)?chuàng)建的ZygoteSpace

的開始地址。這樣就可以使得ImageSpace和ZygoteSpace的布局與圖1所示保持一致。

3.調(diào)用DIMallocSpace類的靜態(tài)成員函數(shù)Create創(chuàng)建一個(gè)ZygoteSpace.注意最后

一個(gè)參數(shù)requesled_alk)€_space_begin,指定了ZygoteSpace的起始地址,它剛剛好是緊跟在

boot.art@classes.oai文件的后面。這時(shí)候代碼是運(yùn)行在Zygote進(jìn)程中,而Zygote進(jìn)程中的

ART運(yùn)行時(shí)剛開始的時(shí)候是沒有ZygoteSpace和AllocationSpace之分的。等到Zygote進(jìn)程

fork第一個(gè)子進(jìn)程的時(shí)候,才會(huì)將這里創(chuàng)建的ZygoteSpace一分為二,得到一個(gè)ZygoteSpace

和?個(gè)AllocationSpace。這,點(diǎn)與前面?文分析Dalvik虛擬機(jī)堆的管理是?樣的。由于這

里創(chuàng)建的ZygoteSpace也是一個(gè)地址空間連續(xù)的Space,因此它也會(huì)被Heap類的成員函數(shù)

AddContinuousSpace添加一個(gè)在地址空間上連續(xù)的Space列表中。

4.接下來是創(chuàng)建La電cObjectSpace。正如前面一文所述,ART運(yùn)行時(shí)提供了兩種

LargeObjectSpace.其中一種是FreeList實(shí)現(xiàn)FreeListSpace,另外一種是由一組相互獨(dú)立的

內(nèi)存塊組成的LargeObjectMapSpace。這里由于kUseFreeListSpaceForLOS的值設(shè)置為false.

因此LargeObjectSpace使用的是后一種實(shí)現(xiàn),通過LargeObjectMapSpacc類的靜態(tài)成員函

數(shù)Create來創(chuàng)建。注意,這里創(chuàng)建的LargeObjectSpace屬于地址空間不連續(xù)的Space,因

此需要調(diào)用Heap類的另外一個(gè)成員函數(shù)AddDiscominuousSpacc將它添加到內(nèi)部一,個(gè)在地址

空間上不連續(xù)的Space列表中。

5.接下來是計(jì)算所有在地址空間上連續(xù)的Space占用的內(nèi)存的大小。此時(shí),地址空

間上連續(xù)的Space有兩個(gè),分別是ImageSpace和ZygoteSpace,它們按照地址從小到大的

順序保存在Heap類的成員變量coniinuous_spaces_描述的,個(gè)向量中。由于ImageSpace的

地址小于ZygoteSpace的地址,因此,保存在Heap類的成員變量con【inuous_spacc3_描述的

向量的第一個(gè)元素是ImageSpace,第二個(gè)元素是ZygoteSpace。注意變量heap_c叩acity的

計(jì)算,它使用ZygoteSpace的結(jié)束地址減去ImageSpace的起始地址,得到的大小實(shí)際上是

包含了圖1所示的boot.art@classes.oat文件映射到內(nèi)存的大小。此外,變量hcap_capacity

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

并沒有真實(shí)地反映ZygoieSpace的真實(shí)大小,因此這時(shí)候需要獲得ZygoleSpace的真實(shí)大小,

并且增加到變量heap_capacity去。首先,continuous_spaces_.back()返回的是一個(gè)

ContinuousSpace指針,但是它實(shí)際上指向的是一個(gè)子類DiMallocSpace對(duì)象。其次,

DIMallocSpace提供了函數(shù)NonGrowthLimitCapacity用來獲得真實(shí)大小。因此,將

coniinuous_spaccs_.back()返回的是一個(gè)ContinuousSpace指針轉(zhuǎn)換為一個(gè)DIMallocSpace指

針,就可以調(diào)用其成員函數(shù)NonGrowthLimitCapacity來獲得ZygoteSpace的真實(shí)大小,并且

添加到變量heap_capacily中去。從這里我們也可以看到,變量heap_capacity描述的是并不

是準(zhǔn)確的ImageSpace和ZygctcSpace的大小之和,而是一個(gè)比它們的和要大的一個(gè)值。但

是變量heap_capacity是用來創(chuàng)建CardTable的,因此它的值比真實(shí)的Space的大小大一些不

會(huì)影響程序的邏輯正確性。

6.有了所有在地址空間上連續(xù)的Space的大小之和he叩.capacity,以及地址最小的

Space的起始地址hcap_bcgin之后,就可以調(diào)用CaidTablc類的靜態(tài)成員函數(shù)Create來創(chuàng)建

一個(gè)CardTabic了。這里的CardTable的創(chuàng)建過程與前面一文分析的Dalvik虛擬機(jī)內(nèi)部使用

的CardTable的創(chuàng)建過程是一樣的。從這里我們也可以看出,只有地址空間連續(xù)的Space才

具有CardTable。

7.接下來是創(chuàng)建用來記錄在并行GC階段,在ImageSpace上分配的對(duì)象對(duì)在

ZygoteSpace和AllocationSpace上分配的對(duì)象的弓|用的ModUnionTable?以及在Zygote

Space上分配的對(duì)象對(duì)在AllocationSpace上分配的對(duì)象的引用為ModUnionTable。前一個(gè)

ModUnionTable使用ModUnionTableToZygoteAllocspace類來描述,后一個(gè)ModUnionTable

使用ModUnionTableCardCache類來描述.關(guān)于ModUnionTableToZygoteAllocspace和

ModUnionTablcCardCachc的關(guān)系和用途可以參考前面一文。

8.接下來是創(chuàng)建MarkStack、AllocationStack和LiveStack,分別保存在成員變量

mark_stack_、allocaiion_siack_和live_siack_中,它們均是使用——個(gè)ObjcclSiack對(duì)象來描述。

MarkStack的初始大小設(shè)置為default_mark_stack_size,即64KBoAllocationStack和LiveStack

的初始大小設(shè)置為niax_allocalion_stack_size_。max_allocation_stack_size_^Heap類的?個(gè)

成員變量,它的值在構(gòu)造函數(shù)初始化列表中設(shè)置,要么等于IKB,要么等于IMB。取決于

kGCALotMode和kDesiredHeapVerification兩個(gè)值。如果kGCALotMode的值等于true.那

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

kDesiredHeapVerification的佰大丁kNoHcapVcrificaiion的值,即ART運(yùn)行時(shí)運(yùn)行在堆驗(yàn)證

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

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

max_allocaiion_siack_size_的值取決于kDesiredHeapVerification

kDesiredHeapVerification是一個(gè)常量,它的定義如下所示:

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

//Howwewanttosanitychecktheheap'scorrectness.

enumHeapVerificationMode{

kHeapVerificationNotPermitted,//Tooearlyinruntimestart-upforheaptobeverified.

kNoHcapVerification,//Prcductiondefault.

kVerifyAIIFast,//Sanitycheckallheapaccesseswithquicker)tests.

kVerifyAll//Sanitycheckallheapaccesses.

);

staticconstexprHeapVerificationModekDesiredHeapVerification=kNoHeapVerification;

這個(gè)常量定義在文件rt/runtime/gc/heap.h中。

常量kDesiredHeapVerification定義為kNoHcapVerification,即在GC過程不對(duì)堆進(jìn)

行驗(yàn)證,因此前面值會(huì)被設(shè)置為1MB,即AllocationStack和

LiveStack的初始大小被設(shè)置為1MB.

9.如果ART運(yùn)行時(shí)啟動(dòng)時(shí)指定了-XX:IgnoreMaxFoolprinl選項(xiàng),即Heap類的成員

變量ignore_max_footprint_的值等于true,那么就需要調(diào)用Heap類的成員函數(shù)

SctklcalFootprint將Heap類的成員變量max_allowcd_fooiprinl_的值設(shè)置為size」類型的最大

值,即不對(duì)堆的大小進(jìn)行限制。同時(shí)也會(huì)將Heap類的成員變量concurrent_slart_bytes_設(shè)置

為成員變量max_allowcd_footprint_的值,這意味著不會(huì)觸發(fā)并行GC。

10.最后創(chuàng)建垃圾收集器,保存在Heap類的成員變量mark_sweep_collectors.描述的

一個(gè)向量中。這些垃圾收集器一共有兩組,其中一組用來執(zhí)行并行GC,另外一組用來執(zhí)行

非并行GCo每一組都包含三個(gè)垃圾收集器,它們分別是MarkSwccp、PariialMarkSwccp和

StickyMarkSweepo關(guān)于這三種垃圾收集器的關(guān)系和作用,可以參考前面一文。

接下來我們就主要分析ImageSpace、ZygoteSpace、AllocationSpace和LargeObject

Space的創(chuàng)建過程,其它的數(shù)據(jù)結(jié)構(gòu)等到后面分析對(duì)象的分配過程和垃圾回收過程時(shí)再分析。

的面提到,ImageSpace是通過調(diào)用ImagcSpacc類的靜態(tài)成員函數(shù)Create來創(chuàng)建的,

它的實(shí)現(xiàn)如卜所示:

[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);

)

這個(gè)函數(shù)定義在文件art/runtimc/gc/spacc/imagc_spacc.cc中。

ImageSpace類的靜態(tài)成員函數(shù)Create我們?cè)谇懊嬉晃囊呀?jīng)分析過了,它的執(zhí)行邏

輯如下所示:

I.判斷參數(shù)original_image_file_name指定的Image文件是否存在。如果存在,就

調(diào)用ImagcSpacc類的靜態(tài)成員函數(shù)Init創(chuàng)建一個(gè)imageSpace<.否則的話,繼續(xù)往下執(zhí)行。

2.判斷/data/dalvik-cache目錄下是否存在一個(gè)

systcm(a)framcwork@boot.ar(@classcs.dcx文件。如果存在,就調(diào)用ImagcSpacc類的靜態(tài)成

員函數(shù)Init創(chuàng)建一個(gè)ImageSpace。否則的話,繼續(xù)往下執(zhí)行。

3.調(diào)用ImagcSpacc類的靜態(tài)成員函數(shù)Gcncralclmagc^/da(a/dalvik-cachc目錄創(chuàng)建

一個(gè)system(a)framework@bool.art(a)classes.dex,作為Image文;牛,并且調(diào)用ImageSpace類

的靜態(tài)成員函數(shù)Init創(chuàng)建一個(gè)ImageSpace0

Image文件的創(chuàng)建過程可以參考前面一文,這里我們主要分析ImageSpace類的靜

態(tài)成員函數(shù)Init的實(shí)現(xiàn),以便可以了解ImageSpace的創(chuàng)建過程,如下所示:

[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();

}

這個(gè)函數(shù)定義在文件art/runiimc/gc/spacc/imagjspacc.cc中。

函數(shù)首先是調(diào)用OS::OpenFileForReading函數(shù)打開參數(shù)image_file_name指定的

Image文件,目的是為了讀取位于文件開始的一個(gè)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_;

);

這個(gè)類定義在文件art/runtime/image.h中。

ImageHeader類的各個(gè)成員變量的含義如下所示:

1.niagic_:Image文件魔數(shù),固定為,art\n;

2.version.:Image文件版本號(hào),目前設(shè)置為'005\0'。

3.image_begin_:指定ImageSpace映射到內(nèi)存的起始地址。

4.image_size_:ImageSpace的大小。

5.image_bitmap_offse:_:用來描述ImageSpace的對(duì)象的存活的Bitmap在Image文

件的偏移位置。

6.image_bitmap_size_用來描述ImageSpace的對(duì)象的存活的Bitmap的大小。

7.oat_checksum_:與Image文件關(guān)聯(lián)的boot.art@classes.oat文件的檢驗(yàn)值。

8.oat_file_begin_:與Image文件關(guān)聯(lián)的b(x)t.ar(@classes.oat文件映射到內(nèi)存的起始

位置。

9.oat_data_begin_:與Image文件關(guān)聯(lián)的boot.art@classes.oat文件的OATDATA段映

射到內(nèi)存的起始位置。

10.oat_data_end_:與Image文件關(guān)聯(lián)的boot.art@classes.oat文件的OATDATA段映

射到內(nèi)存的結(jié)束位置。

11.oat_file_end_:與Image文件關(guān)聯(lián)的boot.art@classes.Dat文件映射到內(nèi)存的結(jié)束位

置。

12.image_roots_:一個(gè)Object對(duì)象地址數(shù)組地址,這些Object對(duì)象就是在Image

Space上分配的對(duì)象。

上而第7到第11個(gè)與OAT文件相關(guān)的成員變量的具體含義可以進(jìn)一步參考前面一

文。

理解了ImageHeader類的各個(gè)成員變量的含義之后,我們就可以知道Image文件頭

都包含有哪些信息了。回到ImageSpace類的靜態(tài)成員函數(shù)1疝中,接下來它就調(diào)用函數(shù)

MemMap::MapFileAtAddress根據(jù)前面讀出來的Image文件頭的image_begin_和image_size_

信息將參數(shù)image_file_name指定的Image文件里面的ImageSpace映射到內(nèi)存來,并且得

到一個(gè)McmMap對(duì)象map,月來描述映射的內(nèi)存。

接下來再繼續(xù)調(diào)用函數(shù)MemMap::MapFileAtAddress根據(jù)Image文件頭的

imagc_bi(niap_sizc_0imagc_$izc_信息將參數(shù)imagc_file_namc指定的Image文件里面的

Bitmap也映射到內(nèi)存來,并且得到一個(gè)MemMap對(duì)象imaRe_map,用來描述映射的內(nèi)存。

注意,Image文件里面的Bitmap剛好是位于Space的后面,因此,在調(diào)用函數(shù)

MemMap::MapFileAtAddress映射參數(shù)image_file_name指定的Image文件時(shí),將文件偏移位

置指定為image_sizej^齊到頁面大小的值,也就是調(diào)用image_header描述的ImageHeader

對(duì)象的成員函數(shù)GetBitmapOffset得到的返回值。

有了前而的image_map之后,就可以調(diào)用SpaceBilmap類的靜態(tài)成員函數(shù)

CreateFromMemMap來創(chuàng)建一個(gè)SpaceBitmap對(duì)象bitmap了。這個(gè)SpaceBitmap對(duì)象bitmap

描述的就是ImageSpace的LiveBitm叩。

在Image文件頭的成員變量imagc_roots_描述的對(duì)象數(shù)組中,有四個(gè)特殊的

AriMcihod對(duì)象,用來描述四種特殊的ART運(yùn)行時(shí)方法。ART運(yùn)行時(shí)方法是一種用來描述

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

1.ImageHcader::kRcsolu(ionMcthod:用來描述一個(gè)還未進(jìn)行解析和鏈接的ART方

法。

2.ImagcHeadcr::kCalleeSavcMcthod:用來描述一個(gè)由被調(diào)用者保存的r4-rll.lr和

s0-s31寄存器的ART方法,即由被調(diào)用者保存非參數(shù)使用的通用寄存器以及所有的浮點(diǎn)數(shù)

寄存器。

3.ImageHeader::kRef$OnlySaveMethod:用來描述一個(gè)由被調(diào)用者保存的r5-r8、

rIO-rll和lr寄存器的ART方法,即由被調(diào)用者保存非參數(shù)使月的通用寄存器。

4.ImageHeader::kRefsAndArgsSaveMethod:用來描述一個(gè)由被調(diào)用者保存的rl-r3、

r5-r8.rIO-rll和lr寄存器的ART方法,即由被調(diào)用者保存參數(shù)和非參數(shù)使用的通用寄存器。

注意,我們上面描述是針對(duì)ARM體系結(jié)構(gòu)的ART方法調(diào)用約定的。其中,r()寄存

器用來保存當(dāng)前調(diào)用的ART方法,rl-r3寄存器用來傳遞前三個(gè)參數(shù),其它參數(shù)通過棧來傳

遞。棧頂由sp寄存器指定,r4寄存器用來保存一個(gè)在GC過程中使用到的線程掛起計(jì)數(shù)器,

r5-r8和rIO-rll寄存器用來分配給局部變量使用,2寄存器用來保存當(dāng)前調(diào)用線程對(duì)象,lr

寄存器用來保存當(dāng)前ART方法的返回地址,ip寄存器用來保存當(dāng)前執(zhí)行的指令地址。

上而四個(gè)特殊的ArtMethod對(duì)象從ImageSpace取出去之后,會(huì)通過調(diào)用Runtime

類的成員函數(shù)SetResolutionMeihod和SetCalleeSaveMethod保存在用來描述ART運(yùn)行時(shí)的?

個(gè)Runtime對(duì)象的內(nèi)部,其中,第2、3和4個(gè)ArtMethod對(duì)象在ART運(yùn)行時(shí)內(nèi)部對(duì)應(yīng)的類

型分別為Runtime::kSaveAll>Runtime::kRefsOniy和Runtime::kRefsAndArgs?

這些ART運(yùn)行時(shí)方法在調(diào)用還未進(jìn)行解析和鏈接的ART方法時(shí)就會(huì)使用到。它們

的具體用法可以參考前面?文。

有了前面用來描述InageSpace的MemMap對(duì)象map和描述ImageSpace的對(duì)象的

存活的SpaceBitmap對(duì)象bitmap之后,就可以創(chuàng)建一個(gè)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);

)

這個(gè)函數(shù)定義在文件art/runtime/gc/space/image_space.cc中。

從這里就可以看出:

1.ImageSpace的回收策略為kGcRctcntionPolicyNcvci<'ollcct?即永遠(yuǎn)不會(huì)進(jìn)行垃圾

回收。

2.ImageSpace是?個(gè)在地址空間上連續(xù)的Space.因?yàn)樗峭ㄟ^父類MemMapSpace

來管理Space的。

3.ImageSpace的對(duì)象的存活是通過SpaceBitmap來標(biāo)記的。注意,ImageSpace不

像其它Space一樣,有Live和Mark兩個(gè)Biimap。它們而是共用一個(gè)Bitmap,這是由pImage

Space永遠(yuǎn)不會(huì)進(jìn)行垃圾回收。

再回到ImagcSpace類的靜態(tài)成員函數(shù)Init中,在將前面創(chuàng)建的ImageSpace返回給

調(diào)用者之前,還會(huì)調(diào)用ImageSpace類的成員函數(shù)OpenOatFile將與前面創(chuàng)建的ImageSpace

關(guān)聯(lián)的OAT文件也加載到內(nèi)存來。OAT文件的加載過程可以參考前面?文。

這樣,ImageSpace就創(chuàng)建完成了。接卜來我們繼續(xù)分析ZygoteSpace的創(chuàng)建過程。

從前面分析的Heap類構(gòu)造函數(shù)可以知道,ZygoteSpace是?種DIMallocSpace,通過調(diào)用

DIMallocSpace類的靜態(tài)成員函數(shù)Create來創(chuàng)建,它的實(shí)現(xiàn)如下所示:

[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;

)

這個(gè)函數(shù)定義在文件art/runtinie/gc/space/d1ma11oc_space.cc中。

DIMallocSpace類的靜態(tài)成員函數(shù)Create創(chuàng)建的ZygoteS

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論