我有静态类,有静态方法,如下所示:
public static StaticTest
{
public static void DoSomeWork()
{
/// Do Some work
}
}
Run Code Online (Sandbox Code Playgroud)
当DoSomeWork()
函数被调用时,如何CLR管理功能的引用,因为它是明显的静态类的实例不能创建?
在这种情况下调用函数的场景背后的机制是什么?
假设你有:
class Foo
{
public void Bar()
{
// instance
}
public static void Fiz()
{
// instance
}
}
Run Code Online (Sandbox Code Playgroud)
你也是:
var temp = new Foo();
Foo.Fiz();
temp.Bar();
Run Code Online (Sandbox Code Playgroud)
你的代码被翻译成类似的东西:
var temp = new Foo();
Foo.Fiz();
Foo.Bar(temp);
Run Code Online (Sandbox Code Playgroud)
在这个被翻译成类的一个隐藏的参数(第一个)。在英特尔的 C++ 中,这称为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
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,Foo.Fiz
是一个直接的call 00007FFBD46ECA40
,而temp.bar()
第一个检查null
(我认为,mov
+ cmp
),然后放入rcx
引用并执行call
当CLR加载包含静态成员的程序集时,这些成员将被放置在内存中名为High Frequency Heap的专用空间中.高频堆中的对象永远不会收集垃圾,以确保静态变量在应用程序的整个生命周期中都可用.