<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
      代碼改變世界

      CLR自動管理內(nèi)存---《clr via c#》筆記

      2012-02-03 16:27  海不是藍(lán)  閱讀(662)  評論(0)    收藏  舉報(bào)

      理解垃圾回收平臺的基本工作原理

      面向?qū)ο蟮沫h(huán)境中,每個(gè)類型都代表可供程序使用的一種資源。要使用這些資源,就需要為資源分配內(nèi)存,當(dāng)不使用資源的時(shí)候再回收銷毀。過程如下。

       

      1.調(diào)用IL指令newobj,為代表資源的類型分配內(nèi)存,c#中就是new操作符。

      2.初始化內(nèi)存,設(shè)置資源為初始狀態(tài),c#中是類型的實(shí)例構(gòu)造器負(fù)責(zé)初始化。

      3.訪問類型的成員(可以重復(fù))使用資源。(就是你平時(shí)不斷的使用一個(gè)對象的過程)

      4.摧毀資源的狀態(tài)以進(jìn)行清理。

      5.釋放內(nèi)存,垃圾回收器獨(dú)自負(fù)責(zé)這一步。

       

      Jeffrey大牛的抱怨

      Jeffrey這里有開始回憶他以前寫c++的光陰了!

      Jeffrey抱怨:進(jìn)行非托管編程的時(shí)候,內(nèi)存管理不當(dāng)是主要的bug。

      Jeffrey抱怨:花了大量的時(shí)間去考慮內(nèi)存的管理,極大的分散了他的精力。

       

      但是CLR的垃圾回收來了!Jeffrey開心的笑了!

       

       

       

      紅領(lǐng)巾???


       

      從托管堆分配資源

      CLR要求所有資源都從托管堆分配!別想逆天!

       

      這個(gè)托管堆和C語言中的堆相似,不同的地方是托管堆不需要你去手動刪除里面的對象。程序不需要的對象它自己會刪除!

       

      托管堆如何知道應(yīng)用程序不再用一個(gè)對象???

      要想知道問題的答案?Jeffrey說:“親,稍后告訴你!”。

      從基本概念講起:

      CLR維護(hù)著一片連續(xù)的地址空間,最開始沒有對應(yīng)物理存儲空間,這個(gè)地址就是托管堆。托管堆還有個(gè)指針,叫“NextObjPtr”,它指向下一個(gè)對象在堆中的分配位置。

       

      Newobj指令導(dǎo)致clr執(zhí)行的步驟

      1.計(jì)算類型的字段需要的字節(jié)數(shù)。

      2.加上對象的開銷需要的字節(jié)數(shù)。每個(gè)對象有2個(gè)開銷:一個(gè)是類型對象指針和一個(gè)同步索引塊。

      3.CLR檢查保留區(qū)是否能提供分配對象所需的字節(jié)數(shù)。

      這里有個(gè)彩蛋,托管堆中分配的對象內(nèi)存地址是連續(xù)的,例如c語言這些從線程棧中分配對象的內(nèi)存可能是分散的。

       

      垃圾回收算法

      垃圾回收器檢查托管堆中是否有程序不用的對象,如果有,那個(gè)對象的內(nèi)存將被回收。如果回收了一次,托管堆中還是沒有可以使用的內(nèi)存,那么new操作符將會拋出OutOfMemoryException異常!

       

      然后Jeffrey開始解釋什么是根!

      然后他寫了一個(gè)類,竟然搬上了32cpu下的80386匯編!

      什么EBX,EDI這些東西,我早忘記了。直接不看了!

      大概也就是從匯編角度去解釋clr怎么進(jìn)行回收的。

       

      根和回收

      每個(gè)程序都包含一組根,每個(gè)根都是一個(gè)存儲位置,其中包含了指向?qū)σ脤ο蟮囊粋€(gè)指針!該指針要么是托管堆中一個(gè)對象,要么是null。

      1.類型中的靜態(tài)字段是一個(gè)根。

      2.任何方法參數(shù)或局部變量也是一個(gè)根。

      3.只有引用類型的變量才能被認(rèn)為是根,值類型的變量永遠(yuǎn)不會是根。

       

      接下來就是那萬惡的匯編了!!!我懷著萬分痛苦的心情還是看了下。

       

      1.標(biāo)記階段

      大概意思就是垃圾回收器檢查托管堆中的每一個(gè)根,然后沿著這些根去檢查根下面是否有引用其他對象,如果有,先標(biāo)記好然后在根的同步索引字段上開啟一位。再檢查這個(gè)對象在堆下面的對象是否存在引用,

      如果不存在,那么這個(gè)對象不會被標(biāo)記。再去檢查其他根。

       

      2.壓縮階段

      已經(jīng)標(biāo)記好的對象是可達(dá)的對象,未標(biāo)記的對象是不可達(dá)的,也就是垃圾對象。

      現(xiàn)在開始第二階段:壓縮階段。

       

      這個(gè)階段中,垃圾回收器會線性的遍歷堆,尋找未標(biāo)記對象的連續(xù)內(nèi)存塊。

      如果內(nèi)存塊比較小,垃圾回收器會直接無視他們,忽略掉。

      如果比較大,垃圾回收器會把非垃圾的對象移動到這里以壓縮堆。

       

      垃圾回收會造成顯著的性能損失!這是托管堆的主要缺點(diǎn)。垃圾回收只在第0代滿的時(shí)候才發(fā)生。

       

      垃圾回收與調(diào)試

      只要對象變得不可達(dá),就會成為垃圾回收器的目標(biāo)!不保證對象在方法的生存周期中始終存活。

      static void Main()

      {

          Timer t = new Timer(TimerCallBack, null, 0, 2000);

          Console.Read();

      }

      private static void TimerCallBack(object obj)

      {

          Console.WriteLine("TimerCallBack:{0}"DateTime.Now);

          GC.Collect();

      }

      上面的程序一般認(rèn)為會每2秒輸出一次,這里主動調(diào)用了GC回收方法。但是運(yùn)行的時(shí)候發(fā)現(xiàn)回調(diào)方法只被調(diào)用了一次。

      因?yàn)檫@里t初始化之后,垃圾回收器發(fā)現(xiàn)在main方法里面再也沒有用過t。所以調(diào)用了一次回調(diào)方法以后t就被回收了!

       

      有些開發(fā)人員嘗試這樣去解決

      Timer t = new Timer(TimerCallBack, null, 0, 2000);

      Console.Read();

      t = null;

      但是發(fā)現(xiàn)最后運(yùn)行的情況和上面一樣!

      因?yàn)閷⒕植孔兞吭O(shè)為null,等于沒有引用這個(gè)變量。所以垃圾回收器一樣的回收你!

       

      正確的解決方法

      Timer t = new Timer(TimerCallBack, null, 0, 2000);

      Console.Read();

      t.Dispose();

      因?yàn)閷ο蟊仨毚婊畈拍苷{(diào)用Dispose方法!

       

      ---------------------------------------------------------------------

      Finalize和Safehandle就直接先忽略。以后接觸到再看!

      唉!手動監(jiān)視和控制對象的生存期也先忽略吧!AppDomain和com操作不太熟悉,以后再看。

      ---------------------------------------------------------------------

       

      代是CLR垃圾回收采用的一種機(jī)制,它的目的就是提升應(yīng)用程序的性能。

      第0代

      托管堆在初始化時(shí)不包含任何對象,添加到堆的對象稱為第0代對象。

      第1代

      當(dāng)程序不斷運(yùn)行,不斷有很多對象添加到托管堆,那么第0代預(yù)算的容量滿了,那么GC就會開始一次垃圾回收,那些0代中不可達(dá)的對象就會被回收。

      在垃圾回收中存活的對象就會升級為第1代。

      第2代

      當(dāng)?shù)?代中的對象越來越多,垃圾回收器就會考慮回收第0代和第1代中的垃圾對象,這次回收以后,存活的第1代對象就會升級到第2代。

       

      下面寫個(gè)程序演示代

      Console.WriteLine("當(dāng)前系統(tǒng)支持的最大代:{0}"GC.MaxGeneration);

      //在堆中創(chuàng)建一個(gè)新的GenObj

      Object obj = new object();

      Console.WriteLine("obj Gen:{0}"GC.GetGeneration(obj));//0

      GC.Collect();

      Console.WriteLine("obj Gen:{0}"GC.GetGeneration(obj));//1

      GC.Collect();

      Console.WriteLine("obj Gen:{0}"GC.GetGeneration(obj));//2

      GC.Collect();

      Console.WriteLine("obj Gen:{0}"GC.GetGeneration(obj));//2(不能再大了)

      obj = null;

       

       

      主站蜘蛛池模板: 69人妻精品中文字幕| 亚洲国产精品无码一区二区三区 | 东方四虎av在线观看| 成人一区二区三区在线午夜| 国产欧美日韩精品第二区| 视频一区视频二区亚洲视频| 日本高清一区免费中文视频| 性一交一黄一片| 少妇av一区二区三区无码| 国产精品十八禁在线观看| 亚洲a免费| 国产精品一区二区久久精品| 亚洲午夜爱爱香蕉片| 精品人妻二区中文字幕| 亚洲国产精品午夜福利| 蜜桃av无码免费看永久| 亚洲成av人片无码不卡播放器| 亚洲av成人一区二区| 产综合无码一区| 老色鬼永久精品网站| 西丰县| 无套内谢少妇高清毛片| 一区二区丝袜美腿视频| 久久综合色天天久久综合图片| 色综合五月伊人六月丁香| 久久88香港三级台湾三级播放| 国产电影无码午夜在线播放| 亚洲偷自拍国综合| 久久国产精品成人免费| 少妇被粗大的猛烈进出69影院一 | xxxx丰满少妇高潮| 亚洲精品一区国产精品| 亚洲国产精品乱码一区二区| 蜜桃av无码免费看永久| 在线a级毛片无码免费真人| 兰西县| 国产亚洲精品久久久久久久软件| 乱60一70归性欧老妇| 中文字幕无码av不卡一区| 高清中文字幕国产精品| 国内精品自线在拍|