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

淺析C#運行時相互關系

開發 后端
本文將介紹C#運行時相互關系,包括運行時類型、對象、線程棧和托管堆之間的相互關系,靜態方法、實例方法和虛方法的區別等等。

  本博客主要講述運行時類型、對象、線程棧和托管堆之間的相互關系,靜態方法、實例方法和虛方法的區別,以及內存的分配和回收。

  線程棧:在一個進程中可能包含多個線程,一個線程在創建的時候,會分配到一個大小1MB大小的棧,棧用于存儲方法的實參、形參以及方法內部的局部變量,棧是從高位內存地址向地位地址構建的,由于棧有先進后出的特點,所以先定義的變量后被回收。

  下面來看一個簡單的例子,讓你更了解線程棧

  由于線程棧是從高位開始分配內存,先分配的我就畫在上面了,在調用F1();方法時,分配內存的順序是:name->n->F2的返回地址->Age->name;回收內存的順序當然是反過來的。在一個方法中,應該包含一些序幕代碼,進行一些初始化工作,還有一些尾聲代碼,等方法執行完成之后做一些回收工作。由于方法的返回地址先分配,在方法執行完成的時候回到返回地址,遞歸太深就容易出現棧溢出,請看我的《遞歸再一次讓哥震驚了》,因為參數、局部變量都必須等到方法返回的時候才能回收。

  在介紹托管堆之前先看看兩個簡單的類:

 

  1.   publicclassPerson  
  2.   {  
  3.   privateintheight;  
  4.   publicvoidSetHeight(intheight)  
  5.   {  
  6.   this.height = height;  
  7.   }  
  8.   publicvirtualvoidSay(stringword) { }  
  9.   publicstaticstringHead()  
  10.   {  
  11.   return"my head";  
  12.   }  
  13.   publicstaticintAge = 100;  
  14.   }  
  15.   publicclassStudent : Person  
  16.   {  
  17.   publicoverridevoidSay(stringword)  
  18.   {  
  19.   Console.WriteLine(word);  
  20.   }  
  21.   } 

 

 

  1. staticvoidMain(string[] args)  
  2.   {  
  3.   Person student = newStudent();  
  4.   student.Say("Hello cth");  
  5.   student.SetHeight(172);  
  6.   Person.Head();  
  7.   Console.ReadLine();  
  8.   } 

 

  CLR會在第一次訪問一個對象時加載該對象,在這里,定義變量student時會為Person對象在線程棧中分配內存,第一次加載嗎,在構造一個Student對象之前先要加載Student對象,并為Student類型對象分配內存,并構建一個Student對象。對象的地址存入線程棧中的局部變量student 中,我們知道類型對象的內容包含:類型對象指針、同步索引塊、靜態字段和方法(靜態的和非靜態的),不管是類型對象、還是實例類型都必須有類型對象指針、同步索引塊;我們知道靜態字段屬于類,被這個類的所有實例共享,當然靜態字段的內存是在類型本身中分配的,方法也是類的所有實例共享的,他的內存也是在類型本身中分配的,在每一個類型對象中都有一個方法表,類中定義的方法都有一個對應的項。

  在構造一個對象的實例時,只需要為類型對象指針、同步索引塊、該對象的實例字段分配內存,對于對象實例來說,類型對象指針可以讓實例訪問類型對象中德靜態字段、方法等。

  Student是線程棧中的定義的一個局部變量,保存Student的一個實例的在托管堆中的地址,所以他可以訪問Student對象中的字段,方法,其實訪問方法是通過類型對象指針訪問類型對象Student中的方法表中對象的項。

  Say方法的執行過程:變量student指向的是一個Student對象,調用的當然是Student類型對象中的Say方法,盡管在定義student的時候是Person類型,因為他是引用類型,他指向的是托管堆中Student對象的內存,然后遍歷該對象的方法表,找到該方法調用。

  特別說明虛方法,JIT在虛方法中加了一些額外的代碼,方法每次調用的時候都會執行這些代碼,這些代碼會檢查發出調用的變量,然后根據這個變量找到其應用的對象,然后調用這個對象的方法,若沒有這些代碼,你覺得CLR是調用父類的方法還是調用之類的方法呢,虛方法帶來方便的同時,也多了這些必須的檢查的代碼。

  SetHeight方法的執行過程:和Say方法前面是一樣,只是在遍歷Student對象的方法表時沒有找到該方法,我們知道父類中定義的非private方法都可以被子類繼承,是因為每個類型都定義了一個字段引用了他的基類,如果一個類調用的方法那個方法不是自己定義的,那么編譯器會回溯類層次結構,一直到基類Object,找到相關的方法并調用,如果沒有找到相關的方法就報了異常唄。所以SetHeight方法其實調用的是Person中的SetHeight方法。

  Head方法的執行:由于Head方法是靜態方法和上面兩個方法有所不同,調用靜態方法的時候,CLR會定位與靜態方法對象的類型對象,然后在對應實例對象對象的方法表中查找相關的記錄項,如果沒有找到,同樣會回溯。

  當執行完student.SetHeight(172);時,student在也沒有被引用,成為垃圾,在其所在的方法返回之前將會被回收,也就是說student實例對象被回收,釋放其所在的內存,而類型對象不會被回收,類型對象的生成周期是:對象被加載到CLR中,直到其所在的AppDomain卸載。靜態字段是他所引用類型的跟,所以被靜態類型引用的對象永遠不會被回收,如果其引用的是一個集合對象,并向其中不斷的加入元素的話,就會造成內存泄露,更多關于內存管理垃圾回收,請看我的另一篇博客《垃圾回收--代》

  作者:陳太漢

  博客:http://www.cnblogs.com/hlxs/

【編輯推薦】

  1. 詳解C#中不同類的類型
  2. 淺談C#中標準Dispose模式的實現
  3. C#選擇正確的集合進行編碼
  4. C# 4.0新特性:協變與逆變中的編程思想
  5. C#應用Attribute特性 代碼統計分析
責任編輯:彭凡 來源: 博客園
相關推薦

2023-01-03 09:10:21

2015-07-20 15:44:46

Swift框架MJExtension反射

2009-08-27 16:18:47

C#類C#結構體

2024-03-21 09:15:58

JS運行的JavaScrip

2009-02-10 09:03:59

動態語言CLRVB.NET

2010-01-27 14:14:48

C++程序運行時間

2011-08-19 15:05:29

異常處理

2010-06-17 19:07:12

UML對象

2010-01-18 11:05:24

C++

2009-09-01 16:35:16

C#單元測試

2019-07-12 09:30:12

DashboardDockerDNS

2021-09-11 15:38:23

容器運行鏡像開放

2010-04-26 10:32:55

Oracle 10g

2025-03-03 09:10:00

C++開發

2009-08-14 17:45:52

C# ArrayLis

2009-08-17 18:34:50

C# ChangeCo

2009-08-07 17:25:37

C# SortedLi

2023-11-21 16:31:51

C++語言

2023-07-28 10:42:43

2020-12-07 13:31:43

GoMutex開發者
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 三级av在线 | 久久国产精99精产国高潮 | 91精品国产自产精品男人的天堂 | 国产午夜精品一区二区三区嫩草 | 在线不卡视频 | 国产精品高潮呻吟久久aⅴ码 | www.天堂av.com | 欧美乱码精品一区二区三区 | 日韩中文字幕网 | 毛片网站免费观看 | 成人av电影天堂 | 亚洲综合成人网 | 日韩av在线不卡 | 国产成人精品视频在线观看 | 国产日韩一区二区三免费高清 | 人人干97| 欧美激情精品久久久久 | 国产高清视频一区 | 久久精品中文字幕 | 中国一级大毛片 | 国产三区精品 | 午夜精品久久久久久久 | 精品国产一区三区 | 鲁视频| 国产伊人精品 | 亚洲综合99| 激情在线视频网站 | 337p日韩 | 九九免费观看视频 | 色视频一区二区 | 一区二区三区四区在线视频 | 国产视频在线一区二区 | 欧美精品在线播放 | 国产伦精品一区二区三区照片91 | 国产精品亚洲精品日韩已方 | 亚洲精品一区二区三区蜜桃久 | 久草福利 | 一区二区高清 | 日本一区二区高清不卡 | av在线一区二区三区 | 亚洲精品1区 |