GC析構物件和列表的處理過程
步驟如下:
1.CLR 會判斷當前物件是否包含解構函式,
2.如果包含,則記錄物件的地址到所屬區域下的析構物件列表中
3.在CLR GC的五個階段的標記階段,會判斷物件是否存活為1
4.如果不為1,檢查物件頭中的一直執行解構函式標記是否為1
5.如果為1,則刪除析構物件列表的中的記錄
6.如果不為1,則把析構物件列表中的記錄移動到析構佇列或者重要析構佇列
7.標記析構佇列和重要析構佇列的物件為存活物件,即為1
8.等待被解構函式的呼叫執行緒呼叫它
9.移除析構佇列或者重要析構佇列
10.下一輪GC的回收
**(一)**管理以上的類CFinalize
.Net裡面有些物件包含了解構函式的處理, CLR為了保證這些析構物件的呼叫以及不影響主體GC的分配與回收,在GC_Heap裡面定義了管理析構物件的CFinalize類
class CFinalize
{
#ifdef DACCESS_COMPILE
friend class ::ClrDataAccess;
#endif // DACCESS_COMPILE
friend class CFinalizeStaticAsserts;
private:
//adjust the count and add a constant to add a segment
static const int ExtraSegCount = 2;
static const int FinalizerListSeg = NUMBERGENERATIONS+1;
static const int CriticalFinalizerListSeg = NUMBERGENERATIONS;
//Does not correspond to a segment
static const int FreeList = NUMBERGENERATIONS+ExtraSegCount;
PTR_PTR_Object m_FillPointers[NUMBERGENERATIONS+ExtraSegCount];
PTR_PTR_Object m_Array;
PTR_PTR_Object m_EndArray;
size_t m_PromotedCount;
VOLATILE(int32_t) lock;
#ifdef _DEBUG
EEThreadId lockowner_threadid;
#endif // _DEBUG
BOOL GrowArray();
void MoveItem (Object** fromIndex,
unsigned int fromSeg,
unsigned int toSeg);
inline PTR_PTR_Object& SegQueue (unsigned int Seg)
{
return (Seg ? m_FillPointers [Seg-1] : m_Array);
}
inline PTR_PTR_Object& SegQueueLimit (unsigned int Seg)
{
return m_FillPointers [Seg];
}
BOOL IsSegEmpty ( unsigned int i)
{
ASSERT ( (int)i < FreeList);
return (SegQueueLimit(i) == SegQueue (i));
}
BOOL FinalizeSegForAppDomain (AppDomain *pDomain,
BOOL fRunFinalizers,
unsigned int Seg);
public:
~CFinalize();
bool Initialize();
void EnterFinalizeLock();
void LeaveFinalizeLock();
bool RegisterForFinalization (int gen, Object* obj, size_t size=0);
Object* GetNextFinalizableObject (BOOL only_non_critical=FALSE);
BOOL ScanForFinalization (promote_func* fn, int gen,BOOL mark_only_p, gc_heap* hp);
void RelocateFinalizationData (int gen, gc_heap* hp);
void WalkFReachableObjects (fq_walk_fn fn);
void GcScanRoots (promote_func* fn, int hn, ScanContext *pSC);
void UpdatePromotedGenerations (int gen, BOOL gen_0_empty_p);
size_t GetPromotedCount();
//Methods used by the shutdown code to call every finalizer
void SetSegForShutDown(BOOL fHasLock);
size_t GetNumberFinalizableObjects();
void DiscardNonCriticalObjects();
//Methods used by the app domain unloading call to finalize objects in an app domain
bool FinalizeAppDomain (AppDomain *pDomain, bool fRunFinalizers);
void CheckFinalizerObjects();
};
class CFinalizeStaticAsserts {
static_assert(dac_finalize_queue::ExtraSegCount == CFinalize::ExtraSegCount, "ExtraSegCount mismatch");
static_assert(offsetof(dac_finalize_queue, m_FillPointers) == offsetof(CFinalize, m_FillPointers), "CFinalize layout mismatch");
};
(二)新增到析構物件列表
CFinalize::RegisterForFinalization (int gen, Object* obj, size_t size)
{
CONTRACTL {
NOTHROW;
GC_NOTRIGGER;
} CONTRACTL_END;
EnterFinalizeLock();
// Adjust gen
unsigned int dest = 0;
if (g_fFinalizerRunOnShutDown)
{
//no method table available yet,
//put it in the finalizer queue and sort out when
//dequeueing
dest = FinalizerListSeg;
}
else
dest = gen_segment (gen);
// Adjust boundary for segments so that GC will keep objects alive.
Object*** s_i = &SegQueue (FreeList);
if ((*s_i) == m_EndArray)
{
if (!GrowArray())
{
LeaveFinalizeLock();
if (method_table(obj) == NULL)
{
// If the object is uninitialized, a valid size should have been passed.
assert (size >= Align (min_obj_size));
dprintf (3, ("Making unused array [%Ix, %Ix[", (size_t)obj, (size_t)(obj+size)));
((CObjectHeader*)obj)->SetFree(size);
}
STRESS_LOG_OOM_STACK(0);
if (GCConfig::GetBreakOnOOM())
{
GCToOSInterface::DebugBreak();
}
return false;
}
}
Object*** end_si = &SegQueueLimit (dest);
do
{
//is the segment empty?
if (!(*s_i == *(s_i-1)))
{
//no, swap the end elements.
*(*s_i) = *(*(s_i-1));
}
//increment the fill pointer
(*s_i)++;
//go to the next segment.
s_i--;
} while (s_i > end_si);
// We have reached the destination segment
// store the object
**s_i = obj;
// increment the fill pointer
(*s_i)++;
LeaveFinalizeLock();
return true;
}
相關文章
- SpringMVC請求處理過程原始碼簡析SpringMVC原始碼
- Swift-析構過程Swift
- python中PCA的處理過程PythonPCA
- DOM在Ahooks中的處理過程Hook
- postgresSQL Extended Query執行過程和sharding-proxy的處理SQL
- Python List 列表的處理Python
- Flink流處理過程的部分原理分析
- 【原始碼】Redis命令處理過程原始碼Redis
- 物件轉json字串的過程中對value為null的值的一些處理物件JSON字串Null
- 一次壞塊的處理過程(一)
- 一次壞塊的處理過程(二)
- 【Tomcat】Tomat 處理請求的過程(圖解)Tomcat圖解
- MySQL儲存過程的異常處理方法MySql儲存過程
- fastHttp服務端處理請求的過程ASTHTTP服務端
- MHA高可用架構工作原理?主庫當機處理過程架構
- 物件導向和麵向過程物件
- Ceph pg unfound處理過程詳解
- 大資料的處理是怎樣的過程大資料
- 體會KEIL5資料處理和傳輸過程
- SICP:構造過程抽象--物件導向的解釋抽象物件
- gc buffer busy acquire問題處理GCUI
- 物件導向和麵向過程的區別物件
- nacos2.3 密碼驗證的處理過程密碼
- Linux伺服器被入侵後的處理過程Linux伺服器
- npm install過程失敗的幾種處理方法NPM
- 記一次PMML檔案的處理過程
- nginx 處理客戶端請求的完整過程Nginx客戶端
- (四)SpringBoot啟動過程的分析-預處理ApplicationContextSpring BootAPPContext
- 大資料處理過程是怎樣大資料
- Linux 核心處理中斷全過程解析Linux
- 分析oc物件的記憶體結構及其建立過程物件記憶體
- 物件的使用處理,作用域的和ajax中this的理解物件
- 處理器架構和配置架構
- MPP架構和批處理架構
- Android輸入系統(二)IMS的啟動過程和輸入事件的處理Android事件
- 程式碼 or 指令,淺析ARM架構下的函式的呼叫過程架構函式
- Nginx圖片下載不完整的處理過程Nginx
- 流處理器與其他部件協同工作的過程