ART运行时CompactingGC为新创建对象分配内存的过程分析.docx
ART运行时COinPaCtingGC为新创立对象分配内存的过程分析在引进CompactingGC后,ART运行时优化了堆内存分配过程.最显著特点是为每个RT运行时线程增加局局部配缓冲区<Thead1.oca1.A1.1.ocationBuffer)和在OOM前进行一次同构空间压缩(HomogeneousSpaceCompact).前者可提高堆内存分配效率,后者可解决内存碎片问璃。本文就对ART运行时引进<npac1.ingGC后的堆内存分配过程进行分析。从接口层面上看,除了提供常规的对©分配接口AIIOCobjeCt,AKT运行时的堆还提供了一个专门用于分配非移动对象的接口A11OcNonMovab1ebject,如图1所示:A1.cO>jStMocNonMftXieCqKtM1.occ(I)MIMtXMIocteor明1ART运行时堆提供的对象分配接口非移动对象指的是保存在前面一倘文章提到的Non-MovingSpace的对象,主要包括那些在类加栽过程中创立的类对象(C1.ass),类方法对象(Ar1.Ne1.hOd)和类成员变量对象(Ar1.Fie1.d等,以及那些在经历过若干次Generationa1.Semi-SpaceGC之后仍然存活的对象.前者是通过A1.IocNonMovab1.eObject接口分配的,而后者是在执行GeneratiOna1.Semi-SpaceCC过程移动过去的.本文主要关注通过AI1.oCNOnMOVab1.eobjeet接口分配的非移动对象,无论是通过AI1.OCObjeCt接口分配对收,还是通过AI1.oeNOnMOVabIeObjeCt接口分配对象.蜃后都统一时用了另外一个接口AnOCObjeCeithA1.IOCatorj5行具体的分配过程,如下所示:cppviewp1.aincopy在CoDE上杳看代玛片派生到我的代码片c1.assHeap(pub1.ic:/A1.1.ocatesandinitia1.izesstorageforanobjectinstance.temp1.ate<IxioIk1.nstruaented,typennmeEreFenceVisitor>mirror:Object*A1.IocObject(Thread*se1.f,mirror:C1.ass*k1.ass,sizenu111.bytes,constPreFenceVisitorftPrjrenCe_ViSi1.Or)SI1.ARED_1.OCKS_REQUIRED(1.oCks:BUtatorOCkj(returnA1.IocObjectBithA1.1.ocator<k1.nstrumented,true>(se1.f,k1.ass,num_bytes,GetcurrentA1.IocatorO,PrCjenCe_viSitor):temp1.ate<boo1.k1.nstru三ented,typenamePreFenceVisitor>mirror:Object*1.IocNonMovab1.cObject(Threadse1.f,mirror:zC1.assk1.ass9sizetnumbytes,constPreFenceVisitorApre_fence_visitor)SHARED1.oCKS_REQUIRED(1.oCkS:BUIaI。J1.OCk_)(return1.IocObjectUithj1.1.ocator<k1.nstrumented.true>(se1.f.k1.ass.num_bytes.GetCurrentNonMoving11.ocatorO,pre_fencevisitor);)temp1.ate<1.)o1.kInstruaentedfboo1.kCheck1.arge()bject,type11fimePreFenceVisitor>A1.WRYS,N1.1NEmirror:ObjeC1.*A1.IocObjectWithA1.1.ocator(Thread*se1.f>BirrornC1.ass*k1.ass1size_tbyte_coun1.»A1.1.ocatorTypea1.1.ocator,constPreFenceVisitorftpre_fence_visitor)SHARED1.()CKS_REQUIREI)(1.ocks:mitator_IockJ;A1.1.ocatorTypcGetCurrentA1.IocatorOconst(returncurrent-a1.1.ocator-;)A1.1.ocatorTypcGetCurreniNonMovirgA11.ocatorOconstreturncurrent_non_moving_a1.1.ocator_;private:/1.1.ocatortype.A1.IocatorTypecurrent_a1.1.ocator_;constA1.1.ocatorTypecurrent_non_moving_a1.1.ocator);这五个函数定义在文件art/runtime/gc/heap.h6:Heap类的成员函数AI1.OCobjeCt4JA1.IocNonMovab1.eObject中.参数Se1.f描述的是当前线程.k1.ass描述的是要分泥的对软所M的类型,参数num.bytes描述的是要分北的对弦的大小.最后一个参数pre_fence_visitor是一个回调函数,用来在分配时象完成后在当前执行路径中执行初始化操作,例如分配完成一个数组对象,通过该回调函数立即设置数组的大小,这样就可以保证数组对象的完整性和一致性,防止多线程环境下通过加馈来完成相同的操作。Heap类的成反函数A1.1.ocObjectWithA1.1.ocator需要另外,个额外的类型为AIIOCatOrTyPe的卷数来描述分配涔的类里,也就是描述要在物个空间分配对象CA1.1.oMIorTyW是一个枚举类型,它的定义如卜所示,cppviewp1.aincopy在CoDE上查看代码片派生到我的代码片/Differenttypesofa1.1.ocators.enim1.IocatorTypek1.IocatorTypeBuffpPointer,/UseBvmpPointera1.1.ocator,hasentrypoints.kA1.IocatorTypeT1.AB1./UseT1.ABa1.1.ocator,hasentrypoints.kj1.IocatorTypeRosA1.1.oc,/UseRos1.Ioca1.1.ocator,hasentrypoints.k1.IocatorTypeD1.Ha1.1.oc,/Used1.ma1.1.ex:a1.1.ocator,hasentrypoints.kA1.IocatorTypeXMip.i11g,/Specia1.a1.1.ocatorfornon11>.ingobjects,doesn'thaveentrypoints.kA1.IocatorType1.XIS,/1.argeobjectspace,a1.sodoesn,thaveen1.rypints.):这个枚举类型定义在文件/artrunti三<gc1.1.ocatortype,hA1.1.ocatorType一共有六个伯,它In的含义如下所示:kA1.IocatorTypcBuinpPointer:表示在BUITPPointerSPHCR中分配对象.kA1.IocatorTypeT1.AB:我示要在由RUmPPointerSPaCe提供的畿程同同部配缓冲区中分配时象。k1.IocatorTypeRosA1.1.oc:表示要在RoS.M1.ocSPHCo分配对kA1.IocatorTypeD1.Ma1.1.oc:表示要在D1.Ma1.1.ocSPaCe分配对象。kA1.IocatorTypeNonMoving:表示要在卜OnMovingSPHCe分配对象.kA1.IocaiorTypc1.OS:表示要在1.argCObjectSPaCC分配时象。Heap类的成员函数A1.1.ocObject和A1.IocNonMovab1.eObject使用的分配器类型分别是由成员变量currenta1.1.ocatorcurrentnonmoving_a1.1.ocator决定的前者的(ft与当前使用的GC类型有关当GC类型发生变化时,就会调用HeaP类的成员函数ChangeCoueCIor来修改当前使用的GC,【可时也会调用月外一个成员函数ChangoA1.1.ocator来修改Heap类的成员变用current_aI1.ocator的值。由于ART运行时只有一个NonMovingSpace.因此后存的Gi就固定为kA1.IociitorTypoMonMoving.Heap类的成员函数ChangeCoIIeeIor的实现如下所示:cppviewp1.aincopy在CODE上查看代码片派生到我的代码片voidHeap:ChangeCo1.Iector(Co1.IectorTypeco1.1.ectortype)'./TODO:On1.ydothiswitha1.1.三utatorssuspendedtoavoidraces.if(co1.Icc1.oj1.ypc!=co1.1.ector_type_)co1.1.ector_type_=co1.1.ector_type;gc_p1.an_.c1.ear();switch(co1.1.ccior_1.ype_)(casekCo1.IectorTypeCC:/Fa1.1-through.casekCo11ectorTypeMC:/Fa1.!-through.casekCoI1.ectorTypeSS:/Fa1.1.-through.MSekCo1.IoctorTypeGSS:gc_p1.an_.push_back(co1.1.ector:ZkGcTypeFu1.1.);if(use-t1.ab_)ChangeA1.1.ocator(kA1IocatorTypeT1.AB):e1.seChangeAI1.ocator(kAIIocatorTypeBumpPointer):Ibreak;casekCo11ectorTypeHS:(gc_p1.an_.ush_back(co1.1.ector:kGcTypcSticky);gc_p1.an_.pushback(co1.1.ector:ZkGcTypePartia1.);gc_p1.an_.PUSh_back(co1.1.ector:ZkGcTypeFu1.1.):ChangeA1.1.ocator(kVseRosA1.Ioc?kA1.IocatorTypeRosA1.Ioc:kA1IocatorTypeD1.Ma11.oc);break;casekCo11ectorTypoCS:gc_p1.an_.push_back(co1.1.ector:ZkGcTypeSticky);gc_p1.an_.push.back(co1.1.ector:RGcTypePariia1.):gc_p1.an_.push_back(co1.1.ector:ZkGcTypeFu1.1.);ChangeA1.1.ocator(k1.seRos1.Ioc?kA1.IocatorTypeRosA1.1.oc:kA1.IocatorTypeD1.Ma1.1.oc);break;defau1.t:I.OG(FATA1.)«*Unimp1.emented*;这个函数定义在文件imecheap.cc中。从这里我们就可以看到.对于CompactingGa它们使用的分配器类型只可能为kMIocHtorTypE1.AB或ffkA1.IocatorTypeBuiipPointer.取决定HeaP类的成员变质USeIIab_的IftCHCaP类的成员变显USeIIab的默认为fa1.se,但是可以通过ART运行时启动选项-XX:USenAB来设置为true,对于Mark-S谭eepGC来说,它们使用的分配器类型只可能为kA1.IocatorTypcRosA1.1.oc或者1.M1.ocatorTypcD1.Ma1.Ioc.取决于常量k1.cRosA1.Ioc的值。此外,我们还可以看到,根据当前使用的GC不同,Hcap类的成员变呆gc会被设置为不同的侑,用来衣示在分配对象过程中遇到内存缺乏时,应该执行的GC粒度,对于CgPHCIiMGC来说,只有一种GC粒度可执行那就是kGcTypeFu1.1.实际上就是说对BumpPointerSpace的所有不可达对望进行回收.时干北nkSweepGC来说,有三种GC粒度可执行,分别是IcGcTypeSticky、kGcTypePartia1.R1.kGcTypeFu1.1.这三者的含义可以卷考前面一文。后面我们继续对象分配过程时,也可以荷到HCaI)类的成员变疑gc1.an_的用途。Heap类的成员函数ChIIngc1.1.ocator的实现如下所示:cppviewp1.aincopy在CoDE上查看代码片派生到我的代码片voidHeap:ChangcA1.Iocator(A1.IocatorTypca1.1.ocator)if(current_a1.1.ocator-!=a1.1.ocator)(current_a1.1.ocator=a1.1.ocator;Mutex1.-ockmu(nu1.1.ptr,*1.x)cks:runti三<?shutdownIockJ;SetQuickA1.IocEntryPointsA1.Iocator(currenta1.1.ocatorJ;这个函数定义在文件ime/gc/heap.CC中。Heap类的成员函数ChangeA1.1.ocator除了设置成员变!currenta1.1.ocator的值之外,还会调用函数SetQuickA1.IocEntryPointsA1.1.ocator来修改提供应NativeCode的用来分配对象的入口点函数以便NativeCOdo可以在ART运行时切换GC时使用正常的接口来分泥时缸这里所谓的NativeCode,就是APK在安装时通过附译DEX字节码得到的本地机器指令。了解了分配器的类型之后,接下来我们就继续分析HaP类的成员函数A1.1.。CObjUcIWithAuoCatOr的实现,如下所示:cppviewp1.aincopy在CoDE上查看代码片派生到我的代码片temp1.ate<boo1.kInstrunented,b1.kCheck1.argeObject,typenamePreFenceVisitor>in1.ine三irror:Object*Heap:A1IocObjectWithA1.1.ocator(Thread*se1.f,mirror:C1.ass*k1.ass.sizebyte_count,A1.IocatorTypea1.1.ocator,constPreFenccVisi1.oripre_fence-visi1.or)if(kCheck1.arge()bject&&IN1.IKEI.Y(ShouId1Ioc1.argeObject(k1ass,byte_count)returnA11Oc1.argeObject<kInstru三ente<J.PreFenceVisitor>(se1.f,k1.ass,byte_count,prc_fence_visitor):)mirror:Object*obj;if(a1.1.ocator=kA1.Ioca1.orTypeT1.AB)byte_count-Round1.Ip(byte_count,space:BumpPointerSpace:kA1.ignment):)if(a1.1.ocator=kA1.1.ocatorTy>eT1.AB&&byte.count<=se1.f->T1.abSize()obj=sc1.f->A1.IocT1.ab(by1.e_count);obj->SetC1.ass(k1ass);pre_fence-visitor(bj>USab1.c_SiZC);)e1.se(obj=TryToA1.1.ocate<k1.nstrumente<i,fa1.se>(se1.f,a1.1.ocator,byte_count.&!>ytes_a1.1.ocated,&usab1.c_sizc):if(UN1.IKE1.Y(obj=nu1.1.ptr)boo1.is_current_a1.1.ocator=a1.1.ocator=GetCurrentA1.IocatorO;obj=A1.IocateInterna1.WithGc(se1.f,a1.1.ocator,byte_count.ftby1.es_a1.1.ocated,&usab1.e_size,Sk1.ass):if(obj=nu1.1.ptr)boo1.after_is_current_a1.1.ocator=a1.1.ocator=GetCurrentA1.1.ocator();/Ifthereisapendingexception,fai1thea1.1.ocationrightawaysincethenextone/cou1.dcauseOOMandaborttheruntime.if(!se1f->IsExceptionPendingO&&is_current_a1.1.ocator&&!after_is_current,a1.1.ocator)(/Ifthea1.1.ocatorchanged,weneedtorestartIhQa1.1.ocation.returnA11oc0bject<kInstrumented>(se1f.k1.ass,byte_count,pre_fence_visitor);returnnu1.1.ptr;obj->SetC1.ass(k1.ass);pre_fence_visitor(obj,usab1.e_size);if(1.IocatorIIasA1.IocationStack(a1.1.ocator)(PushOnA1.IocationStack(seif.&obj):if(1.IocatorMay1.1.aveConcurrentGC(a1.1.ocator)4IsGcConcurrent()(CheckConcurrenttC(se1.f,newnum_bytes_a1.1.ocated.&obj);returnobj;这个函数定义在文件art/runtime/gc/heap-ini.h中。HCHP类的成员由数A1.1.ocObjectUiIhA1.1.ocator分配对象的主要遗辛t如图2所示:由2AJ1.OCobjeCtWi1.hA1.1.OCatO硼刑象过程首先,如果模桢参数kCheck1.rgeObject等于true,并且要分泡的是一个黑子类型数组,且该为数组的大小大于预先设汽的伯,那么忽略抻参数a1.1.ocator,而是调用HeaP类的另外一个成见函数A1.IoC1.argeObjeCt直接在1.argeObjectSpace中分配内存。后一个条件是通过调用Heap类的成员由数ShouIdA1.1.Oc1.arxeObjec1来判断是否满足的它的实现如下所示,cppviewp1.aincopy在CODE上St看代码片派生到我的代码片in1.inebo1.Heap:Shou1.dA1.Ioc1.arKcObjcct(三irror:C1.ass*c,SiZejbyte_CoUnI)const(/Weneedtohaveazygotespaceore1.seournew1.ya1.1.ocated1.argeobjectcanendupinthe/Zygoteresu1.tinginitbeingPreBatUreIyfreed./Wecanon1.ydothisforPriiIi1.iVeobjectssince1.argeobjectswi1.1.notbewithinthecardtab1.e/range.Thisa1.soeansthatwere1.yonSe1.C1.assnot.dirtyingtheobject'scard.returnbytecount>=Iarge_ObjeCtthresho1.d_&&c->IsPrimitiveArrayO:)这个函数定义在文件artrn<imecheap-in1.h中。HeaP类的成员变呆IarKCObjCC1.Ihreshu1.d.初始化为kDcfau1.1.1.arcObjec1.Thres1.)1.d,后者又定义为3个内存页大小.也就是说,当分配的原子类型数组大小大干等干3个内存页时,就在1.QrgeObjeCtSPaCe中进行分配.回到HCaP类的成员A1.IocObjectriIhA1.1.ocatorM1.如果指定了要在当前ART运行时线程的T1.AB中分配对望,并且这时候当前ART运行时线程的TI.AB的剩余大小大于请求分配的对象大小,那么就宜接在当前线程的T"B中分配.ART运行时线程的T1.AB实际上是来自于BUmPPointerSPaCe上的,后面我们就可以看到这一点,如果上面的条件都不成立,接卜来就调用Heap类的成员函数TryToA1.1.ocate来进行分配了Heap类的成员函数TryToA1.1.ocate会根据参数a1.1.ocator,在指定的Space分配内存,同时会根据第二个模板参数来决定是否要在允许的危围内增加Space的大小限制,以便可以满足分配要求.这里指定HeaP类的成员函数TryToA1.1.ocate的值为fa1.se.就表示现在在不增长Space的大小限制的前提下为对象分配内存.如果Heap类的成员函数TryTo1.M1.ocate不能成功分配到指定大小的内存,那么就35要调用HeaP类的成员函数A1.1.ocateIntenia1.WithGc来先执行必要的GC.再会试分配请求的内存了。如果HeaP类的成员函数AHOCate1.nternaIBithGC也不能成功分配到内存,那就说明是分配失败了.不过有一个例外,那就是ART运行时当前使用分充器类型发生了变化,这种情况就能要正新调用HeaP类的成员函数A1.iocObject重月分配过程,从上面的分析可以知遒,当ART运行时当前使用的GC发牛.切换时,ART运行时当前使用的分配零类型也会随着变化.因此这时候重新调用HeaP类的成员函数RI1.oCobject,就可以使用当前的分配涔来分配对象.假设前面成功分配了到指定的内存,接下来还有两件事情需要做,第一件事情是冏用HeaP类的成员函数A1.1.。CatorHaSAnMationStack判断参数a1.1.oCator指定的分配器是否与ART运行时的AI1.OCaIionStaCk有关。如果有关的话,那么就霰要将刚刚成功分配到的对象通过调用Heap类的成员函数PushOriA1.1.ocationStack压入到ART运行时的AIIoCa1.ionStack中,以便以后可以执行S1.ickyGCC关于StiCkyGC.可以参考前面一文.Heap类的成0函数A1.1.ocatorHasA1.IocationStack的实现如下所示:cppviewp1.aincopy在CODE上查看代码片派生到我的代码片c1.assHeappub1.ic:staticA1.WAY$_1.N1.1.NEboo1.A1.Icx:HtorIIasA1.IocationStackGX1.IcxiatorTypea1.1.ocatortype)returna1.1.ocatortype!-kA1.IocatorTypcBuinpPoin1.er&&a1.Iocatojtype!-k1.IocatorTypeT1.AB:):这个函数定义在文件art/runtimgcheap.h',.前面提到,RRT运行时雄程的T1.AR是来自于BUBPPointerSpace的,而BU1.nDPointerSpace是与CompactingGC相关的,A1.1.ocationStack是与StickyGC相关的,这就意味着CompactingGC不会执行S1.ieky类型的GC第:件W情是调用Heap类的成员函数AI1.OCa1.orHayHaVeCOneurrentGC判断多数a1.1.ocator指定的分配器是否与ConCUrrernGC相关,并且当前使用的GC就是一个ConcunentGG如果条件都成立的话,就调用HCaP类的成员函数CheCkCOnCUrrentGC检查是否需要发起一个ConCUrrentGC请求.Heap类的成仍函数A1.1.OCaIOrUayHaVeConCUrretnGC的实现如下所示:cppviewp1.aincopy在CODE上查看代码片派生到我的代码片c1.assHoappub1.ic:staticR1.WAYS_1N1.1.NEbuo1.1.1.ocatorMayHaveConcurrcntCC(A1.IocatorTypea1.Iocatoitype)(return1.Iocator1.1.as1.1.ocationStack(a1.Iocator_type);):这个函数定义在文件art/runtiBe/gc/heap.h中.Heap类的成员函数A1.IocatorMayHaveConcurrentGC的判断逻辑与上面分析的成员函数A1.IocatorIIasA1.IocationStack是一样的.这就意味着目的提供的CompactingGCff1.5JConcurrentFfJj不过以后是会提供具有Concurrent功能的CcmpactingGC的称为ConcurrentCopyingGC.以上就是HCaP类的成员函数A1.1.ocobjectWithA1.1.ocator的实现,接下来我们鼓续分析Heap类的成员函数TryToA1.1.ocatc和AU(Ka1.C1.n1.CrmiIKi1.Mk:的实现.以便可以更好地了解ART运行时分配对象的过程。这也有利用我们后面分析ART运行时的CompactingGC的执行过程.HeaP类的成员函数TryToA1.1.ocate的实现如下所示:cppviewp1.aincopy在CO1.)E上查看代码片派生到我的代码片temp1.ate<constboo1.k1.nstrumented.const1.)o1.k(Jrow>in1.ine三irror:Object*Heap:TryToA1.1.ocate(Thread*se1.f,A1.1.ocatorTypea1.1.ocator-type,size,a1.Iojsizc,size*bytes_a1.1.ocated,size_t*usab1.e_size)i(a1.Iocator_type!=k1.IocatorTypeTIAB&&UN1.1.KE1.YdsoutOfMeioryOnA1.1.ocation<kGrow>(a1.1.ocator_type,a1.1.oc.size)returnnu1.1.pir:)mirror:Objectret;switch(a1.1.ocator_type)casek.MIocaiorTypeBuinpPoin1.er:DCI1ECK(bump_pointer_space_!=nu1.1.ptr);a1.1.oc_size=RoundUp(a1.Iocsize,space:IBuiipPointerSpace:zk1.ignmont);ret=bump_pointer_space->A1.IocNonvirtua1.a1.Iocsize);if(1.IKE1.Y(ret!=nu1.1.ptr)bytes_a1.1.ocated-1.1.oc_size;usab1.e_size=a1.1.oc_size;break;casekA1.IocatorTypoRosA1.1.oc:if(k1.nstrumented&&CN1.IKE1.Y(running_on_va1.grindJ),/IfrunningonvaIgrind,weshou1.dbeUSinKtheinstrumentedpath.ret二rosa1.1oc_space_->A1Ioc(se1.f,a1.1.oc_size.bytes_a1.1.ocated.usab1.e_size);e1.seDCHECK(!running_on_vaIgrind_);ret=rosa1.1.o<!space_->A1.IocNonvirtuaI(se1.f,a1.1.oc_size,bytes_a1.1.ocated,usab1.e_size);break:casekA1.IocatorTypeD1.Ma1.oc:(if(k1.nstrumented&&UN1.IKE1.Y(running_on_va1grindJ);/Ifrunningonva1.grind,»eshou1.dbeUSinKtheinstru11en1.edpath.ret=d1.ma1.1.oc_space_>A1.1.oc(se1.f,a1.1.oc_size,bytes_a1.1.ocated,usab1.e_size);e1.se(DCHECK(!running_on_vaIgrindJ:ret=d1.na1.1.oc-sace->AI1.ocNonvirtuaI(se1.f,a1.1.oc.size,by1.es_a1.1.ocated,usab1.e-size);break;casekA1.IocatorTypeNonMoving:ret-non_moving_space_>1.Ioc(se1.f,a1.1.oc_size.bytes_a1.1.ocated,usab1.e_size);break;casek.1.IocaiorType1.OS:ret-1.arge_object_space_->A1.Ioc(seif.a1.1.oc-size,bytes_a1.1.ocated,usab1.e_size):/Notethatthebumppointerspacesaren*tnecessariIynextto/theothercontinuousspaces1.ikethenon-三ovinga1.1.ocspaceor/thezygotespace.DCHECK(retnu1.Iptr1.arge_object_space_->Contains(ret);break;MSCkA1.1.ocat.orTypeTI.AB:(DCHECK-1.IGNED(a1.Ioc_size,space:ZBumpPointerSpace:kA1.ignment);if(IW1.IKE1.Y(seIf->T1abSize()<a1.1.oc.size)constsizenew_t1.ab_size=a1.1.oc.sizekDefau1.tT1.BSize;if(IW1.IKE1.Y(IsOutO11!cmoryOnA1.1.oction<kGrow>(a1.1.ocatortype,newt1.absize)(returnnu1.1.ptr;/Trya1.1.ocatinganewthread1.oca1.buffer,ifthea1.Iocaitonfai1.sthespacemustbe/fu1.1.soreturnnu1.1.ptr.if(!bumppointer_space_>11ocNewT1ab(se1f.new_t1.ab_size)(returnnu1.1.ptr;bytes_a1.1.ocated=new_t1.ab_size;e1.se(bytes_a1.1.ocated=O;/Thea1.1.ocationcan,tfai1.ret=se1.f->1.IocT1.ab(a1.1.oc-size);DCHECK(ret!=nu1.1.ptr);*usab1.e_size三a1.1.oc_size;break;defau1.t:1.OG(FT1.)«*Inva1.ida1.1.ocatortype*;ret=nu1.1.ptr;)returnret:这个函数定义在文件art/runtime/gc/heap.h中。Heap类的成员函数TryTUAuOMIe的实现是很直觉的,我们可以通过图3来描述:首先,如果不是指定在当前ART运行时线程的T1.AB中分配对象,并且指定分配的对象大小超出了当前堆的限制,那么就会分配失败,返回一个nu1.1.p1.r指针.接下来,就根据参数a1.1.ocator指定的分配器在不同的Space中分配对象:1 .指定在IkmPpointR1.SpaCB中分配对奴就调用He叩类的成员变址bump_PointerSPnCR_指向的一个BumpPointerSpace对望的成员函数A1.1.ocXcnvirtim1.分配指定大小的内存.2 .指定在RosA1.1.ocSpace中分配对象,就调用Heap类的成员变量rosa1.IOjSPaCe_指向的一个RosA1.1.ocSpace对软的成员函数RI1.OCftA1.1.ocNonvirtua1.分配指定大小的内存.当模板参数k1.nstn三ented的值等于true,并且Heap类的成员变htrunningJInVa1.grind的值等于true时,就调用RosA1.IocSpace类的成员函数A1.1.oc进行分皂。否则的话,就调用R。SA1.1.oCSPaCC类的成员函数MIOCNoaiHUaIJS行分配,从HCaD类的成员变量runningonva1.grird的命令就可以很容易推Bf出,调用ROSAI1.OCSPaCe类的成员函数A1.Ioc分配的内存具有非法内存访问检查功能.在前面一篇文堂中.我们行提到这种内存分