日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > asp.net >内容正文

asp.net

[你必须知道的.NET]第十九回:对象创建始末(下)

發(fā)布時(shí)間:2023/12/10 asp.net 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [你必须知道的.NET]第十九回:对象创建始末(下) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

本文將介紹以下內(nèi)容:

  • 對(duì)象的創(chuàng)建過(guò)程
  • 內(nèi)存分配分析
  • 內(nèi)存布局研究

?

接上回[第十八回:對(duì)象創(chuàng)建始末(上)],繼續(xù)對(duì)對(duì)象創(chuàng)建話題的討論>>>

2.2?托管堆的內(nèi)存分配機(jī)制

引用類型的實(shí)例分配于托管堆上,而線程棧卻是對(duì)象生命周期開(kāi)始的地方。對(duì)32位處理器來(lái)說(shuō),應(yīng)用程序完成進(jìn)程初始化后,CLR將在進(jìn)程的可用地址空間上分配一塊保留的地址空間,它是進(jìn)程(每個(gè)進(jìn)程可使用4GB)中可用地址空間上的一塊內(nèi)存區(qū)域,但并不對(duì)應(yīng)于任何物理內(nèi)存,這塊地址空間即是托管堆。

托管堆又根據(jù)存儲(chǔ)信息的不同劃分為多個(gè)區(qū)域,其中最重要的是垃圾回收堆(GC Heap)和加載堆(Loader Heap),GC Heap用于存儲(chǔ)對(duì)象實(shí)例,受GC管理;Loader Heap又分為High-Frequency Heap、Low-Frequency Heap和Stub Heap,不同的堆上又存儲(chǔ)不同的信息。Loader Heap最重要的信息就是元數(shù)據(jù)相關(guān)的信息,也就是Type對(duì)象,每個(gè)Type在Loader Heap上體現(xiàn)為一個(gè)Method Table(方法表),而Method Table中則記錄了存儲(chǔ)的元數(shù)據(jù)信息,例如基類型、靜態(tài)字段、實(shí)現(xiàn)的接口、所有的方法等等。Loader Heap不受GC控制,其生命周期為從創(chuàng)建到AppDomain卸載。

在進(jìn)入實(shí)際的內(nèi)存分配分析之前,有必要對(duì)幾個(gè)基本概念做以交代,以便更好的在接下來(lái)的分析中展開(kāi)討論。

·TypeHandle,類型句柄,指向?qū)?yīng)實(shí)例的方法表,每個(gè)對(duì)象創(chuàng)建時(shí)都包含該附加成員,并且占用4個(gè)字節(jié)的內(nèi)存空間。我們知道,每個(gè)類型都對(duì)應(yīng)于一個(gè)方法表,方法表創(chuàng)建于編譯時(shí),主要包含了類型的特征信息、實(shí)現(xiàn)的接口數(shù)目、方法表的slot數(shù)目等。

·SyncBlockIndex,用于線程同步,每個(gè)對(duì)象創(chuàng)建時(shí)也包含該附加成員,它指向一塊被稱為Synchronization Block的內(nèi)存塊,用于管理對(duì)象同步,同樣占用4個(gè)字節(jié)的內(nèi)存空間。

·NextObjPtr,由托管堆維護(hù)的一個(gè)指針,用于標(biāo)識(shí)下一個(gè)新建對(duì)象分配時(shí)在托管堆中所處的位置。CLR初始化時(shí),NextObjPtr位于托管堆的基地址。

因此,我們對(duì)引用類型分配過(guò)程應(yīng)該有個(gè)基本的了解,由于本篇示例中FileStream類型的繼承關(guān)系相對(duì)復(fù)雜,在此本文實(shí)現(xiàn)一個(gè)相對(duì)簡(jiǎn)單的類型來(lái)做說(shuō)明:

//@?2007?Anytao.com?
//http://www.anytao.com
????public?class?UserInfo
????{
????????
private?Int32?age?=?-1;
????????
private?char?level?=?'A';
????}

????
public?class?User
????{
????????
private?Int32?id;
????????
private?UserInfo?user;
????}

????
public?class?VIPUser?:?User
????{
????????
public?bool?isVip;

????????
public?bool?IsVipUser()
????????{
????????????
return?isVip;
????????}

????????
public?static?void?Main()
????????{
????????????VIPUser?aUser;
????????????aUser?
=?new?VIPUser();
????????????aUser.isVip?
=?true;
????????????Console.WriteLine(aUser.IsVipUser());
????????}
????}

將上述實(shí)例的執(zhí)行過(guò)程,反編譯為IL語(yǔ)言可知:new關(guān)鍵字被編譯為newobj指令來(lái)完成對(duì)象創(chuàng)建工作,進(jìn)而調(diào)用類型的構(gòu)造器來(lái)完成其初始化操作,在此我們?cè)敿?xì)的描述其執(zhí)行的具體過(guò)程:

·首先,將聲明一個(gè)引用類型變量aUser:

????????????VIPUser?aUser;

它僅是一個(gè)引用(指針),保存在線程的堆棧上,占用4Byte的內(nèi)存空間,將用于保存VIPUser對(duì)象的有效地址,其執(zhí)行過(guò)程正是上文描述的在線程棧上的分配過(guò)程。此時(shí)aUser未指向任何有效的實(shí)例,因此被自行初始化為null,試圖對(duì)aUser的任何操作將拋出NullReferenceException異常。

·接著,通過(guò)new操作執(zhí)行對(duì)象創(chuàng)建:

??????????? aUser =?new?VIPUser();

如上文所言,該操作對(duì)應(yīng)于執(zhí)行newobj指令,其執(zhí)行過(guò)程又可細(xì)分為以下幾步:

(a)CLR按照其繼承層次進(jìn)行搜索,計(jì)算類型及其所有父類的字段,該搜索將一直遞歸到System.Object類型,并返回字節(jié)總數(shù),以本例而言類型VIPUser需要的字節(jié)總數(shù)為15Byte,具體計(jì)算為:VIPUser類型本身字段isVip(bool型)為1Byte;父類User類型的字段id(Int32型)為4Byte,字段user保存了指向UserInfo型的引用,因此占4Byte,而同時(shí)還要為UserInfo分配6Byte字節(jié)的內(nèi)存。

實(shí)例對(duì)象所占的字節(jié)總數(shù)還要加上對(duì)象附加成員所需的字節(jié)總數(shù),其中附加成員包括TypeHandle和SyncBlockIndex,共計(jì)8字節(jié)(在32位CPU平臺(tái)下)。因此,需要在托管堆上分配的字節(jié)總數(shù)為23字節(jié),而堆上的內(nèi)存塊總是按照4Byte的倍數(shù)進(jìn)行分配,因此本例中將分配24字節(jié)的地址空間。

(c)CLR在當(dāng)前AppDomain對(duì)應(yīng)的托管堆上搜索,找到一個(gè)未使用的20字節(jié)的連續(xù)空間,并為其分配該內(nèi)存地址。事實(shí)上,GC使用了非常高效的算法來(lái)滿足該請(qǐng)求,NextObjPtr指針只需要向前推進(jìn)20個(gè)字節(jié),并清零原NextObjPtr指針和當(dāng)前NextObjPtr指針之間的字節(jié),然后返回原NextObjPtr指針地址即可,該地址正是新創(chuàng)建對(duì)象的托管堆地址,也就是aUser引用指向的實(shí)例地址。而此時(shí)的NextObjPtr仍指向下一個(gè)新建對(duì)象的位置。注意,棧的分配是向低地址擴(kuò)展,而堆的分配是向高地址擴(kuò)展。

另外,實(shí)例字段的存儲(chǔ)是有順序的,由上到下依次排列,父類在前子類在后,詳細(xì)的分析請(qǐng)參見(jiàn)[第十五回:繼承本質(zhì)論]。

在上述操作時(shí),如果試圖分配所需空間而發(fā)現(xiàn)內(nèi)存不足時(shí),GC將啟動(dòng)垃圾收集操作來(lái)回收垃圾對(duì)象所占的內(nèi)存,我們將以后對(duì)此做詳細(xì)的分析。

·最后,調(diào)用對(duì)象構(gòu)造器,進(jìn)行對(duì)象初始化操作,完成創(chuàng)建過(guò)程。該構(gòu)造過(guò)程,又可細(xì)分為以下幾個(gè)環(huán)節(jié):

???(a)構(gòu)造VIPUser類型的Type對(duì)象,主要包括靜態(tài)字段、方法表、實(shí)現(xiàn)的接口等,并將其分配在上文提到托管堆的Loader Heap上。

(b)初始化aUser的兩個(gè)附加成員:TypeHandle和SyncBlockIndex。將TypeHandle指針指向Loader Heap上的MethodTable,CLR將根據(jù)TypeHandle來(lái)定位具體的Type;將SyncBlockIndex指針指向Synchronization Block的內(nèi)存塊,用于在多線程環(huán)境下對(duì)實(shí)例對(duì)象的同步操作。

(c)調(diào)用VIPUser的構(gòu)造器,進(jìn)行實(shí)例字段的初始化。實(shí)例初始化時(shí),會(huì)首先向上遞歸執(zhí)行父類初始化,直到完成System.Object類型的初始化,然后再返回執(zhí)行子類的初始化,直到執(zhí)行VIPUser類為止。以本例而言,初始化過(guò)程為首先執(zhí)行System.Object類,再執(zhí)行User類,最后才是VIPUser類。最終,newobj分配的托管堆的內(nèi)存地址,被傳遞給VIPUser的this參數(shù),并將其引用傳給棧上聲明的aUser。

上述過(guò)程,基本完成了一個(gè)引用類型創(chuàng)建、內(nèi)存分配和初始化的整個(gè)流程,然而該過(guò)程只能看作是一個(gè)簡(jiǎn)化的描述,實(shí)際的執(zhí)行過(guò)程更加復(fù)雜,涉及到一系列細(xì)化的過(guò)程和操作。對(duì)象創(chuàng)建并初始化之后,內(nèi)存的布局,可以表示為:

??? 由上文的分析可知,在托管堆中增加新的實(shí)例對(duì)象,只是將NextObjPtr指針增加一定的數(shù)值,再次新增的對(duì)象將分配在當(dāng)前NextObjPtr指向的內(nèi)存空間,因此在托管堆棧中,連續(xù)分配的對(duì)象在內(nèi)存中一定是連續(xù)的,這種分配機(jī)制非常高效。

2.3?必要的補(bǔ)充

有了對(duì)象創(chuàng)建的基本流程概念,下面的幾個(gè)問(wèn)題時(shí)常引起大家的思考,在此本文一并做以探索:

·值類型中的引用類型字段和引用類型中的值類型字段,其分配情況又是如何?

????這一思考其實(shí)是一個(gè)問(wèn)題的兩個(gè)方面:對(duì)于值類型嵌套引用類型的情況,引用類型變量作為值類型的成員變量,在堆棧上保存該成員的引用,而實(shí)際的引用類型仍然保存在GC堆上;對(duì)于引用類型嵌套值類型的情況,則該值類型字段將作為引用類型實(shí)例的一部分保存在GC堆上。在[?第八回:品味類型---值類型與引用類型(上)-內(nèi)存有理]一文對(duì)這種嵌套結(jié)構(gòu),有較詳細(xì)的分析。對(duì)于值類型,你只要記著它總是分配在聲明它的地方。

·方法保存在Loader Heap的MethodTable中,那么方法調(diào)用時(shí)又是怎么樣的過(guò)程?

如上文所言,MethodTable中包含了類型的元數(shù)據(jù)信息,類在加載時(shí)會(huì)在Loader Heap上創(chuàng)建這些信息,一個(gè)類型在內(nèi)存中對(duì)應(yīng)一份MethodTable,其中包含了所有的方法、靜態(tài)字段和實(shí)現(xiàn)的接口信息等。對(duì)象實(shí)例的TypeHandle在實(shí)例創(chuàng)建時(shí),將指向MethodTable開(kāi)始位置的偏移處(默認(rèn)偏移12Byte),通過(guò)對(duì)象實(shí)例調(diào)用某個(gè)方法時(shí),CLR根據(jù)TypeHandle可以找到對(duì)應(yīng)的MethodTable,進(jìn)而可以定位到具體的方法,再通過(guò)JIT Compiler將IL指令編譯為本地CPU指令,該指令將保存在一個(gè)動(dòng)態(tài)內(nèi)存中,然后在該內(nèi)存地址上執(zhí)行該方法,同時(shí)該CPU指令被保存起來(lái)用于下一次的執(zhí)行。

在MethodTable中,包含一個(gè)Method Slot Table,稱為方法槽表,該表是一個(gè)基于方法實(shí)現(xiàn)的線性鏈表,并按照以下順序排列:繼承的虛方法,引入的虛方法,實(shí)例方法和靜態(tài)方法。方法表在創(chuàng)建時(shí),將按照繼承層次向上搜索父類,直到System.Object類型,如果子類覆寫(xiě)了父類方法,則將會(huì)以子類方法覆蓋父類虛方法。關(guān)于方法表的創(chuàng)建過(guò)程,可以參考[第十五回:繼承本質(zhì)論]中的描述。

·靜態(tài)字段的內(nèi)存分配和釋放,又有何不同?

????靜態(tài)字段也保存在方法表中,位于方法表的槽數(shù)組后,其生命周期為從創(chuàng)建到AppDomain卸載。因此一個(gè)類型無(wú)論創(chuàng)建多少個(gè)對(duì)象,其靜態(tài)字段在內(nèi)存中也只有一份。靜態(tài)字段只能由靜態(tài)構(gòu)造函數(shù)進(jìn)行初始化,靜態(tài)構(gòu)造函數(shù)確保在類型任何對(duì)象創(chuàng)建前,或者在任何靜態(tài)字段或方法被引用前執(zhí)行,其詳細(xì)的執(zhí)行順序請(qǐng)參考相關(guān)討論。

3.?結(jié)論

對(duì)象創(chuàng)建過(guò)程的了解,是從底層接觸CLR運(yùn)行機(jī)制的入口,也是認(rèn)識(shí).NET自動(dòng)內(nèi)存管理的關(guān)鍵。通過(guò)本文的詳細(xì)論述,關(guān)于對(duì)象的創(chuàng)建、內(nèi)存分配、初始化過(guò)程和方法調(diào)用等技術(shù)都會(huì)建立一個(gè)相對(duì)全面的理解,同時(shí)也清楚的把握了線程棧和托管堆的執(zhí)行機(jī)制。

對(duì)象總是有生有滅,本文簡(jiǎn)述其生,這是個(gè)偉大的開(kāi)始。?

?

[祝福] 一個(gè)值得紀(jì)念的日子,一切快樂(lè)、平安、健康,這次專注,2008會(huì)更好。

參考文獻(xiàn)

?

(USA)Joe Duffy, Professinal .NET Framework 2.0?
(USA)Don Box, Essiential .NET?
(MSDN)Hanu Kommalapati and Tom Christian, Drill Into .NET Framework Internals to See How the CLR Creates Runtime Objects,?http://msdn.microsoft.com/msdnmag/issues/05/05/JITCompiler/default.aspx

?

?

方法表:?
方法槽表應(yīng)該先是基類的方法成員(一直到OBJECT),然后是自己的,自己里的,順序是繼承的虛方法,引入的虛方法,實(shí)例方法和靜態(tài)方法。?
在方法槽表上面的應(yīng)該還又委托,這點(diǎn)應(yīng)該要提下了。?
方法槽下面才是靜態(tài)字段,接口吧。

第十五回:繼承本質(zhì)論,?http://www.cnblogs.com/anytao/archive/2007/09/10/must_net_15.html?
中有比較詳細(xì)的論述,不過(guò)沒(méi)有從更底層的分配過(guò)程來(lái)詳述。?
關(guān)于委托,系列后續(xù)肯定會(huì)有,謝謝你的關(guān)注。

?

?

?

#33樓?2007-12-15 09:39?lihaoware

看了樓主這一系列的文章受益匪淺,向樓主表示敬意!?

在本文中我對(duì)樓主關(guān)于“VIPUser類型實(shí)例”占內(nèi)存大小的計(jì)算有疑問(wèn):?

文中“類型VIPUser需要的字節(jié)總數(shù)為11Byte,具體計(jì)算為:VIPUser類型本身字段isVip(bool型)為1Byte;父類User類型的字段id(Int32型)為4Byte,字段user(UserInfo型)為6Byte。?

我認(rèn)為:UserInfo類型實(shí)例占6byte,而VIPUser類型父類User中的user字段只是UserInfo類型的引用,其內(nèi)存分配應(yīng)為4byte(文中上下文指的32位機(jī)器),而不是6byte。User類型實(shí)例占內(nèi)存為6byte,VIPUser類型實(shí)例占內(nèi)存為17byte

支持(0)?反對(duì)(0)

??

#34樓?[樓主]?2007-12-15 12:05?Anytao

@lihaoware?
的確有失嚴(yán)謹(jǐn),已經(jīng)做了檢查,在user字段的判斷部分分析有誤,正確的應(yīng)該是:?
CLR按照其繼承層次進(jìn)行搜索,計(jì)算類型及其所有父類的字段,該搜索將一直遞歸到System.Object類型,并返回字節(jié)總數(shù),以本例而言類型VIPUser需要的字節(jié)總數(shù)為15Byte,具體計(jì)算為:VIPUser類型本身字段isVip(bool型)為1Byte;父類User類型的字段id(Int32型)為4Byte,字段user保存了指向UserInfo型的引用,因此占4Byte,而同時(shí)還要為UserInfo分配6Byte字節(jié)的內(nèi)存。?
實(shí)例對(duì)象所占的字節(jié)總數(shù)還要加上對(duì)象附加成員所需的字節(jié)總數(shù),其中附加成員包括TypeHandle和SyncBlockIndex,共計(jì)8字節(jié)(在32位CPU平臺(tái)下)。因此,需要在托管堆上分配的字節(jié)總數(shù)為23字節(jié),而堆上的內(nèi)存塊總是按照4Byte的倍數(shù)進(jìn)行分配,因此本例中將分配24字節(jié)的地址空間。


由于網(wǎng)絡(luò)問(wèn)題,暫時(shí)不能修改,我將擇日盡快修改,感謝你的指正:-)?

?

?

?

?

總結(jié)

以上是生活随笔為你收集整理的[你必须知道的.NET]第十九回:对象创建始末(下)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 91视频一区二区三区 | 强开小受嫩苞第一次免费视频 | av在线资源观看 | 献给魔王伊伏洛基亚吧动漫在线观看 | 夫妻露脸自拍[30p] | 国产成人精品午夜福利Av免费 | 日韩成人免费 | 在线日本中文字幕 | www伊人网| 污av| 久久综合中文字幕 | 奇米777第四色 | 国产又黄又骚 | 亚洲精品成人无码 | 欧美日韩色 | 欧美日韩在线视频免费观看 | 男人插入女人下面的视频 | 欧美一区二区三区在线观看视频 | 国产 日韩 欧美 制服丝袜 | 欧美精品一区二区三区视频 | 美女日批在线观看 | 国产精品美女视频 | 永久免费无码av网站在线观看 | 国语对白一区二区三区 | 精品国模一区二区三区欧美 | 成人黄色免费网站 | 精品国产一区二区三区久久久蜜月 | 亚洲精品小视频在线观看 | 在线免费播放av | 奇米第四色7777 | 国产不卡av在线播放 | 精品黄色在线观看 | 成人av免费在线看 | 天天做天天躁天天躁 | 男女爽爽视频 | 国产高潮国产高潮久久久91 | 综合激情四射 | 狠狠久久 | 老狼影院伦理片 | 日韩国产专区 | a级片在线观看视频 | 成人在线一区二区三区 | av中文网站 | 丰满熟妇人妻av无码区 | 亚洲一区二区人妻 | 男女做爰真人视频直播 | 综合网婷婷| 免费黄网在线观看 | 黄色免费网站视频 | 亚洲综合日韩 | 久草热线 | 日本天堂一区 | 亚洲欧美在线免费观看 | 日韩精品一区在线 | 人妻少妇一区二区三区 | 婷婷久久亚洲 | 亚洲精品123区 | 一区二区三区视频 | 超碰午夜 | 少妇诱惑av| 日韩一级黄色大片 | 国产又粗又长又爽 | 欧美用舌头去添高潮 | 一级片一区二区三区 | 日韩第六页 | 久久国产一级 | 国产成人短视频在线观看 | 中文字幕乱码在线 | 精品无码一区二区三区在线 | 亚洲黄色免费看 | 99精品在线免费观看 | 福利片第一页 | 日韩视频h| 正在播放亚洲 | 国产午夜福利视频在线观看 | 精品国产91乱码一区二区三区 | 欧美一级免费在线 | 这里只有精品视频在线 | 欧美v视频| 国内性视频 | 97麻豆视频 | 国产精品免费无遮挡无码永久视频 | 久久综合爱 | 日韩欧美国产一区二区三区 | 波多野结衣视频观看 | 婷婷色九月 | 激情小视频在线观看 | 天天插天天操 | 成人日皮视频 | 黄色av影院 | 青草国产 | 中文字幕5566| 黄频视频在线观看 | 一级免费毛片 | 97综合视频| 久久久久激情 | 中文字幕第页 | 国内精品国产三级国产aⅴ久 | 自拍1页 |