成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

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

開發 前端
WeakReference 的內部玩法有很多,更深入的理解還需要對 g_HandleTableMap 進行深度挖掘,后面有機會再聊吧,有時候dump分析還是挺苦逼的,需要對相關領域底層知識有一個足夠了解,否則談何修復呢?

一、背景

1. 講故事

最近在分析dump時,發現有程序的卡死和WeakReference有關,在以前只知道怎么用,但不清楚底層邏輯走向是什么樣的,借著這個dump的契機來簡單研究下。

二、弱引用的玩法

1. 一些基礎概念

用過WeakReference的朋友都知道這里面又可以分為弱短和弱長兩個概念,對應著構造函數中的trackResurrection參數,同時它也是對底層GCHandle.Alloc 方法的封裝,參考源碼如下:

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 的注釋來看。

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

可能這么說有點抽象,畫張圖如下:

圖片圖片

2. 一個簡單的測試例子

為了方便講述兩者的區別,使用 對象復活 來做測試。

  • Weak 的情況

因為在 ScanForFinalization 方法之前做的判斷,所以與垃圾對象的聯系會被馬上切斷,參考代碼如下:

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 析構已執行...");
            }
        }
    }

圖片圖片

  • WeakTrackResurrection 的情況

因為是在 ScanForFinalization 之后做的判斷,這時候可能會存在 對象復活 的情況,所以垃圾又變成不垃圾了,如果是這種情況就不能切斷,參考代碼如下:

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

圖片圖片

3. coreclr源碼分析

在 coreclr 里有一個 struct 枚舉強對應 GCHandleType 結構體,而且名字看的更加清楚,代碼如下:

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

接下來看下剛才截圖源碼上的驗證。

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;
}

源碼中有幾個注意點:

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

gc 在標記時,將有根的對象mt的第一位設為 1 來表示當前已經標記過,即有用對象,未被標記的即為垃圾對象。

  • 終結器線程真的被啟動了嗎

從簡化的源碼看,一旦有垃圾對象被送入到 終結器隊列的 預備區 時,就會通過 GCToEEInterface::EnableFinalization(true) 啟動終結器線程,所以在測試代碼中加了 GC.WaitForPendingFinalizers(); 就是為了等待終結器線程執行完畢然后才判斷 Target,這樣結果就會更加準確。

4. 切斷邏輯在哪里

有些朋友會好奇那個 weakHandle.Target=null 的邏輯到底在 coreclr 的何處,這個比較簡單,可以用 windbg 下 ba 斷點即可,我們還是拿弱引用來舉例,截圖如下:

圖片圖片

三、總結

WeakReference 的內部玩法有很多,更深入的理解還需要對 g_HandleTableMap 進行深度挖掘,后面有機會再聊吧,有時候dump分析還是挺苦逼的,需要對相關領域底層知識有一個足夠了解,否則談何修復呢?

責任編輯:武曉燕 來源: 一線碼農聊技術
相關推薦

2025-01-10 08:15:22

C#異步底層

2024-08-26 14:46:57

2021-03-29 00:02:10

C#Attribute元素

2024-12-26 10:05:58

C#前臺線程

2023-03-05 18:40:39

iptables防火墻軟件

2021-06-29 08:45:55

邏輯變量法函數

2023-10-24 15:56:23

2022-08-30 07:39:57

C++namespace隔離

2020-10-30 07:11:31

C 語言編程

2024-10-08 10:55:04

2022-11-02 08:51:01

2023-12-07 07:26:04

2024-01-02 13:26:39

TLSC#線程

2020-10-23 07:00:00

C++函數

2023-07-06 13:56:14

微軟Skype

2020-09-08 06:54:29

Java Gradle語言

2018-03-22 10:36:15

未來數據中心停機

2021-01-28 22:31:33

分組密碼算法

2023-09-22 17:36:37

2020-05-22 08:16:07

PONGPONXG-PON
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日韩av一二三区 | 亚洲成人精品久久久 | 四虎影院在线免费观看 | 久久se精品一区精品二区 | 激情五月综合 | 亚洲欧洲中文日韩 | 日韩在线一区二区三区 | 一区二区三区精品在线 | 国产精品久久久久久久久久免费 | 国产欧美一区二区在线观看 | 99这里只有精品视频 | 亚洲图片一区二区三区 | 国产午夜精品一区二区三区嫩草 | 国产精品久久片 | 亚洲色图在线观看 | 九九色九九 | 欧美成人免费在线视频 | 毛片国产 | 亚洲国产精品久久久久婷婷老年 | 91精品国产91久久久久久最新 | 国产69精品久久久久777 | 91亚洲一区 | 女人毛片a毛片久久人人 | 国产日韩精品久久 | 欧美99| 色频| av天天干 | 欧美日韩精品在线免费观看 | 观看毛片 | 国产一区二区三区在线观看免费 | 午夜无码国产理论在线 | 欧美日韩在线一区二区 | 亚洲一区三区在线观看 | 国产精品国产a级 | 中文在线一区二区 | 免费在线黄 | 操夜夜 | 精品久久一 | 麻豆久久久久久 | 日韩欧美在线视频 | 日韩人体视频 |