[英]How does CLR manage when a static method is called?
我有靜態類,有靜態方法,如下所示:
public static StaticTest
{
public static void DoSomeWork()
{
/// Do Some work
}
}
當DoSomeWork()
函數時,CLR如何管理函數引用,因為很明顯無法創建靜態類的實例?
在這種情況下調用函數的場景背后的機制是什么?
當CLR加載包含靜態成員的程序集時,這些成員將被放置在內存中名為High Frequency Heap的專用空間中。 高頻堆中的對象永遠不會收集垃圾,以確保靜態變量在應用程序的整個生命周期中都可用。
假設你有:
class Foo
{
public void Bar()
{
// instance
}
public static void Fiz()
{
// instance
}
}
你也是:
var temp = new Foo();
Foo.Fiz();
temp.Bar();
您的代碼翻譯為:
var temp = new Foo();
Foo.Fiz();
Foo.Bar(temp);
這被翻譯為類的隱藏參數(第一個)。 在C ++ for Intel中,這稱為thiscall調用約定 。 對於靜態函數,只是沒有這個參數。
如果你在該代碼上打開反匯編函數,你會發現它是這樣的:
var temp = new Foo();
00007FFBD48042EC lea rcx,[7FFBD48563D8h]
00007FFBD48042F3 call 00007FFC33E42400
00007FFBD48042F8 mov qword ptr [rsp+2B0h],rax
00007FFBD4804300 mov rax,qword ptr [rsp+2B0h]
00007FFBD4804308 mov qword ptr [rsp+2B8h],rax
00007FFBD4804310 mov rcx,qword ptr [rsp+2B8h]
00007FFBD4804318 call 00007FFBD46ECA48
00007FFBD480431D mov r11,qword ptr [rsp+2B8h]
00007FFBD4804325 mov qword ptr [rsp+30h],r11
Foo.Fiz();
00007FFBD480432A call 00007FFBD46ECA40
temp.Bar();
00007FFBD480432F mov r11,qword ptr [rsp+30h]
00007FFBD4804334 cmp byte ptr [r11],0
00007FFBD4804338 mov rcx,qword ptr [rsp+30h]
00007FFBD480433D call 00007FFBD46ECA38
正如您所看到的, Foo.Fiz
是直接call 00007FFBD46ECA40
,而temp.bar()
首先檢查null
(我認為是mov
+ cmp
),然后將rcx
引用並進行call
當方法開始執行時,CLR會識別方法中使用的類型,並確保加載引用的程序集。
然后,它為方法中的每個引用類型創建“類型對象”(如果它們不存在)。
每個類型對象包含類型對象指針,同步塊索引,靜態字段和方法表(其中包含每種類型方法的一個條目)。
public void DoSomething()
{
InstanceClass objectInstance = new InstanceClass();
objectInstance.MethodName();
StaticClass.MethodName();
// i.e.here clr creates Type Objects for Instance class and StaticClass in the heap
}
當new
運算符用於創建類的對象時,CLR會自動在該類的實例中創建一個類型對象指針並初始化它以引用相應的類型對象。
當調用INSTANCE(非虛擬)方法,即objectInstance.MethodName()
,CLR根據使用的變量類型識別Type對象,並在類型對象的方法表中找到方法,然后在方法中找到JIT。
當調用靜態方法即StaticTest.DoSomeWork()
,CLR(JIT編譯器)將根據類名識別靜態類的“類型對象”,並且JIT編譯器在相應類型的方法表中查找方法對象然后是JIT的方法。
函數體作為一組IL指令存在於程序集中。 當您調用該函數時,IL結果如下:
call void[assembly]StaticTest:DoSomeWork()
所以運行時查看DoSomeWork,JIT的IL主體的“程序集”並執行它。 從另一個角度來看,靜態函數就像常規函數一樣,但沒有“this”引用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.