AVt天堂网 手机版,亚洲va久久久噜噜噜久久4399,天天综合亚洲色在线精品,亚洲一级Av无码毛片久久精品

當(dāng)前位置:首頁 > 科技  > 軟件

聊一聊 C# 弱引用底層是怎么玩的

來源: 責(zé)編: 時間:2024-06-28 17:09:52 148觀看
導(dǎo)讀一、背景1. 講故事最近在分析dump時,發(fā)現(xiàn)有程序的卡死和WeakReference有關(guān),在以前只知道怎么用,但不清楚底層邏輯走向是什么樣的,借著這個dump的契機來簡單研究下。二、弱引用的玩法1. 一些基礎(chǔ)概念用過WeakReference的朋

一、背景

1. 講故事

最近在分析dump時,發(fā)現(xiàn)有程序的卡死和WeakReference有關(guān),在以前只知道怎么用,但不清楚底層邏輯走向是什么樣的,借著這個dump的契機來簡單研究下。L8Q28資訊網(wǎng)——每日最新資訊28at.com

二、弱引用的玩法

1. 一些基礎(chǔ)概念

用過WeakReference的朋友都知道這里面又可以分為弱短和弱長兩個概念,對應(yīng)著構(gòu)造函數(shù)中的trackResurrection參數(shù),同時它也是對底層GCHandle.Alloc 方法的封裝,參考源碼如下:L8Q28資訊網(wǎng)——每日最新資訊28at.com

public WeakReference(object? target, bool trackResurrection){    Create(target, trackResurrection);}private void Create(object target, bool trackResurrection){    nint num = GCHandle.InternalAlloc(target, trackResurrection ? GCHandleType.WeakTrackResurrection : GCHandleType.Weak);    _taggedHandle = (trackResurrection ? (num | 1) : num);    ComAwareWeakReference.ComInfo comInfo = ComAwareWeakReference.ComInfo.FromObject(target);    if (comInfo != null)    {        ComAwareWeakReference.SetComInfoInConstructor(ref _taggedHandle, comInfo);    }}public enum GCHandleType{    //    // Summary:    //     This handle type is used to track an object, but allow it to be collected. When    //     an object is collected, the contents of the System.Runtime.InteropServices.GCHandle    //     are zeroed. Weak references are zeroed before the finalizer runs, so even if    //     the finalizer resurrects the object, the Weak reference is still zeroed.    Weak = 0,    //    // Summary:    //     This handle type is similar to System.Runtime.InteropServices.GCHandleType.Weak,    //     but the handle is not zeroed if the object is resurrected during finalization.    WeakTrackResurrection = 1}

從上面的 GCHandleType 的注釋來看。L8Q28資訊網(wǎng)——每日最新資訊28at.com

  • Weak 會在終結(jié)器執(zhí)行之前判斷持有的對象是否為垃圾對象,如果是的話直接切斷引用。
  • WeakTrackResurrection 會在終結(jié)器執(zhí)行之后判斷對象是否為垃圾對象,如果是的話直接切斷引用。

可能這么說有點抽象,畫張圖如下:L8Q28資訊網(wǎng)——每日最新資訊28at.com

圖片圖片L8Q28資訊網(wǎng)——每日最新資訊28at.com

2. 一個簡單的測試?yán)?/h3>

為了方便講述兩者的區(qū)別,使用 對象復(fù)活 來做測試。L8Q28資訊網(wǎng)——每日最新資訊28at.com

  • Weak 的情況

因為在 ScanForFinalization 方法之前做的判斷,所以與垃圾對象的聯(lián)系會被馬上切斷,參考代碼如下:L8Q28資訊網(wǎng)——每日最新資訊28at.com

class Program    {        static void Main()        {            WeakReferenceCase();            GC.Collect();            GC.WaitForPendingFinalizers();            Console.WriteLine(weakHandle.Target ?? "Person 引用被切斷");            Console.ReadLine();        }        public static GCHandle weakHandle;        static void WeakReferenceCase()        {            var person = new Person() { ressurect = false };            weakHandle = GCHandle.Alloc(person, GCHandleType.Weak);        }    }    public class Person    {        public bool ressurect = false;        ~Person()        {            if (ressurect)            {                Console.WriteLine("Person 被永生了,不可能被消滅的。。。");                GC.ReRegisterForFinalize(this);            }            else            {                Console.WriteLine("Person 析構(gòu)已執(zhí)行...");            }        }    }

圖片圖片L8Q28資訊網(wǎng)——每日最新資訊28at.com

  • WeakTrackResurrection 的情況

因為是在 ScanForFinalization 之后做的判斷,這時候可能會存在 對象復(fù)活 的情況,所以垃圾又變成不垃圾了,如果是這種情況就不能切斷,參考代碼如下:L8Q28資訊網(wǎng)——每日最新資訊28at.com

static void WeakReferenceCase(){    var person = new Person() { ressurect = true };    weakHandle = GCHandle.Alloc(person, GCHandleType.WeakTrackResurrection);}

圖片圖片L8Q28資訊網(wǎng)——每日最新資訊28at.com

3. coreclr源碼分析

在 coreclr 里有一個 struct 枚舉強對應(yīng) GCHandleType 結(jié)構(gòu)體,而且名字看的更加清楚,代碼如下:L8Q28資訊網(wǎng)——每日最新資訊28at.com

typedef enum{ HNDTYPE_WEAK_SHORT = 0, HNDTYPE_WEAK_LONG = 1,}HandleType;

接下來看下剛才截圖源碼上的驗證。L8Q28資訊網(wǎng)——每日最新資訊28at.com

void gc_heap::mark_phase(int condemned_gen_number, BOOL mark_only_p){ // null out the target of short weakref that were not promoted. GCScan::GcShortWeakPtrScan(condemned_gen_number, max_generation, &sc); dprintf(3, ("Finalize marking")); finalize_queue->ScanForFinalization(GCHeap::Promote, condemned_gen_number, mark_only_p, __this); // null out the target of long weakref that were not promoted. GCScan::GcWeakPtrScan(condemned_gen_number, max_generation, &sc);}BOOL CFinalize::ScanForFinalization(promote_func* pfn, int gen, BOOL mark_only_p, gc_heap* hp){    for (unsigned int Seg = startSeg; Seg <= gen_segment(0); Seg++)    {        Object** endIndex = SegQueue(Seg);        for (Object** i = SegQueueLimit(Seg) - 1; i >= endIndex; i--)        {            CObjectHeader* obj = (CObjectHeader*)*i;            if (!g_theGCHeap->IsPromoted(obj))            {                if (method_table(obj)->HasCriticalFinalizer())                {                    MoveItem(i, Seg, CriticalFinalizerListSeg);                }                else                {                    MoveItem(i, Seg, FinalizerListSeg);                }            }        }    }    if(finalizedFound) GCToEEInterface::EnableFinalization(true);    return finalizedFound;}

源碼中有幾個注意點:L8Q28資訊網(wǎng)——每日最新資訊28at.com

  • 如何判斷一個對象為垃圾

gc 在標(biāo)記時,將有根的對象mt的第一位設(shè)為 1 來表示當(dāng)前已經(jīng)標(biāo)記過,即有用對象,未被標(biāo)記的即為垃圾對象。L8Q28資訊網(wǎng)——每日最新資訊28at.com

  • 終結(jié)器線程真的被啟動了嗎

從簡化的源碼看,一旦有垃圾對象被送入到 終結(jié)器隊列的 預(yù)備區(qū) 時,就會通過 GCToEEInterface::EnableFinalization(true) 啟動終結(jié)器線程,所以在測試代碼中加了 GC.WaitForPendingFinalizers(); 就是為了等待終結(jié)器線程執(zhí)行完畢然后才判斷 Target,這樣結(jié)果就會更加準(zhǔn)確。L8Q28資訊網(wǎng)——每日最新資訊28at.com

4. 切斷邏輯在哪里

有些朋友會好奇那個 weakHandle.Target=null 的邏輯到底在 coreclr 的何處,這個比較簡單,可以用 windbg 下 ba 斷點即可,我們還是拿弱引用來舉例,截圖如下:L8Q28資訊網(wǎng)——每日最新資訊28at.com

圖片圖片L8Q28資訊網(wǎng)——每日最新資訊28at.com

三、總結(jié)

WeakReference 的內(nèi)部玩法有很多,更深入的理解還需要對 g_HandleTableMap 進行深度挖掘,后面有機會再聊吧,有時候dump分析還是挺苦逼的,需要對相關(guān)領(lǐng)域底層知識有一個足夠了解,否則談何修復(fù)呢?L8Q28資訊網(wǎng)——每日最新資訊28at.com

本文鏈接:http://www.tebozhan.com/showinfo-26-97278-0.html聊一聊 C# 弱引用底層是怎么玩的

聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 十個 Python 秘訣將顛覆你的編碼方式

下一篇: 為什么會 Js 但是依然不會寫 Node?原因竟是這三點...

標(biāo)簽:
  • 熱門焦點
  • 一加Ace2 Pro真機揭曉 鈦空灰配色質(zhì)感拉滿

    終于,在經(jīng)過了幾波預(yù)熱之后,一加Ace2 Pro的外觀真機圖在網(wǎng)上出現(xiàn)了。還是博主數(shù)碼閑聊站曝光的,這次的外觀設(shè)計還是延續(xù)了一加11的方案,只是細節(jié)上有了調(diào)整,例如新加入了鈦空灰
  • K60至尊版剛預(yù)熱 一加Ace2 Pro正面硬剛

    Redmi這邊剛?cè)缁鹑巛钡男麄髁薑60 Ultra的各種技術(shù)和硬件配置,作為競品的一加也坐不住了。一加中國區(qū)總裁李杰發(fā)布了兩條微博,表示在自家的一加Ace2上早就已經(jīng)采用了和PixelWo
  • Rust中的高吞吐量流處理

    作者 | Noz編譯 | 王瑞平本篇文章主要介紹了Rust中流處理的概念、方法和優(yōu)化。作者不僅介紹了流處理的基本概念以及Rust中常用的流處理庫,還使用這些庫實現(xiàn)了一個流處理程序
  • 把LangChain跑起來的三個方法

    使用LangChain開發(fā)LLM應(yīng)用時,需要機器進行GLM部署,好多同學(xué)第一步就被勸退了,那么如何繞過這個步驟先學(xué)習(xí)LLM模型的應(yīng)用,對Langchain進行快速上手?本片講解3個把LangChain跑起來
  • 虛擬鍵盤 API 的妙用

    你是否在遇到過這樣的問題:移動設(shè)備上有一個固定元素,當(dāng)激活虛擬鍵盤時,該元素被隱藏在了鍵盤下方?多年來,這一直是 Web 上的默認(rèn)行為,在本文中,我們將探討這個問題、為什么會發(fā)生
  • 阿里瓴羊One推出背后,零售企業(yè)迎數(shù)字化新解

    作者:劉曠近年來隨著數(shù)字經(jīng)濟的高速發(fā)展,各式各樣的SaaS應(yīng)用服務(wù)更是層出不窮,但本質(zhì)上SaaS大多局限于單一業(yè)務(wù)流層面,對用戶核心關(guān)切的增長問題等則沒有提供更好的解法。在Saa
  • 三星Galaxy Z Fold/Flip 5國行售價曝光 :最低7499元/12999元起

    據(jù)官方此前宣布,三星將于7月26日也就是明天在韓國首爾舉辦Unpacked活動,屆時將帶來帶來包括Galaxy Buds 3、Galaxy Watch 6、Galaxy Tab S9、Galaxy
  • iQOO Neo8 Pro評測:旗艦雙芯加持 最強性能游戲旗艦

    【Techweb評測】去年10月,iQOO推出了一款Neo7手機,該機搭載了聯(lián)發(fā)科天璣9000+,配備獨顯芯片Pro+,帶來了同價位段最佳的游戲體驗,一經(jīng)上市便受到了諸多用
  • 由于成本持續(xù)增加,筆記本產(chǎn)品價格預(yù)計將明顯上漲

    根據(jù)知情人士透露,由于材料、物流等成本持續(xù)增加,筆記本產(chǎn)品價格預(yù)計將在2021年下半年有明顯上漲。進入6月下旬以來,全球半導(dǎo)體芯片缺貨情況加劇,顯卡、處理器
Top