• 
    

    
    

      99热精品在线国产_美女午夜性视频免费_国产精品国产高清国产av_av欧美777_自拍偷自拍亚洲精品老妇_亚洲熟女精品中文字幕_www日本黄色视频网_国产精品野战在线观看

      ?

      .NET Framework GC.Keep Alive方法的實現(xiàn)原理分析

      2021-08-07 11:56:18楊存?zhèn)?/span>
      鄂州大學學報 2021年4期
      關鍵詞:編譯器調(diào)用示例

      楊存?zhèn)?/p>

      (西南大學 計算機科學與技術系,重慶 402460)

      在.NET中,內(nèi)存資源分為托管資源和非托管資源,其中托管資源指的是.NET 可以自動進行回收的資源,主要是指托管堆上分配的內(nèi)存資源[1]。GC 類中包含了垃圾回收相關的方法,其中GC.KeepAlive 是其中一個較為特別的方法,它利用編譯器和運行時的特性,阻止對象過早被回收。

      1 GC.KeepAlive 的使用場景

      示例1

      在類Value中,實現(xiàn)了IDisposable中的Dispose方法,在類OuterClass 中,析構方法調(diào)用類成員i 的Dispose 方法來釋放資源。

      在Main 函數(shù)中,生成了一個Outerclass 的對象,變量名為outer,并將outer.i 作為參數(shù)傳遞給Do函數(shù)。outer.i 作為參數(shù)傳入之后,不存在對Outerclass 的對象的使用,因此垃圾回收器認為該對象已經(jīng)無用,而outer.i 是有效的。從這時起到程序運行結(jié)束的任何時刻,垃圾回收器都有可能執(zhí)行一次回收(回收Outerclass 的對象)。在垃圾回收器調(diào)用outer 的析構方法后,outer.i 已經(jīng)執(zhí)行了Dispose 方法,從而Do 函數(shù)中對outer.i 的操作可能是無效的,造成程序出錯(圖1)。

      圖1 不調(diào)用GC.KeepAlive 方法時程序的執(zhí)行流程

      若在Do(outer.i)后添加“GC.KeepAlive(outer)”,則Do 方法調(diào)用之后依然有對outer 的使用,保證了在調(diào)用Do 方法的時候,OuterClass 的對象不會被垃圾回收器回收(圖2)[2]。

      圖2 調(diào)用GC.KeepAlive 方法時程序的執(zhí)行流程

      2 實現(xiàn)原理

      Microsoft 對該方法的官方實現(xiàn)為:

      2.1 屬性(Attribute)的使用

      屬性(Attribute)是用于在運行時傳遞程序中各種元素(類、結(jié)構體、方法等)的行為信息的聲明性質(zhì)的標簽,它添加元數(shù)據(jù),如編譯器指令和注釋、描述、方法、類等其他信息。

      .NET 提供了兩種類型的特性:預定義特性和自定義特性。MethodImplAttribute 和Reliability-Contract 都屬于預定義特性[3]。

      2.2 MethodImplAttribute 的使用

      MethodImplAttribute 屬性指定了一個方法是怎樣編譯和執(zhí)行的。

      ImplOptions.NoInlining 指定了該方法不應該被內(nèi)聯(lián),由于GC.KeepAlive 并沒有對傳入的對象進行任何操作(也不應該進行任何操作),假如將其內(nèi)聯(lián),將不能保證在調(diào)用該方法之前傳入的對象不被垃圾回收。

      ReliabilityContract 屬性與實現(xiàn)原理無關,與安全性和可靠性有關,因此不做解析。

      2.3 在調(diào)用GC.KeepAlive 之前對象不被回收的原因分析

      .NET 的垃圾回收器使用一種引用跟蹤算法。在垃圾回收時,暫停所有線程,遍歷所有堆內(nèi)存中存在的對象,若引用類型變量引用了某個對象,該對象的同步索引字段將被置為1,否則為0。完成遍歷后,同步索引字段為0 的對象是可以被回收的(不一定會被回收)[4]。

      在示例1 中,outer.i 作為參數(shù)傳入后,假設垃圾回收器開始回收,將發(fā)現(xiàn)OuterClass 的對象的同步索引塊標記為0,這意味著沒有變量繼續(xù)引用OuterClass 的對象,則其可以回收。

      若加上“GC.KeepAlive(outer)”,則outer.i 作為參數(shù)傳入后,假如垃圾回收器開始回收,發(fā)現(xiàn)在Main 函數(shù)中還有待調(diào)用的GC.KeepAlive 方法使用了OuterClass 的對象,因此在調(diào)用GC.KeepAlive 之前,同步索引塊都為1,即該對象都必須存在,不應該被回收。假設將“GC.KeepAlive(outer)”替換成“var str=outer.ToString ()” 等語句(只要使用了OuterClass 的對象),和調(diào)用GC.KeepAlive 方法的作用是一樣的,只是該方法不產(chǎn)生任何副作用。

      3.NET 源碼中對該方法運用的示例分析

      3.1 GC.GetGeneration 方法的實現(xiàn)

      示例2:

      .NET 的垃圾回收器查找未被引用的對象時,使用可達性分析算法[5],WeakReference 引用變量不會存在于GCRoots 開始的引用鏈中。若在調(diào)用GetGenerationWR 方法之后不調(diào)用KeepAlive 方法,不能保證wo 所指向的對象一定是存在的,造成調(diào)用失敗。

      3.2 X509Utils.GetCertContext 方法的實現(xiàn)

      示例3:

      在將certificate.Handle 作為參數(shù)傳入CertDuplicateCertificateContext 方法后,若沒有GC.KeepAlive 方法,將導致certificate 隨時被垃圾回收,導致certificate.Handle 失效。

      3.3 RuntimeHelpers.PrepareMethod 方法的實現(xiàn)

      示例4:

      PrepareMethod 方法是對外部函數(shù)_PrepareMethod 的一層包裝,在CopyRuntimeTypeHandles 方法使用instantiation 作為參數(shù)后,instantiationHandles 的有效性依然依賴于instantiation,故在_PrepareMethod 函數(shù)后調(diào)用GC.KeepAlive 方法來保證instantiation 在PrepareMethod 函數(shù)返回前都是有效的。

      4 結(jié)語

      GC.KeepAlive 的實現(xiàn)并未調(diào)用.NET 中的內(nèi)部類和方法,也未調(diào)用Win32 的API,其實質(zhì)是運用了編譯器和運行時的特性,保證了對象不被過早回收,其實現(xiàn)十分簡潔。在實際運用中準確運用此方法,提高了程序的安全性和穩(wěn)定性。

      猜你喜歡
      編譯器調(diào)用示例
      大還是小
      基于相異編譯器的安全計算機平臺交叉編譯環(huán)境設計
      2019年高考上海卷作文示例
      核電項目物項調(diào)用管理的應用研究
      常見單位符號大小寫混淆示例
      山東冶金(2019年5期)2019-11-16 09:09:22
      LabWindows/CVI下基于ActiveX技術的Excel調(diào)用
      測控技術(2018年5期)2018-12-09 09:04:46
      “全等三角形”錯解示例
      基于系統(tǒng)調(diào)用的惡意軟件檢測技術研究
      通用NC代碼編譯器的設計與實現(xiàn)
      利用RFC技術實現(xiàn)SAP系統(tǒng)接口通信
      依兰县| 遂平县| 和平区| 桐庐县| 图片| 广德县| 兴海县| 华安县| 鄂温| 外汇| 漳平市| 玉溪市| 桦甸市| 内黄县| 龙胜| 阿瓦提县| 天津市| 海林市| 西和县| 财经| 汉川市| 岳阳县| 新野县| 江山市| 临邑县| 枞阳县| 珠海市| 葫芦岛市| 雷波县| 湘乡市| 昌乐县| 永泰县| 长兴县| 齐齐哈尔市| 潜山县| 宣武区| 久治县| 云南省| 南安市| 和田市| 定南县|