简体   繁体   English

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

[英]How does CLR manage when a static method is called?

I have static class having static methods as shown below: 我有静态类,有静态方法,如下所示:

public static StaticTest
{
   public static void DoSomeWork()
   {
    /// Do Some work
   }
}

When DoSomeWork() function is called, how does CLR manage the function references as it is obvious that an instance of static class cannot be created? DoSomeWork()函数时,CLR如何管理函数引用,因为很明显无法创建静态类的实例?

What is the mechanism behind the scene to call the function in this case? 在这种情况下调用函数的场景背后的机制是什么?

When the CLR loads an assembly containing static members, those members are placed in a dedicated space in memory called High Frequency Heap . 当CLR加载包含静态成员的程序集时,这些成员将被放置在内存中名为High Frequency Heap的专用空间中。 Objects in the High-Frequency Heap are never Garbage collected to make sure that the static variables are available throughout the lifetime of the application. 高频堆中的对象永远不会收集垃圾,以确保静态变量在应用程序的整个生命周期中都可用。

Let's say you have: 假设你有:

class Foo
{
    public void Bar()
    {
        // instance
    }

    public static void Fiz()
    {
        // instance
    }
}

And you do: 你也是:

var temp = new Foo();
Foo.Fiz();
temp.Bar();

Your code is translated to something like: 您的代码翻译为:

var temp = new Foo();
Foo.Fiz();
Foo.Bar(temp);

The this is translated as an hidden parameter of the class (the first one). 被翻译为类的隐藏参数(第一个)。 In C++ for Intel this is called the thiscall calling convention . 在C ++ for Intel中,这称为thiscall调用约定 For static functions, simply there isn't this parameter. 对于静态函数,只是没有这个参数。

If you open the Disassembly function on that code you'll see that it is something like: 如果你在该代码上打开反汇编函数,你会发现它是这样的:

            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  

As you can see the Foo.Fiz is a direct call 00007FFBD46ECA40 , while the temp.bar() first does a check for the null (I think, the mov + cmp ), then puts in rcx the reference and does the call 正如您所看到的, Foo.Fiz是直接call 00007FFBD46ECA40 ,而temp.bar()首先检查null (我认为是mov + cmp ),然后将rcx引用并进行call

When a method starts executing, CLR identifies the types used in the method and ensures that referred assemblies are loaded. 当方法开始执行时,CLR会识别方法中使用的类型,并确保加载引用的程序集。

Then it creates "Type Objects" for each referenced type in the method (if they are not existing). 然后,它为方法中的每个引用类型创建“类型对象”(如果它们不存在)。

Each type object contains Type Object Pointer, Sync Block Index, static fields and a Method table (which contains one entry for each method of the type). 每个类型对象包含类型对象指针,同步块索引,静态字段和方法表(其中包含每种类型方法的一个条目)。

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
}

在此输入图像描述

When the new operator is used to create an object of a class, CLR automatically creates a Type Object Pointer in the instance of that class and initializes it to refer the corresponding Type Object. new运算符用于创建类的对象时,CLR会自动在该类的实例中创建一个类型对象指针并初始化它以引用相应的类型对​​象。

When an INSTANCE (non virtual) method is called, ie objectInstance.MethodName() , CLR identifies the Type Object based on the variable type used and finds the method in the type object's method table and then JIT's the method. 当调用INSTANCE(非虚拟)方法,即objectInstance.MethodName() ,CLR根据使用的变量类型识别Type对象,并在类型对象的方法表中找到方法,然后在方法中找到JIT。

When a static method is called ie StaticTest.DoSomeWork() , CLR (JIT Compiler) will identify the "Type Object" of the static class based on the class name and the JIT compiler looks for the method in the method table of the corresponding Type Object and then JIT's the method. 当调用静态方法即StaticTest.DoSomeWork() ,CLR(JIT编译器)将根据类名识别静态类的“类型对象”,并且JIT编译器在相应类型的方法表中查找方法对象然后是JIT的方法。

The function body exists in the assembly as a set of IL instructions. 函数体作为一组IL指令存在于程序集中。 When you call that function, the IL resulting is something like: 当您调用该函数时,IL结果如下:

call     void[assembly]StaticTest:DoSomeWork()

so the runtime looks into "assembly" for the IL body of DoSomeWork, JIT and execute it. 所以运行时查看DoSomeWork,JIT的IL主体的“程序集”并执行它。 By another point of view, static function are just as regular function, but without a "this" reference to work with. 从另一个角度来看,静态函数就像常规函数一样,但没有“this”引用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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