.Net CLR運行時的相互關系

昨天同事在部門分享中談到了Android的虛擬機機制。正好想到我在學習.Net CLR的時候研究過CLR運行時的相互關系,所以拿出來分享一下。

我們在本文中要搞清楚類型,對象,線程棧,托管堆的關系。

首先你需要對內存管理、.net框架和.net clr有個基本的了解。.net框架

線程棧

我們先來看看一個加載了CLR的Microsoft Windows的進程。一個進程可能會有多個線程。一個線程創建時,會分配到1MB大小的棧。
作用

  • 保存向方法傳遞的實參
  • 保存方法內部定義的局部變量

棧是高位向低位地址構建的

一個線程的棧,準備調用M1方法

image.png

分配局部變量name的內存

image.png

M1調用M2方法,把實參s壓入棧,調用方法時,還需要將“返回地址”壓入棧,被調用方法結束后,返回這個位置。

image.png

M2開始執行,最終到達return語句,指令指針被設置為棧中的返回地址,M2的棧幀(指當前線程中調用棧的一個方法調用,每個方法調用都會在調用棧中創建并壓入一個棧幀)會被釋放。線程棧如下圖

image.png

線程將繼續執行M1在調用M2之后的代碼

托管堆

我們假定有這兩個類的定義

image.png

window進程已經啟動,托管堆已初始化,已經創建了一個線程。該線程已經調用了一些代碼,現在馬上要調用M3。

image.png

這時候CLR要做的事情

  • 確保M3內部引用的所有類型的程序集都已加載
  • 利用程序集的元數據創建類型對象(Type Object表示類型本身)

類型對象包括

  • 類型對象指針(Type Object Pointer)和同步塊索引(sync block index)
  • 靜態字段
  • 方法表
image.png

當前面的事情做好后,開始執行M3的本地代碼,首先為局部變量分配內存,CLR會自動將局部變量初始化成null或0

image.png

接下來,M3代碼開始構造一個Manager實例(也就是一個Manager對象),步驟如下

  1. 初始化類型對象指針,并指向與對象對應的類型對象
  2. 初始化同步索引塊
  3. 將所有實例字段初始化
  4. new操作符會返回對象的內存地址,將之保存到變量e

對象包括

  • 類型對象指針(Type Object Pointer)和同步塊索引(sync block index)
  • 實例字段


    image.png

M3下一行調用Employee的靜態方法Lookup。調用靜態方法的步驟

  1. CLR會定位與定義靜態方法的類型相對應的類型對象
  2. JIT編譯器在類型對象的方法表找到該方法,對方法進行JIT進行編譯(如果需要的話),再調用JIT編譯的代碼
  3. Lookup方法在堆上構造一個新的Manager對象,并返回地址
  4. M3將地址存到變量e

需要注意的是,變量e已經引用了新的對象。原來的對象沒有變量引用,GC將會對其自動進行回收。

image.png

M3的下一行代碼調用虛實例方法GenProgressReport。調用一個虛實例方法時,JIT編譯器要在方法中生成一些額外的代碼;方法每次調用時,都會調用這些代碼。

  1. 檢查發出調用的變量,跟隨地址來到發出調用的對象,檢查對象的類型對象指針,找到類型對象,并在方法表中定位該方法。(和非虛方法的區別:非虛關心的是變量e的類型,而虛關心的是變量e所指向的對象的類型)
  2. JIT編譯器在類型對象的方法表找到該方法,對方法進行JIT進行編譯(如果需要的話),再調用JIT編譯的代碼
image.png

Manager和Employee類型對象也有類型對象指針,那這些指針是指向哪里的呢?實際上,CLR在進程運行時,會為System.Type創建一個特殊的類型對象,Manager和Employee的類型對象的類型對象指針都指向它。System.Type的類型對象指針就指向自身。
System.Obejct有一個GetType方法,返回類型對象指針,這樣就可以判斷系統中任何對象(也包括類型對象)的類型了。

image.png
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 本章內容: 1.所有類型都從System.Object派生2.類型轉換3.命名空間和程序集4.運行時的相互關系 4...
    clihen閱讀 417評論 0 0
  • [TOC] 內存管理 一、托管堆基礎 在面向對象中,每個類型代表一種可使用的資源,要使用該資源,必須為代表資源的類...
    _秦同學_閱讀 3,871評論 0 3
  • 第二部分 自動內存管理機制 第二章 java內存異常與內存溢出異常 運行數據區域 程序計數器:當前線程所執行的字節...
    小明oh閱讀 1,210評論 0 2
  • 《深入理解Java虛擬機》筆記_第一遍 先取看完這本書(JVM)后必須掌握的部分。 第一部分 走近 Java 從傳...
    xiaogmail閱讀 5,175評論 1 34
  • 所有知識點已整理成app app下載地址 J2EE 部分: 1.Switch能否用string做參數? 在 Jav...
    侯蛋蛋_閱讀 2,507評論 1 4