繁体   English   中英

当调用静态方法时,CLR如何管理?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM