freepeople性欧美熟妇, 色戒完整版无删减158分钟hd, 无码精品国产vα在线观看DVD, 丰满少妇伦精品无码专区在线观看,艾栗栗与纹身男宾馆3p50分钟,国产AV片在线观看,黑人与美女高潮,18岁女RAPPERDISSSUBS,国产手机在机看影片

正文內(nèi)容

dalvik虛擬機垃圾收集過程分析(編輯修改稿)

2025-07-22 06:24 本頁面
 

【文章內(nèi)容簡介】 hread != NULL。 thread = threadnext) { if (thread == self) continue。 /* debugger events don39。t suspend JDWP thread */ if ((why == SUSPEND_FOR_DEBUG || why == SUSPEND_FOR_DEBUG_EVENT) amp。amp。 threadhandle == dvmJdwpGetDebugThread()) continue。 dvmAddToSuspendCounts(thread, 1, (why == SUSPEND_FOR_DEBUG || why == SUSPEND_FOR_DEBUG_EVENT) ? 1 : 0)。 } unlockThreadSuspendCount()。 for (thread = 。 thread != NULL。 thread = threadnext) { if (thread == self) continue。 /* debugger events don39。t suspend JDWP thread */ if ((why == SUSPEND_FOR_DEBUG || why == SUSPEND_FOR_DEBUG_EVENT) amp。amp。 threadhandle == dvmJdwpGetDebugThread()) continue。 /* wait for the other thread to see the pending suspend */ waitForThreadSuspend(self, thread)。 ...... } dvmUnlockThreadList()。 unlockThreadSuspend()。 ...... } 這個函數(shù)定義在文件dalvik/vm/。 在以下三種情況下,當(dāng)前線程需要掛起其它線程: 1. 執(zhí)行GC。 2. 調(diào)試器請求。 3. 發(fā)生調(diào)試事件,如斷點命中。 而且,上述三種情況有可能是同時發(fā)生的。例如,一個線程在分配對象的過程中發(fā)生GC的同時,調(diào)試器也剛好請求掛起所有線程。這時候就需要保證每一個掛起操作都是順序執(zhí)行的,即要對掛起線程的操作進(jìn)行加鎖。這是通過調(diào)用函數(shù)函數(shù)lockThreadSuspend來實現(xiàn)的。 。如果獲取失敗,就表明有其它線程也正在請求掛起Dalvik虛擬機中的線程,包括當(dāng)前線程。每一個Dalvik虛擬機線程都有一個Suspend Count計數(shù),每當(dāng)它們都掛起的時候,對應(yīng)的Suspend Count計數(shù)就會加1,而當(dāng)被喚醒時,對應(yīng)的Suspend Count計數(shù)就會減1。,當(dāng)前線程按照一定的時間間隔檢查自己的Suspend Count,直到自己的Suspend Count等于0。這樣就可以保證每一個掛起Dalvik虛擬機線程的請求都能夠得到順序執(zhí)行。 從函數(shù)lockThreadSuspend返回之后,就表明當(dāng)前線程可以執(zhí)行掛起其它線程的操作了。它首先要做的第一件事情是遍歷Dalvik虛擬機線程列表,并且調(diào)用函數(shù)dvmAddToSuspendCounts將列表里面的每一個線程對應(yīng)的Suspend Count都增加1,但是除了當(dāng)前線程之外。注意,當(dāng)掛起線程的請求是調(diào)試器發(fā)出或者是由調(diào)試事件觸發(fā)的時候,Dalvik虛擬機中的JDWP線程是不可以掛起的,因為JDWP線程掛起來之后,就沒法調(diào)試了。在這種情況下,也不能將JDWP線程對應(yīng)的Suspend Count都增加1。 通過調(diào)用函數(shù)dvmJdwpGetDebugThread可以獲得JDWP線程句柄,用這個句柄和Dalvik虛擬機線程列表中的線程句柄相比,就可以知道當(dāng)前遍歷的線程是否是JDWP線程。同時,通過參數(shù)why可以知道當(dāng)掛起線程的請求是否是由調(diào)試器發(fā)出的或者由調(diào)試事件觸發(fā)的, 注意,在增加被掛起線程的Suspend Count計數(shù)之前。這個鎖的獲取和釋放可以通過函數(shù)lockThreadSuspendCount和unlockThreadSuspendCount完成。 將被掛起線程的Suspend Count計數(shù)都增加1之后,接下來就是等待被掛起線程自愿將自己掛起來了。這是通過函數(shù)waitForThreadSuspend來實現(xiàn)。當(dāng)一個線程自愿將自己掛起來的時候,會將自己的狀態(tài)設(shè)置為非運行狀態(tài)(THREAD_RUNNING),這樣函數(shù)waitForThreadSuspend通過不斷地檢查一個線程的狀態(tài)是否處于非運行狀態(tài)就可以知道它是否已經(jīng)掛起來了。 那么,一個線程在什么情況才會自愿將自己掛起來呢?一個線程在執(zhí)行的過程中,會在合適的時候檢查自己的Suspend Count計數(shù)。一旦該計數(shù)值不等于0,那么它就知道有線程請求掛起自己,因此它就會很配合地將自己的狀態(tài)設(shè)置為非運行的,并且將自己掛起來。例如,當(dāng)一個線程通過解釋器執(zhí)行代碼時,就會周期性地檢查自己的Suspend Count是否等于0。這里說的周期性,實際上就是碰到IF指令、GOTO指令、SWITCH指令、RETURN指令和THROW指令等時。 2. dvmHeapBeginMarkStep 函數(shù)dvmHeapBeginMarkStep用來初始化堆的標(biāo)記范圍和Mark Stack,它的實現(xiàn)如下所示:[cpp] view plain copy 在CODE上查看代碼片派生到我的代碼片bool dvmHeapBeginMarkStep(bool isPartial) { GcMarkContext *ctx = amp。markContext。 if (!createMarkStack(amp。ctxstack)) { return false。 } ctxfinger = NULL。 ctximmuneLimit = (char*)dvmHeapSourceGetImmuneLimit(isPartial)。 return true。 } 這個函數(shù)定義在文件dalvik/vm/alloc/。 在標(biāo)記過程中用到的各種信息都保存一個GcMarkContext結(jié)構(gòu)體描述的GC標(biāo)記上下文ctx中。其中,ctxstack描述的是Mark Stack,ctxfinger描述的是一個標(biāo)記指紋,在遞歸標(biāo)記對象時會用到,ctximmuneLimit用來限定堆的標(biāo)記范圍。 函數(shù)dvmHeapBeginMarkStep調(diào)用另外一個函數(shù)createMarkStack來初始化Mark Stack,它的實現(xiàn)如下所示:[cpp] view plain copy 在CODE上查看代碼片派生到我的代碼片static bool createMarkStack(GcMarkStack *stack) { assert(stack != NULL)。 size_t length = dvmHeapSourceGetIdealFootprint() * sizeof(Object*) / (sizeof(Object) + HEAP_SOURCE_CHUNK_OVERHEAD)。 madvise(stackbase, length, MADV_NORMAL)。 stacktop = stackbase。 return true。 } 這個函數(shù)定義在文件dalvik/vm/alloc/。 函數(shù)createMarkStack根據(jù)最壞情況來設(shè)置Mark Stack的長度,也就是用當(dāng)前堆的大小除以對象占用的最小內(nèi)存得到的結(jié)果。當(dāng)前堆的大小可以通過函數(shù)dvmHeapSourceGetIdealFootprint來獲得。在堆上分配的對象,都是從Object類繼承下來的,因此,每一個對象占用的最小內(nèi)存是sizeof(Object)。由于在為對象分配內(nèi)存時,還需要額外的內(nèi)存來保存管理信息,例如實際分配給對象的內(nèi)存字節(jié)數(shù)。這些額外的管理信息占用的內(nèi)存字節(jié)數(shù)通過宏HEAP_SOURCE_CHUNK_OVERHEAD來描述。 由于Mark Stack實際上是一個Object指針數(shù)組,因此有了上面的信息之后,我們就可以計算出Mark Stack的長度length。Mark Stack使用的內(nèi)存塊在Dalvik虛擬機啟動的時候就創(chuàng)建好的,具體參考前面一文,起始地址位于stackbase中。由于這塊內(nèi)存開始的時候被函數(shù)madvice設(shè)置為MADV_DONTNEED,因此這里要將它重新設(shè)置為MADV_NORMAL,以便可以通知內(nèi)核,這塊內(nèi)存要開始使用了。 Mark Stack的棧頂stacktop指向的是Mark Stack內(nèi)存塊的起始位置,以后就會從這個位置開始由小到大增長。 回到函數(shù)dvmHeapBeginMarkStep中,ctximmuneLimit記錄的實際上是堆的起始標(biāo)記位置。在此位置之前的對象,都不會被GC。這個位置是通過函數(shù)dvmHeapSourceGetImmuneLimit來確定的,它的實現(xiàn)如下所示:[cpp] view plain copy 在CODE上查看代碼片派生到我的代碼片void *dvmHeapSourceGetImmuneLimit(bool isPartial) { if (isPartial) { return hs2heap(gHs)base。 } else { return NULL。 } } 這個函數(shù)定義在文件dalvik/vm/alloc/。 當(dāng)參數(shù)isPartial等于true時,函數(shù)dvmHeapSourceGetImmuneLimit返回的是Active堆的起始位置,否則的話就返回NULL值。也就是說,如果當(dāng)前執(zhí)行的GC只要求回收部分垃圾,那么就只回收Active堆的垃圾,否則的話,就同時回收Active堆和Zygote堆的垃圾。 3. dvmHeapMarkRootSet 函數(shù)dvmHeapMarkRootSet用來的標(biāo)記根集對象,它的實現(xiàn)如下所示:[cpp] view plain copy 在CODE上查看代碼片派生到我的代碼片/* Mark the set of root objects. * * Things we need to scan: * System classes defined by root classloader * For each thread: * Interpreted stack, from top to curFrame * Dalvik registers (args + local vars) * JNI local references * Automatic VM local references (TrackedAlloc) * Associated Thread/VMThread object * ThreadGroups (could track amp。 start with these instead of working * upward from Threads) * Exception currently being thrown, if present * JNI global references * Interned string table * Primitive classes * Special objects * * Objects in debugger object registry * * Don39。t need: * Native stack (for inprogress stuff in the VM) * The TrackedAlloc stuff watches all native VM references. */ void dvmHeapMarkRootSet() { GcHeap *gcHeap = 。 dvmMarkImmuneObjects(gcHeap)。 dvmVisitRoots(rootMarkObjectVis
點擊復(fù)制文檔內(nèi)容
黨政相關(guān)相關(guān)推薦
文庫吧 www.dybbs8.com
備案圖片鄂ICP備17016276號-1