版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、罢ART运行昂时垃圾收集搬(GC)过翱程分析扮ART运行拔时与Dal拌vik虚拟扳机一样,都蔼使用了Ma鞍rk-Sw白eep算法背进行垃圾回背收,因此它鞍们的垃圾回阿收流程在总败体上是一致绊的。但是A邦RT运行时俺对堆的划分胺更加细致,氨因而在此基懊础上实现了霸更多样的回艾收策略。不隘同的策略有把不同的回收凹力度,力度罢越大的回收昂策略,每次斑回收的内存敖就越多,并埃且它们都有鞍各自的使用扮情景。这样肮就可以使得把每次执行G艾C时,可以摆最大限度地半减少应用程敖序停顿。本半文就详细分爸析ART运耙行时的垃圾隘收集过程。笆ART运行背时的垃圾收背集收集过程袄如图1所示盎:拜图1的最上邦面三个箭头
2、蔼描述触发G霸C的三种情捌况,左边的隘流程图描述八非并行GC笆的执行过程矮,右边的流鞍程图描述并挨行GC的执俺行流程,接扳下来我们就肮详细图中涉柏及到的所有艾细节。办o。班 佰 在前耙面一文中,版我们提到了袄两种可能会触发GC的拔情况。第一瓣种情况是没芭有足够内存暗分配请求的凹分存时,会半调用Hea罢p类的成员碍函数Col颁lectG班arbag碍eInte班rnal触半发一个原因罢为kGcC岸auseF皑orAll凹oc的GC柏。第二种情芭况下分配出爸请求的内存拜之后,堆剩板下的内存超佰过一定的阀斑值,就会调稗用Heap吧类的成员函爸数Requ爱estCo凹ncurr安entGC拌请求执行一
3、癌个并行靶GC。袄d。摆 版 He稗ap类的成胺员函数Re捌quest岸Concu芭rrent昂GC的实现霸如下所示:八1。翱cpp癌 view绊 plai班n cop捌y 在CO癌DE上查看柏代码片派生阿到我的代码肮片斑W。靶void 胺Heap:拜:Requ案estCo搬ncurr昂entGC吧(Thre碍ad* s佰elf) 吧 隘J。袄 / 巴Make 盎sure 扮that 盎we ca耙n do 啊a con败curre案nt GC把. 唉r。伴 Run靶time*八 runt芭ime =俺 Runt懊ime:绊Curre拔nt();安 班E。绊 DCH碍ECK(c瓣oncur阿r
4、ent_耙g敖c_); 笆 芭 if 板(runt皑ime =绊= NUL佰L | 柏!runt百ime-蔼IsFin跋ished阿Start背ing()罢 | 办y。拔 扮 !run巴time-靶IsCo吧ncurr摆entGc班Enabl扳ed()稗 唉9。柏 r俺eturn颁; 氨 M翱utexL跋ock m爸u(sel办f, *L翱ocks:芭:runt皑ime_s摆hutdo白wn_lo暗ck_);巴 白z。般 i矮f (ru爸ntime敖-IsS胺hutti百ngDow暗n() 板 皑G。扳 疤 retu败rn; 傲 案 澳 if 碍(self澳-IsH拌andli斑ngSta艾c
5、kOve哀rflow唉() 袄 拔s。啊 r俺eturn挨; 百 / 搬We al颁ready巴 have巴 a re扒quest案 pend隘ing, 肮no re败ason 奥to st笆art m奥ore u俺ntil 癌we up矮date 哀 袄c。跋 / 扮concurrent拌_star柏t_byt奥es_. 板 昂 con霸curre百nt_st挨art_b岸ytes_敖 = st挨d:nu罢meric扳_limi柏ts昂:max靶(); 澳3。 俺 JNI爸Env* 班env =扮 self哀-Get般JniEn背v(); 斑 傲O。扳 DCH班ECK(W笆ellKn暗own
6、Cl皑asses吧:jav肮a_lan扳g_Dae鞍mons 佰!= NU敖LL); 靶 盎g。百 DCH坝ECK(W芭ellKn袄ownCl爱asses艾:jav吧a_lan胺g_Dae蔼mons_暗reque笆stGC 叭!= NU挨LL); 拜 鞍e。绊 env稗-Cal哎lStat俺icVoi捌dMeth哀od(We凹llKno唉wnCla背sses:熬:java斑_lang班_Daemons, 伴 哎6。败 凹 鞍 澳 般 办 We疤llKno八wnCla熬sses:靶:java斑_lang安_Daem跋ons_r跋eques笆tGC);蔼 芭v。阿 CHE佰CK(!e岸nv-E隘x
7、cept澳ionCh靶eck()隘); 疤 笆 唉这个函数定埃义在文件a挨rt/ru奥ntime百/gc/h柏eap.c安c。芭B。碍 懊 只有满俺足以下四个暗条件,He耙ap类的成昂员函数Re胺quest扒Concu挨rrent版GC才会触版发一个并行挨GC:柏5。挨 佰 1. 佰ART运行艾时已经启动耙完毕。吧 盎 2. 隘ART运行哀时支持并行八GC。AR熬T运行时默矮认是支持并吧行GC的,袄但是可以通鞍过启动选项斑-Xgc来昂关闭。芭Y。艾 拜 3. 胺ART运行奥时不是正在捌关闭。爱 癌 4. 矮当前线程没版有发生栈溢捌出。版 啊 上述4拜个条件都满败足之后,H案eap类的矮成员函数
8、鞍Reque绊stCon白curre佰ntGC就熬将成员变量罢concu吧rrent拜_star氨t_byt耙es_的值背设置为类型昂size_白t的最大值巴,表示目前唉正有一个并唉行GC在等埃待执行,以斑阻止触发另扒外一个并行霸GC。版x。佰 敖 最后,佰Heap类背的成员函数碍Reque芭stCon矮curre癌ntGC调叭用Java暗层的jav笆a.lan安g.Dae板mons类八的静态成员阿函数req叭uestG八C请求执行芭一次并行G肮C。Jav癌a层的ja摆va.la伴ng.Da疤emons瓣类在加载的艾时候,会启凹动五个与堆瓣或者GC相板关的守护线暗程,如下所啊示:版5。哎jav
9、a岸 唉view 芭plain奥 copy巴 在COD氨E上查看代鞍码片派生到阿我的代码片埃k。翱publi坝c fin霸al cl败ass D绊aemon颁s 坝 .爸.吧 吧 p把ublic敖 stat斑ic vo伴id st氨art()岸 癌 哀 Re柏feren隘ceQue隘ueDae鞍mon.I爱NSTAN鞍CE.st芭art()摆; 碍k。拜 案 Fi白naliz爱erDae跋mon.I捌NSTAN拔CE.st哀art()背; 按K。靶 颁 Fi按naliz矮erWat八chdog哀Daemo皑n.INS昂TANCE罢.star唉t(); 吧 捌g。办 拔 He稗apTri霸mme
10、rD扮aemon哀.INST把ANCE.佰start岸(); 挨Q。昂 败 GC百Daemo巴n.INS白TANCE暗.star岸t(); 疤 白 把 白 .拜.昂 板 般 这个类搬定义在文件半libco霸re/li岸bart/般src/m拔ain/j霸ava/j癌ava/l癌ang/D板aemon疤s.jav袄a中。安4。笆 埃 这五个胺守护线程分吧别是:暗 碍 1. 跋Refer班enceQ霸ueueD盎aemon搬:引用队列扮守护线程。扮我们知道,败在创建引用败对象的时候把,可以关联啊一个队列。百当被引用对熬象引用的对瓣象被GC回爸收的时候,疤被引用对象埃就会被加入疤到其创建时氨关联的队
11、列笆去。这个加跋入队列的操胺作就是由R胺efere碍nceQu坝eueDa搬emon守斑护线程来完熬成的。这样八应用程序就坝可以知道那袄些被引用对班象引用的对绊象已经被回笆收了。隘f。 拌 2. 叭Final班izerD扮aemon斑:析构守护班线程。对于按重写了成员艾函数fin岸alize颁的对象,它叭们被GC决暗定回收时,绊并没有马上霸被回收,而昂是被放入到俺一个队列中罢,等待Fi敖naliz癌erDae鞍mon守护拜线程去调用版它们的成员佰函数fin拔alize安,然后再被艾回收。靶R。啊 肮 3. 办Final碍izerW哀atchd板ogDae俺mon:析巴构监护守护笆线程。用来皑监
12、控Fin按alize拌rDaem笆on线程的把执行。一旦挨检测那些重半定了成员函邦数fina搬lize的傲对象在执行把成员函数f暗inali奥ze时超出百一定的时候扒,那么就会笆退出VM。肮F。埃 哎 4. 搬HeapT办rimme扮rDaem靶on:堆裁拌剪守护线程稗。用来执行邦裁剪堆的操按作,也就是斑用来将那些凹空闲的堆内敖存归还给系搬统。啊R。佰 八 5. 安GCDae伴mon:并笆行GC线程澳。用来执行巴并行GC。摆 碍 Jav熬a层的案java.耙lang.颁Daemo哀ns类的静柏态成员函数鞍reque捌stGC被挨调用时,就搬会唤醒上述暗的并行GC傲线程,然后袄这个并行G疤C线程
13、就会敖通过JNI俺调用Hea艾p类的成员罢函数Con半curre岸ntGC,班它的实现如疤下所示:拌n。瓣cpp岸 view扒 plai皑n cop埃y 在CO霸DE上查看坝代码片派生案到我的代码鞍片吧f。疤void 盎Heap:按:Conc罢urren耙tGC(T肮hread肮* sel吧f) 疤 扳T。 坝 M爱utexL靶ock m蔼u(sel柏f, *L矮ocks:安:runt昂ime_s邦hutdo吧wn_lo俺ck_);搬 袄i。俺 扮 if 背(Runt半ime:案Curre吧nt()-百IsSh靶uttin颁gDown捌() 懊 巴D。翱 白 retu瓣rn; 俺 稗 邦 /
14、扳Wait 昂for a爸ny GC班s cur邦rentl百y run盎ning 耙to fi埃nish.哎 邦j。凹 if 扳(Wait芭ForCo按ncurr般entGc八ToCom哎plete稗(self颁) = 扮colle绊ctor:瓣:kGcT霸ypeNo昂ne) 碍 班w。翱 C半ollec哎tGarb吧ageIn摆terna俺l(nex阿t_gc_矮type_八, kGc艾Cause芭Backg熬round般, fal霸se); 哎 胺9。 瓣 吧 佰这个函数定啊义在文件a跋rt/ru拔ntime般/gc/h艾eap.c盎c中。白h。柏 百 只要昂ART运行疤时当前不是扮处于
15、正在关颁闭的状态,敖那么Hea霸p类的成员半函数Con啊curre按ntGC就啊会检查当前芭是否正在执昂行GC。如伴果是的话,挨那么就等待柏它执行完成斑,然后再调背用Heap肮类的成员函伴数Coll碍ectGa艾rbage矮Inter摆nal触发凹一个原因为碍kGcCa摆useBa拌ckgro笆und的G斑C。否则的啊话,就直接盎调用Hea靶p类的成员函数Col白lectG耙arbag吧eInte耙rnal触扮发一个原因版为kGcC熬auseB氨ackgr八ound的伴GC。芭i。熬 按 从这靶里就可以看稗到,无论是稗触发GC的昂原因是kG艾cCaus爸eForA斑lloc,拔还是kGc搬Ca
16、use般Backg伴round拔,最终都是捌通过调用H哎eap类的翱成员函数C斑ollec佰tGarb拔ageIn凹terna啊l来执行G癌C的。此外哎,还有第三斑种情况会触扳发GC,如扳下所示:败4。啊cpp爱 view扒 plai碍n cop芭y 在CO澳DE上查看搬代码片派生爱到我的代码芭片昂a。哎void 半Heap:班:Coll隘ectGa版rbage坝(bool芭 clea岸r_sof扮t_ref背erenc拌es) 半 坝1。般 / 败Even 哀if we肮 w靶aited办 for 邦a GC 拔we st癌ill n埃eed t霸o do 版anoth捌er GC啊 sin
17、c哎e wea吧ks al把locat阿ed du瓣ring 败the 败W。翱 / 跋last 唉GC wi摆ll no艾t hav肮e nec挨essar暗ily b柏een c扮leare坝d. 爱1。 Thr癌ead* 背self 巴= Thr澳ead:笆Curre哎nt();懊 傲e。胺 Wai柏tForC叭oncur百rentG稗cToCo办mplet暗e(sel唉f); 爱W。奥 Col伴lectG艾arbag柏eInte霸rnal(唉colle班ctor:拜:kGcT板ypeFu败ll, k芭GcCau凹seExp盎licit挨, cle蔼ar_so拔ft_re安feren鞍c
18、es);百 版w。 扒 败 坝这个函数定拔义在文件a啊rt/ru般ntime坝/gc/h癌eap.c败c。碍G。把 昂 当我傲们调用Ja瓣va层的j癌ava.l板ang.S跋ystem奥的静态成员疤函数gc时巴,如果AR翱T运行时支拔持显式GC把,那么就它矮就会通过J矮NI调用H岸eap类的跋成员函数C巴ollec唉tGarb肮ageIn隘terna岸l来触发一傲个原因为k矮GcCau熬seExp八licit安的GC。A蔼RT运行时扒默认是支持办显式GC的板,但是可以鞍通过启动选鞍项-XX:版+Disa鞍bleEx懊plici芭tGC来关扳闭。凹7。案 搬 从上耙面的分析就岸可以看出,唉ART
19、运行肮时在三种情隘况下会触发按GC,这三斑种情况通过傲三个枚举k懊GcCau澳seFor案Alloc靶、kGcC百auseB暗ackgr跋ound和八kGcCa埃useEx办plici邦tk来描述胺。这三人枚吧举的定义如芭下所示:鞍g。cpp爸 view皑 plai佰n cop芭y 在CO奥DE上查看敖代码片派生八到我的代码唉片袄Z。盎/ Wh把at ca胺used 拔the G板C? 昂enum 埃GcCau靶se 皑 班 / 碍GC tr爱igger吧ed by扮 a fa拔iled 背alloc柏ation般. Thr半ead d疤oing 阿alloc俺ation爸 is b昂lock
20、e澳d wai艾ting 邦for G暗C bef邦ore 白J。颁 / 跋retry芭ing a坝lloca吧tion.邦 捌 kGc氨Cause颁ForAl坝loc, 吧 挨 / 案A bac版kgrou阿nd GC哎 tryi蔼ng to哀 ensu叭re th斑ere i皑s fre瓣e mem翱ory a皑head 艾of al盎locat矮ions.肮 按5。笆 kGc版Cause懊Backg靶round芭, 翱 / 埃An ex扳plici把t Sys巴tem.g笆c() c坝all. 芭 百N。拔 kGc八Cause白Expli哀cit, 搬 ; 吧 懊 这三个捌枚举定义在阿文
21、件ar唉t/run暗time/蔼gc/he斑ap.h中懊。霸P。岸 肮 从上面般的分析还可跋以看出,A吧RT运行时版的所有GC奥都是以He班ap类的成翱员函数Co挨llect耙Garba袄geInt靶ernal氨为入口,它邦的实现如下拔所示:袄4。爸cpp耙 view罢 plai案n cop扒y 在CO翱DE上查看挨代码片派生岸到我的代码蔼片败a。瓣colle稗ctor:碍:GcTy败pe He肮ap:C挨ollec鞍tGarb背ageIn澳terna耙l(col坝lector:Gc矮Type 矮gc_ty埃pe, G俺cCaus叭e gc_班cause爱, 捌x。版 艾 佰 背 巴 白 哀
22、阿 芭 碍 b敖ool c岸lear_班soft_办refer案ences氨) 罢 Thr白ead* 般self 芭= Thr翱ead:颁Curre隘nt();案 跋Q。矮 .肮. 俺 / 隘Ensur芭e the柏re is扮 only艾 one 败GC at唉 a ti啊me. 唉W。伴 boo癌l sta爸rt_co版llect扮 = fa俺lse; 啊 爱 whi哎le (!暗start捌_coll哎ect) 办 芭 佰 澳 哀 Mute安xLock邦 mu(s艾elf, 暗*gc_c芭omple拜te_lo八ck_);半 背E。岸 胺 if (白!is_g疤c_run凹ning_办)
23、 百 邦 is肮_gc_r哎unnin跋g_ = 霸true;绊 阿 扮 st般art_c靶ollec佰t = t半rue; 凹 凹 颁 爱 胺 板 i邦f (!s佰tart_百colle碍ct) 办 傲 巴 / T爱ODO: 俺timin斑glog 罢this.岸 般 邦 Wait爸ForCo袄ncurr艾entGc八ToCom皑plete背(self鞍); 翱s。笆 笆 .奥. 矮 疤 哎 .盎. 班 if 摆(gc_t爸ype =安= col拔lecto蔼r:kG佰cType翱Stick哎y & 靶 把x。邦 叭 allo拌c_spa鞍ce_-肮Size(半) Is胺Concu稗rren
24、t芭() =哎 conc叭urren拔t_gc_巴 & c案ur_co版llect靶or-G板etGcT芭ype()盎 = g罢c_typ袄e) 俺 啊d。爱 盎 coll靶ector拌 = cu坝r_col背lecto按r; 扮 艾 brea凹k; 蔼 案 坝 .板. 坝 col颁lecto唉r-cl半ear_s半oft_r斑efere伴nces_案 = cl霸ear_s叭oft_r凹efere柏nces;办 埃u。按 col班lecto靶r-Ru奥n(); 扮 背 .绊. 熬 岸 Mute爸xLock艾 mu(s八elf, 奥*gc_c八omple版te_lo懊ck_);阿 奥L。叭 般
25、is_g稗c_run凹ning_佰 = fa扳lse; 鞍 笆 绊 last百_gc_t鞍ype_ 凹= gc_稗type;袄 稗 俺 / W绊ake a扒nyone岸 who 瓣may h把ave b罢een w伴aitin扮g for叭 the 案GC to佰 comp芭lete.疤 扒R。拜 霸 gc_c八omple拌te_co阿nd_-版Broad巴cast(爸self)蔼; 拜j。 板 .案. 昂 ret俺urn g坝c_typ隘e; 案 叭 稗这个函数定翱义在文件a奥rt/ru唉ntime扮/gc/h挨eap.c凹c。捌b。氨 疤 参数皑gc_ty瓣pe和gc霸_caus捌e分别用
26、来霸描述要执行傲的GC的类挨型和原因,哀而参数cl靶ear_s啊oft_r爱efere疤nces用敖来描述是否吧要回收被软奥引用对象引蔼用的对象。爱L。盎 柏 He凹ap类的成瓣员函数Co矮llect班Garba把geInt翱ernal阿的执行逻辑摆如下所示:埃k。澳 艾 1.办 通过一个搬while扮循环不断地把检查Hea唉p类的成员盎变量is_艾gc_ru凹nning岸_,直到它肮的值等于f扳alse为耙止,这表示俺当前没有其百它线程正在扳执行GC。败当它的值等艾于true拔时,就表示芭在其它线程拔正在执行G般C,这时候盎就要调用H艾eap类的俺成员函数W拔aitFo柏rConc唉urre
27、n胺tGcTo艾Compl埃ete等待隘其执行完成白。注意,在拜当前GC执袄行之前,H艾eap类的蔼成员变量i稗s_gc_板runni跋ng_会被唉设置为tr拌ue。佰B。碍 阿 2.癌 如果当前蔼请求执行的柏GC的类型翱为kGcT盎ypeSt敖icky,绊但是当前A坝lloca佰tion 矮Space班的大小小于稗Heap类版的成员变量版min_a艾lloc_爱space懊_size案_for_埃stick百y_gc_阿指定的阀值把,那么就改盎为执行类型伴为kGcT啊ypePa巴rtial蔼。关于类型凹为kGcT懊ypeSt佰icky的昂GC的执行按限制,可以参数前面一疤文。凹P。半 凹 3
28、.耙 从Hea搬p类的成员摆变量mar板k_swe扳ep_co吧llect哎ors_指跋向的一个垃啊圾收集器列肮表找到一个敖合适的垃圾吧收集器来执癌行GC。从碍前面一文可版以知道,A翱RT运行时澳在内部创建班了六个垃圾八收集器。这巴六个垃圾收集器分为两吧组,一组支氨持并行GC氨,另一组不耙支持。每一安组都是由三拜个类型分别翱为kGcT搬ypeSticky、鞍kGcTy澳pePar安tial和白kGcTy扒peFul肮l的垃垃圾邦收集器组成笆。这里说的笆合适的垃圾颁收集器,是伴指并行性与哎Heap类摆的成员变量扳concu澳rrent岸_gc_一拜致,并且类百型也与参数岸gc_ty班pe一致的背
29、垃圾收集器吧。叭W。暗 盎 4.安 找到合适背的垃圾收集扮器之后,就皑将参数cl摆ear_s拔oft_r盎efere澳nces的靶值保存它的哀成员变量c摆lear_肮soft_敖refer哎ences安_中,以便把可以告诉它俺要不要回收霸被软引用对疤象引用的对办象,然后再扮调用它的成背员函数Run来执行G肮C。挨g。隘 背 5.板 GC执行啊完毕,将H癌eap类的芭成员变量i鞍s_gc_坝runni按ng_设置扳为fals佰e,以表示傲当前GC已凹经执行完毕安,下一次请败求的GC可扮以执行了。碍此外,也会柏将Heap巴类的成员变拜量last阿_gc_t懊ype_设绊置为当前执安行的GC的稗类型
30、。这样案下一次执行熬GC时,就矮可以执行另斑外一个不同癌类型的GC鞍。例如,如百果上一次执八行的GC的班类型为kG柏cType蔼Stick板y,那么接拔下来的两次安GC的类型背就可以设置袄为kGcT芭ypePa扒rtial叭和kGcT耙ypeFu罢ll,这样扮可以使得每袄次都能执行叭有效的GC拜。袄U。哎 八 6.傲 通过He拌ap类的成跋员变量gc埃_comp敖lete_邦cond_案唤醒那些正哎在等待GC耙执行完成的柏线程。鞍o。版 坝 在办上面的六个唉步骤中,最扳重要的就是按第四步了。邦从前面一文敖可以知道,稗所有的垃圾鞍收集器都是瓣从Garb半ageCo碍llect版or类继承翱下来的
31、,因背此上面的第矮四步实际上澳执行的是G扒arbag熬eColl背ector奥类的成员函八数Run,奥它的实现如坝下所示:澳C。巴cpp鞍 view隘 plai胺n cop昂y 在CO吧DE上查看稗代码片派生隘到我的代码袄片伴2。拜void 柏Garba耙geCol扮lecto跋r:Ru跋n() 埃 扒 Thr拔eadLi耙st* t搬hread拔_list哎 = Ru蔼ntime袄:Cur蔼rent(奥)-Ge扳tThre奥adLis爸t(); 霸 拔S。皑 uin罢t64_t耙 star爸t_tim肮e = N背anoTi唉me();巴 拌Z。耙 pau扮se_ti翱mes_.邦clear
32、白(); 唉 dur巴ation敖_ns_ 捌= 0; 隘 皑 Ini澳tiali绊zePha肮se();叭 摆 if 岸(!IsC袄oncur翱rent(唉) 邦 绊 /哀/ Pau袄se is坝 the 扳entir埃e len白gth o巴f the背 GC. 拔 翱5。跋 u办int64斑_t pa俺use_s挨tart 颁= Nan败oTime跋(); 背E。安 A案TRACE俺_BEGI阿N(Ap邦plica蔼tion 半threa隘ds su哀spend疤ed);暗 氨U。半 t盎hread袄_list袄-Sus案pendA熬ll();袄 M碍arkin摆gPhas罢e(); 艾
33、 按 R柏eclai翱mPhas昂e(); 八 矮 t吧hread白_list澳-Res把umeAl般l(); 瓣 败 A熬TRACE伴_END(埃); 澳 u氨int64靶_t pa佰use_e斑nd = 爱NanoT耙ime()颁; 瓣m。巴 p板ause_疤times巴_.pus皑h_bac扒k(pau半se_en搬d - p颁ause_伴start霸); 澳i。皑 e佰lse 奥 绊 T叭hread熬* sel爱f = T版hread百:Cur斑rent(白); 傲G。安 隘 霸 拜 Read瓣erMut胺exLoc班k mu(暗self,爱 *Loc佰ks:m班utato氨r_loc
34、背k_); 癌 搬Q。敖 扒 Mark埃ingPh埃ase()拜; 鞍 笆 皑 b稗ool d八one =蔼 fals吧e; 哀 w胺hile 凹(!don扮e) 绊 矮 败 uint凹64_t 蔼pause翱_star矮t = N跋anoTi爸me();绊 艾3。艾 拌 ATRA矮CE_BE般GIN(绊Suspe艾nding半 muta扒tor t搬hread半s); 爱 翱K。蔼 安 thre拔ad_li白st-S摆uspen背dAll(澳); 摆 邦 ATRA般CE_EN颁D(); 颁 凹 搬 ATRA翱CE_BE把GIN(矮All m瓣utato霸r thr耙eads 哎suspe皑n
35、ded绊); 矮V。啊 隘 done艾 = Ha吧ndleD半irtyO搬bject爱sPhas胺e(); 摆 鞍i。搬 澳 ATRA板CE_EN白D(); 笆 笆 白 uint氨64_t 鞍pause巴_end 案= Nan伴oTime俺(); 拌z。扒 翱 ATRA爱CE_BE哎GIN(疤Resum拜ing m安utato鞍r thr盎eads哀); 般3。般 昂 thre伴ad_li挨st-R办esume半All()板; 鞍 傲 ATRA澳CE_EN矮D(); 疤 摆 盎 paus稗e_tim挨es_.push_b碍ack(p暗ause_皑end -百 paus伴e_sta埃rt); 颁
36、 隘X。昂 靶 奥 瓣 罢 敖 Read俺erMut翱exLoc板k mu(胺self,绊 *Loc绊ks:m绊utato扒r_loc吧k_); 捌 芭1。碍 拌 Recl奥aimPh哀ase()疤; 鞍 凹 爱 uin搬t64_t叭 end_安time 瓣= Nan邦oTime颁(); 板T。摆 dur伴ation邦_ns_ 白= end矮_time伴 - st啊art_t肮ime; 盎 把b。 坝 Fin唉ishPh扮ase()安; 叭 把 巴这个函数定佰义在文件a邦rt/ru澳ntime般/gc/c伴ollec白tor/g叭arbag凹e_col班lecto埃r.cc中百。颁T。癌 版
37、Ga八rbage澳Colle俺ctor类唉的成员函数八Run的实爸现就对应于斑图1所示的碍左边和右边捌的两个流程暗。靶e。岸 啊 图1俺所示的左边蔼流程是用来捌执行非并行半GC的,过隘程如下所示笆:拔 隘 1.埃 调用子类版实现的成员叭函数Ini柏tiali叭zePha肮se执行G碍C初始化阶懊段。拌R。拜 芭 2.肮 挂起所有扒的ART运唉行时线程。袄 拔 3.耙 调用子类搬实现的成员凹函数Mar班ki坝ngPha肮se执行G绊C标记阶段案。佰Q。昂 般 4.百 调用子类俺实现的成员把函数Rec盎laimP把hase执吧行GC回收吧阶段。罢j。氨 氨 5.埃 恢复第2邦步挂起的A案RT运行时
38、颁线程。岸 般 6.佰 调用子类隘实现的成员摆函数Fin氨ishPh坝ase执行搬GC结束阶绊段。岸f。瓣 柏 图1凹所示的右边哀流程是用来皑执行并行G霸C的,过程柏如下所示:懊 耙 1.把 调用子类暗实现的成员芭函数Ini俺tiali拔zePha八se执行G敖C初始化阶颁段。肮9。奥 岸 2.背 获取用于啊访问Jav拌a堆的锁。唉 斑 稗 3. 昂调用子类实半现的成员函隘数Mark办ingPh扳ase执行板GC并行标哀记阶段。靶U。邦 拜 4.把 释放用于靶访问Jav瓣a堆的锁。板 鞍 5.爸 挂起所有熬的ART运碍行时线程。吧 安 6.奥 调用子类胺实现的成员般函数Han颁dleDi败rt
39、yOb皑jects把Phase熬处理在GC敖并行标记阶佰段被修改的百对象。爸7。瓣 蔼 7.背 恢复第4版步挂起的A叭RT运行时啊线程。败 捌 8.版 重复第5到第7步,爸直到所有在疤GC并行阶爱段被修改的斑对象都处理稗完成。埃y。瓣 巴 9.哀 获取用于昂访问Jav坝a堆的锁。斑 绊 10瓣. 调用子拔类实现的成般员函数Re跋claim拔Phase捌执行GC回蔼收阶段。熬J。胺 扒 11败. 释放用癌于访问Ja熬va堆的锁叭。把 百 12搬. 调用子巴类实现的成半员函数Fi伴nishP般hase执胺行GC结束疤阶段。袄B。跋 罢 从上盎面的分析就绊可以看出,鞍并行GC和癌非并行GC胺的区别在
40、于安:矮 拌 1.案 非并行G挨C的标记阶翱段和回收阶扳段是在挂住颁所有的AR芭T运行时线哀程的前提下疤进行的,因傲此,只需要傲执行一次标熬记即可。霸e。八 拜 2.搬 并行GC氨的标记阶段拔只锁住了J半a八va堆,因隘此它不能阻办止那些不是坝正在分配对案象的ART皑运行时线程摆同时运行,傲而这些同进稗运行的AR隘T运行时线癌程可能会引唉用了一些在熬之前的标记氨阶段没有被啊标记的对象。如果不对版这些对象进癌行重新标记癌的话,那么八就会导致它百们被GC回碍收,造成错扳误。因此,稗与非并行G扳C相比,并案行GC多了耙一个处理脏背对象的阶段版。所谓的脏罢对象就是我巴们前面说的澳在GC标记阿阶段同时运
41、佰行的ART搬运行时线程斑访问或者修按改过的对象捌。E。办 熬 3.把 并行GC斑并不是自始暗至终都是并靶行的,例如扮,处理脏对阿象的阶段就敖是需要挂起靶除GC线程扮以外的其它拔ART运行哎时线程,这阿样才可以保爱证标记阶段芭可以结束。巴T。凹 氨 从前摆面一文可以按知道,Ga矮rbage艾Colle跋ctor类澳有三个直接伴或者间接的霸子类Mar啊kSwee稗p、Par胺tialM伴arkSw碍eep和S版ticky凹MarkS搬weep都扒可以用来执拔行垃圾回收癌,其中,P袄artia扳lMark按Sweep半类又是从M俺arkSw般eep类直爱接继承下来办的,而St肮ickyM哀arkS
42、w版eep类是奥从Part版ialMa耙rkSwe拔ep类直接瓣继承下来的傲。Mark白Sweep挨类用来回收奥Zygot唉e Spa敖ce和Al扳locat扮ion S把pace的挨垃圾,Pa挨rtial氨Ma败rkSwe澳ep类用来芭回收All蔼ocati肮on Sp伴ace的垃邦圾,Sti斑ckyMa坝rkSwe霸ep类用来扳回收上次G隘C以来在Allcat笆ion S暗pace上芭分配的最终拌又没有被引翱用的垃圾。盎a。柏 唉 接下挨来,我们就把主要分析A八RT运行时白线程的挂起皑和恢复过程柏,以及Ma靶rkSwe叭ep、Pa袄rtial懊MarkS板weep和霸Stick跋yMark
43、摆Sweep傲这三个类是挨执行Ini哎tiali扮zePha巴se、Ma颁rking邦Phase绊、Hand啊leDir坝tyObj白ectsP扳hase、氨Recla埃imPha班se和Fi艾nishP翱hase的按五个GC阶扮段的过程。挨h。矮 唉 1. 氨ART运行懊时线程的挂俺起芭 坝 从上面搬的分析可以爸知道,AR隘T运行时线暗程的挂起是靶通过调用T败hread扒List类办的成员函数坝Suspe熬ndAll哀实现的,如捌下所示:柏s。癌cpp啊 view摆 plai笆n cop澳y 在CO肮DE上查看败代码片派生办到我的代码袄片俺h。背void 板Threa芭dList昂:Sus艾
44、pendA拌ll() 伴 袄B。颁 Thr啊ead* 澳self 班= Thr扒ead:拔Curre蔼nt();埃 岸c。颁 .癌. 爱 M柏utexL稗ock m芭u(sel叭f, *L颁ocks:芭:thre耙ad_li奥st_lo班ck_);板 吧C。哀 败 瓣 爸 Mute盎xLock把 mu2(八self,柏 *Loc昂ks:t班hread岸_susp靶end_c靶ount_挨lock_按); 岸y。邦 扒 / U柏pdate岸 glob叭al su把spend暗 all 叭state扮 for 奥attac靶hing 案threa肮ds. 艾F。扒 熬 +su板spend跋_all
45、_氨count傲_; 半 班 / I胺ncrem搬ent e暗veryb碍odys鞍 susp挨end c般ount 暗(exce奥pt ou傲r own巴). 安i。疤 坝 for 啊(cons靶t aut版o& th败read 皑: lis捌t_) 碍 凹8。绊 扒 if瓣 (thr般ead =斑= sel伴f) 昂 跋 柏 鞍conti邦nue; 败 凹 扮 拌 皑 肮 .般. 跋 拌 吧 th蔼read-叭Modi败fySus暗pendC耙ount(巴self,伴 +1, false柏); 凹l。半 氨 皑 版 案 / 瓣Block案 on t埃he mu碍tator拜 lock靶 u
46、nti暗l all稗 Runn俺able 靶threa昂ds re哎lease肮 thei白r sha岸re of氨 acce哎ss. 敖c。安#if H安AVE_TIMED_盎RWLOC板K / 斑Timeo埃ut if罢 we w叭ait m肮ore t芭han 3坝0 sec捌onds.败 罢m。啊 if 霸(UNLI案KELY(把!Lock捌s:mu绊tator佰_lock艾_-Ex啊clusi颁veLoc盎kWith肮Timeo爸ut(se坝lf, 3挨0 * 1奥000, 埃0) 耙 八R。蔼 U佰nsafe案LogFa板talFo奥rThre颁adSus半pendA耙llTime
47、out(颁self)敖; 拜d。 搬#else安 熬 Loc扮ks:m柏utato爸r_loc安k_-E按xclus叭iveLo暗ck(se傲lf); 坝 稗D。靶#endi罢f 白 .佰. 扒 奥 坝这个函数定柏义在文件a坝rt/ru埃ntime阿/thre啊ad_li氨st.cc百中。背q。凹 绊 所有的坝ART运行绊时线程都保罢存在Thr皑eadLi班st类的成袄员变量li班st_描述凹的一个列表唉,遍历这个盎列表时,需邦要获取Lo盎ck类的成斑员变量th佰read_靶list_啊lock_扳描述的一个氨互斥锁。氨J。凹 哀 Thr唉eadList类有一爸个成员变量邦suspe按nd_a
48、l斑l_cou凹nt_,用斑来描述全局叭的线程挂起案计数器。在翱所有的AR颁T运行时线巴程挂起期间靶,如果有新耙的线程将自唉己注册为A奥RT运行时办线程,那么捌它也会将自皑己挂起来,艾而判断所有捌的ART运行时佰线程是不是背处于挂起期半间,就是通俺过Thre耙adLis奥t类的成员敖变量sus瓣pend_敖all_c稗ount_暗的值是否大扮于0进行的霸。因此,T案hread白List类板的成员函数啊Suspe挨ndAll啊在挂起所有颁的ART运斑行时线程之办前,会将T矮hread斑List类鞍的成员变量癌suspe八nd_al靶l_cou版nt_的值败增加1。癌s。邦 瓣 接下来百,Thre
49、案adLis阿t类的成员安函数Sus岸pendA伴ll遍历所疤有的ART绊运行时线程版,并且调用翱Threa斑d类的成员氨函数Mod艾ifySu板spend邦Count叭将它内部的蔼线程计算数俺器增加1,绊如下所示:袄C。袄cpp啊 view唉 plai啊n cop柏y 在CO澳DE上查看胺代码片派生坝到我的代码版片坝d。隘void 柏Threa柏d:At耙omicS矮etFla绊g(Thr隘eadFl背ag fl唉ag) 拜 哎N。奥 and翱roid_斑atomi邦c_or(澳flag,百 &sta盎te_an按d_fla袄gs_.a伴s_int蔼); 吧Z。 背void 斑Threa艾d
50、:At艾omicC碍learF笆lag(T氨hread扒Flag 熬flag)盎 懊G。摆 and败roid_蔼atomi斑c_and俺(-1 啊 flag爸, &st拌ate_a岸nd_fl哀ag瓣s_.as捌_int)鞍; 搬P。 氨.扮. 佰void 挨Threa疤d:Mo八difyS皑uspen瓣dCoun捌t(Thr扳ead* 罢self,霸 int 盎delta白, boo把l for挨_debu坝gger)案 敖w。癌 .矮. 唉 sus爱pend_耙count傲_ += 稗delta鞍; 熬 .蔼. 盎 if 拜(susp耙end_c氨ount_霸 = 0鞍) 般 A版tomi
51、c蔼Clear翱Flag(佰kSusp吧endRe颁quest搬); 昂S。搬 e岸lse 暗 柏 A耙tomic耙SetFl袄ag(kS败uspen白dRequ捌est);拔 背x。 芭 艾这三个函数昂定义在文件叭art/r邦untim芭e/thr白ead.c绊c中。懊2。罢 癌 Thr霸ead类的懊成员函数M绊odify扮Suspe皑ndCou昂nt的实现搬很简单,它叭主要就是将敖成员变量s坝uspen版d_cou傲nt_的值安增加del背ta,并且败判断增加后班的值是否等袄于0。如果皑等于0,就哀调用成员函搬数Atom般icCle摆arFla搬g将另外一扮个成员变量稗state挨_and
52、_爱flags颁_的int拌值的kSu坝spend艾Reque啊st位清0搬,表示线程拌没有挂起请吧求。否则的拌话,就调用疤成员函数A皑tomic敖SetFl敖ag将成员艾变量sta办te_an盎d_背flags拜_的int值的kSu八spend百Reque佰st位置1斑,表示线程靶有挂起请求百。鞍e。半 扮 回到前绊面Thre颁adLis挨t类的成员傲函数Sus胺pendA吧ll中,全艾局ART运傲行时线程挂白起计数器和八每一个AR碍T运行时线拜程内部的线百程挂起计数岸器的操作都胺是需要在获凹取Lock癌s类的静态耙成员变量t隘hread版_susp俺end_c扒ount_八lock_扮描述
53、的一个扮互斥锁的前绊提下进行的拔。鞍8。啊 奥 最后,拜Threa扒dList颁类的成员函伴数Susp肮endAl邦l通过获取皑Locks佰类的静态成百员变量mu蔼tator班_lock拔_描述的一阿个读写锁的八写访问来等哎待所有的A艾RT运行时俺线程挂起的绊。这是如何哀做到的呢?肮在前面一文颁中,我们提岸到,ART佰运行时提供袄给由DEX鞍字节码翻译翱而来的本地八机器代码使搬用的一个函办数表中,包凹含了一个p八Check柏Suspe颁nd函数指扒针,该函数白指针指向了哎函数Che挨ckSus按pendF奥romCo蔼de。于是胺,每一个A鞍RT运行时隘线程在执行般本地机器代挨码的过程中捌,就
54、会周期翱性地通过调败用函数Ch芭eckSuspend爱FromC佰ode来检澳查自己是否板需要挂起。伴这一点与前懊面一文分析八的Dalv拌ik虚拟机艾线程挂起的佰过程是类似哀的。熬E。岸 函数C氨he霸ckSus哎pendF般romCo氨de的实现拜如下所示:啊cpp伴 view阿 plai捌n cop埃y 在CO邦DE上查看凹代码片派生伴到我的代码癌片罢J。唉void 拔Check百Suspe氨ndFro坝mCode奥(Thre拌ad* t胺hread捌) 艾U。盎 S傲HARED皑_LOCK袄S_REQ拜UIRED盎(Lock案s:mu懊tator笆_lock暗_) 疤 案9。案 .阿.
55、蔼 Che翱ckSus搬pend(啊threa矮d); 背 半 这个函坝数定义在文半件art/颁runti氨me/en斑trypo板ints/佰quick绊/quic耙k_thr捌ead_e半ntryp扮oints颁.cc中。半S。扳 傲 函数C拜heckS背uspen澳dFrom扳Code调靶用另外一个搬函数Che耙ckSus百pend检百查当前线程白是否需要挂瓣起,后者的袄实现如下所板示:癌G。拔cpp扒 view伴 plai斑n cop把y 在CO傲DE上查看安代码片派生坝到我的代码靶片般B。吧stati班c inl扮ine v矮oid C岸heckS矮uspen俺d(Thr澳ead*
56、捌threa奥d) SH碍ARED_阿LOCKS昂_REQU皑IRED(柏Locks扒:mut暗ator_鞍lock_邦) 捌I。翱 for癌 (;)败 俺 癌 if (澳threa叭d-Re哀adFla吧g(kCh跋eckpo百intRequest凹) 阿 翱Q。暗 佰 thre爸ad-R凹unChe矮ckpoi蔼ntFun巴ction奥(); 败b。熬 扳 thre邦ad-A癌tomic拌Clear扒Flag(矮kChec皑kpoin傲tRequ艾est);敖 傲1。盎 埃 else瓣 if (唉threa笆d-Re佰adFla袄g(kSu柏spend矮Reque按st) 扳 靶S。碍 爸
57、 thre稗ad-F跋ullSu颁spend袄Check啊(); 蔼 熬 else哀 鞍 罢 brea邦k; 耙 靶 半 绊 懊这个函数定背义在文件a肮rt/ru把ntime艾/entr板ypoin案ts/en捌trypo袄int_u隘tils.阿h中。澳i。靶 把 从上面鞍的分析可以敖知道,如果坝当前线程的哎线程挂起计澳数器不等于暗0,那么它拜内部的一个斑标记位kS绊uspen案dRequ百est被设霸置为1。这隘时候函数C盎heckS挨uspen佰d就会调用稗Threa爸d类的成员板函数Ful疤lSusp爸endCh绊eck来将挨自己挂起。蔼此外,函数碍Check瓣Suspe鞍nd还会检袄
58、查线程内部昂的另外一个扒标记位kC半heckp碍ointR艾eques氨t是否被设按置为1。如斑果被设置为岸1的话,那俺么就说明线按程有一个C艾heck 挨Point巴需要执行,八这时候就会拌先调用Th吧read类胺的成员函数斑RunCh皑eckpo半intFu跋nctio颁n运行该C扒heck 啊Point败,接着再将搬线程内部的懊标记位kC矮heckp拌ointR案eques柏t清0。关袄于线程的C搬heck 盎Point叭,我们后面隘再分析。氨n。颁 翱 Thr矮ead类的板成员函数F拌ullSu疤spend暗Check熬的实现如下疤所示:颁3。阿cpp伴 view佰 plai疤n co
59、p捌y 在CO拔DE上查看胺代码片派生吧到我的代码拌片跋g。扒void 办Threa坝d:Fu疤llSus笆pendC霸heck(芭) 叭Y。叭 .皑. 暗 / 拌Make 翱threa澳d app盎ear s笆uspen昂ded t懊o oth吧er th捌reads袄, rel矮ease 阿mutat绊or_lo哎ck_. 拜 柏H。板 Tra伴nsiti袄onFro皑mRunn跋ableT案oSusp耙ended皑(kSus跋pende版d); 邦J。矮 / 鞍Trans蔼ition背 back百 to r捌unnab俺le no唉ting 唉reque澳sts t岸o sus疤pend
60、,般 re-a扳cquir碍e sha拌re on埃 muta翱tor_l绊ock_.伴 百S。扒 Tra捌nsiti唉onFro傲mSusp笆ended把ToRun背nable翱(); 罢W。坝 .板. 拔 胺 澳这个函数定叭义在文件a办rt/ru扒ntime把/thre拜ad.cc疤中。俺t。把 罢 Thr白ead类的翱成员函数F啊ullSu隘spend胺Check爸首先是调用靶成员函数T拔ransi伴tionF白romRu叭nnabl稗eToSuspend坝ed将自己肮从运行状态八修改为挂起安状态,接着霸再调用成员白函数Tra凹nsiti凹onFro皑mSusp叭ended笆ToRun斑
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026农业现代化技术应用发展现状前景规划市场研究报告
- 2025新全国中学生物理竞赛核心考点题目及答案
- 2026农业市场潜力行业市场深度调研及发展趋势与投资前景预测研究报告
- 2026中国金属期货技术指标有效性比较研究报告
- 2026中国白银期货市场发展现状及投资潜力分析报告
- 2026-2030中国甲醇行业发展分析及投资风险预警与发展策略研究报告
- 2025年AI情绪调节设备行业市场调研报告数据分析
- 临床股骨颈骨折伴压力性损伤患者的个案查房
- 2026年设备监理师职业资格考试(设备工程质量管理与检验)仿真试题及答案三
- 2026届湖南省湘西土家族苗族自治州古丈县中考猜题历史试卷含解析
- 传承五四精神争做新时代好少年
- 学生违纪处理管理规定细则(2026年新版)
- 职业中学校美发与形象设计专业人才培养方案
- 交管12123驾照学法减分题库500题(含答案)
- 广东佛山市顺德区2024-2025学年八年级物理下册期末试卷(解析版)
- 2026年入团团员知识考试题库100题及答案
- 牛场安全防疫培训课件
- 网络信息茧房的形成机制与破局路径研究毕业答辩
- 消渴目病中医辨证施护体系与临床护理方案
- 化工厂人员定位施工方案
- 2025小学五年级英语阅读理解专项训练50篇
评论
0/150
提交评论