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?
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 . 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 . 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
When a method starts executing, CLR identifies the types used in the method and ensures that referred assemblies are loaded.
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.
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.
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.
The function body exists in the assembly as a set of IL instructions. When you call that function, the IL resulting is something like:
call void[assembly]StaticTest:DoSomeWork()
so the runtime looks into "assembly" for the IL body of DoSomeWork, JIT and execute it. By another point of view, static function are just as regular function, but without a "this" reference to work with.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.