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;
}
相關文章
- GC 10.2.0.1 OMS和Agent連線失敗後的處理過程GC
- SpringMVC請求處理過程原始碼簡析SpringMVC原始碼
- Swift-析構過程Swift
- oracle處理SQL的過程OracleSQL
- 【分享】Delphi的內部字串處理函式/過程不完全列表字串函式
- 異常處理過程
- SQL語句的處理過程SQL
- 分散裝運處理的過程
- 資料轉換衝突及轉換過程中大物件的處理物件
- DML 語句處理過程
- Nucleus中斷處理過程!!!!
- python中PCA的處理過程PythonPCA
- DOM在Ahooks中的處理過程Hook
- SQL語句的處理過程修正SQL
- OnWndMsg函式的處理過程函式
- 【故障處理】一次RAC故障處理過程
- 資料庫變慢的處理過程資料庫
- 【原始碼】Redis命令處理過程原始碼Redis
- 某次BW 異常處理過程
- ora-14452處理過程
- HSG80故障處理過程
- ora-04031處理過程
- oracle 的DML命令的詳細處理過程Oracle
- postgresSQL Extended Query執行過程和sharding-proxy的處理SQL
- Python List 列表的處理Python
- MHA高可用架構工作原理?主庫當機處理過程架構
- 一次壞塊的處理過程(一)
- 一次壞塊的處理過程(二)
- MySQL儲存過程的異常處理方法MySql儲存過程
- fastHttp服務端處理請求的過程ASTHTTP服務端
- Flink流處理過程的部分原理分析
- undo表空間損壞的處理過程
- OGG 配置過程中的錯誤處理
- 一次壞塊的處理過程 [轉]
- Library cache pin問題的處理過程
- [zt]Logical standby同步故障的處理過程
- 物件導向和麵向過程物件
- Ceph pg unfound處理過程詳解