版權(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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025廣東湛江市麻章區(qū)大學(xué)生鄉(xiāng)村醫(yī)生專項(xiàng)計(jì)劃招聘7人備考筆試題庫(kù)及答案解析
- 2026年中國(guó)林業(yè)集團(tuán)有限公司校園招聘(廣東11人)模擬筆試試題及答案解析
- 2025江西吉安市泰和縣新睿人力資源服務(wù)有限公司面向社會(huì)招聘項(xiàng)目制人員5人模擬筆試試題及答案解析
- 2025遼寧沈陽盛京資產(chǎn)管理集團(tuán)有限公司所屬子公司沈陽華海錕泰投資有限公司所屬子公司招聘5人參考考試題庫(kù)及答案解析
- 2025上海對(duì)外經(jīng)貿(mào)大學(xué)公開招聘工作人員備考筆試題庫(kù)及答案解析
- 2025湖南衡陽市衡陽縣湘南船山高級(jí)技工學(xué)校招聘專業(yè)技術(shù)人員6人參考筆試題庫(kù)附答案解析
- 2026上海銀清企業(yè)服務(wù)有限公司招聘?jìng)淇脊P試試題及答案解析
- 2025浙江溫州甌海招商發(fā)展有限公司招聘1人備考筆試題庫(kù)及答案解析
- 2025安徽皖新融資租賃有限公司服務(wù)人員招聘崗位核減備考筆試題庫(kù)及答案解析
- 2025年河南輕工職業(yè)學(xué)院招聘工作人員(博士)5名備考考試試題及答案解析
- 招投標(biāo)自查自糾報(bào)告
- 高校公寓管理述職報(bào)告
- HG-T 20583-2020 鋼制化工容器結(jié)構(gòu)設(shè)計(jì)規(guī)范
- 單位職工健康體檢總結(jié)報(bào)告
- 有序則安之現(xiàn)場(chǎng)定置管理技術(shù)
- V型濾池設(shè)計(jì)計(jì)算書2021
- 醫(yī)院護(hù)理培訓(xùn)課件:《老年患者靜脈輸液的治療與護(hù)理》
- 安全用電防止觸電主題教育PPT模板
- LY/T 1690-2017低效林改造技術(shù)規(guī)程
- 通信工程設(shè)計(jì)基礎(chǔ)doc資料
- 流體機(jī)械原理:05第四章 泵的汽蝕
評(píng)論
0/150
提交評(píng)論