Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 是否迫切需要编译静态方法(JIT';ed)?_.net_Memory Management_Clr_Jit - Fatal编程技术网

.net 是否迫切需要编译静态方法(JIT';ed)?

.net 是否迫切需要编译静态方法(JIT';ed)?,.net,memory-management,clr,jit,.net,Memory Management,Clr,Jit,据我所知,CLR编译器对实例方法和静态方法的处理是相同的,并且每当第一次调用该方法时,IL代码都是JIT的。今天我和同事讨论了一下,他告诉我静态方法与实例方法的处理方式不同。i、 静态方法在程序集加载到应用程序域时立即进行JIT,而实例方法在第一次调用时进行JIT 我实际上很困惑,也不明白为什么静态方法应该被CLR急切地编译?我了解关键终结器对象的静态构造函数或终结器方法,或者何时使用受约束的执行区域。但是,如果某个类具有静态方法和实例方法的组合,我真的不确定为什么在包含该类的程序集加载到内存中

据我所知,CLR编译器对实例方法和静态方法的处理是相同的,并且每当第一次调用该方法时,IL代码都是JIT的。今天我和同事讨论了一下,他告诉我静态方法与实例方法的处理方式不同。i、 静态方法在程序集加载到应用程序域时立即进行JIT,而实例方法在第一次调用时进行JIT

我实际上很困惑,也不明白为什么静态方法应该被CLR急切地编译?我了解关键终结器对象的静态构造函数或终结器方法,或者何时使用受约束的执行区域。但是,如果某个类具有静态方法和实例方法的组合,我真的不确定为什么在包含该类的程序集加载到内存中时,所有静态方法都会被jit


请帮助我理解这种行为。

据我所知,静态方法与实例方法受到的威胁并没有什么不同,也许您的同事正在谈论的是在调用程序集中引用类型时实际调用的静态构造函数。因此感到紧张

更新4.0版(感谢@JulienLebosquain的指点)


.NET 4.0使用了一种所谓的惰性类型初始化,它基本上改变了行为,静态构造函数在第一次加入static字段时被调用。

查看使用WinDbg/SOS对方法进行JIT编译的时间,发现静态方法在调用之前没有编译

考虑以下类别:

class SomeType
{
    [MethodImpl(MethodImplOptions.NoInlining)]
    public void InstanceMethod()
    {
        Console.WriteLine("instance");
    }

    [MethodImpl(MethodImplOptions.NoInlining)]
    public static void TypeMethod()
    {
        Console.WriteLine("type");
    }
}
我使用noinline选项来防止编译器在发布版本中内联这些方法

如果我运行一个像下面这样的小应用程序并连接WinDbg,我可以在方法得到JIT编译时观察到

var st = new SomeType();

Console.WriteLine("attach");
Console.ReadLine();

Console.WriteLine("calling methods");
st.InstanceMethod();
SomeType.TypeMethod();

Console.ReadLine();
在附加点处,
SomeType
的方法表如下所示:

0:004> !dumpmt -md 0041387c
EEClass:         004114d4
Module:          00412e94
Name:            ConsoleApplication2.SomeType
mdToken:         02000007
File:                c:\temp\ConsoleApplication1\ConsoleApplication1\bin\Release\ConsoleApplication1.exe
BaseSize:        0xc
ComponentSize:   0x0
Slots in VTable: 7
Number of IFaces in IFaceMap: 0
--------------------------------------
MethodDesc Table
   Entry MethodDe    JIT Name
6d374960 6d076728 PreJIT System.Object.ToString()
6d368790 6d076730 PreJIT System.Object.Equals(System.Object)
6d368360 6d076750 PreJIT System.Object.GetHashCode()
6d3616f0 6d076764 PreJIT System.Object.Finalize()
0041c035 00413874   NONE ConsoleApplication2.SomeType..ctor()
0041c02d 0041385c   NONE ConsoleApplication2.SomeType.InstanceMethod()
0041c031 00413868   NONE ConsoleApplication2.SomeType.TypeMethod()
0:007> !dumpmt -md 0041387c
EEClass:         004114d4
Module:          00412e94
Name:            ConsoleApplication2.SomeType
mdToken:         02000007
File:            c:\temp\ConsoleApplication1\ConsoleApplication1\bin\Release\ConsoleApplication1.exe
BaseSize:        0xc
ComponentSize:   0x0
Slots in VTable: 7
Number of IFaces in IFaceMap: 0
--------------------------------------
MethodDesc Table
   Entry MethodDe    JIT Name
6d374960 6d076728 PreJIT System.Object.ToString()
6d368790 6d076730 PreJIT System.Object.Equals(System.Object)
6d368360 6d076750 PreJIT System.Object.GetHashCode()
6d3616f0 6d076764 PreJIT System.Object.Finalize()
0041c035 00413874   NONE ConsoleApplication2.SomeType..ctor()
004700e0 0041385c    JIT ConsoleApplication2.SomeType.InstanceMethod()
00470110 00413868    JIT ConsoleApplication2.SomeType.TypeMethod()
显式调用这些方法后,看起来如下所示:

0:004> !dumpmt -md 0041387c
EEClass:         004114d4
Module:          00412e94
Name:            ConsoleApplication2.SomeType
mdToken:         02000007
File:                c:\temp\ConsoleApplication1\ConsoleApplication1\bin\Release\ConsoleApplication1.exe
BaseSize:        0xc
ComponentSize:   0x0
Slots in VTable: 7
Number of IFaces in IFaceMap: 0
--------------------------------------
MethodDesc Table
   Entry MethodDe    JIT Name
6d374960 6d076728 PreJIT System.Object.ToString()
6d368790 6d076730 PreJIT System.Object.Equals(System.Object)
6d368360 6d076750 PreJIT System.Object.GetHashCode()
6d3616f0 6d076764 PreJIT System.Object.Finalize()
0041c035 00413874   NONE ConsoleApplication2.SomeType..ctor()
0041c02d 0041385c   NONE ConsoleApplication2.SomeType.InstanceMethod()
0041c031 00413868   NONE ConsoleApplication2.SomeType.TypeMethod()
0:007> !dumpmt -md 0041387c
EEClass:         004114d4
Module:          00412e94
Name:            ConsoleApplication2.SomeType
mdToken:         02000007
File:            c:\temp\ConsoleApplication1\ConsoleApplication1\bin\Release\ConsoleApplication1.exe
BaseSize:        0xc
ComponentSize:   0x0
Slots in VTable: 7
Number of IFaces in IFaceMap: 0
--------------------------------------
MethodDesc Table
   Entry MethodDe    JIT Name
6d374960 6d076728 PreJIT System.Object.ToString()
6d368790 6d076730 PreJIT System.Object.Equals(System.Object)
6d368360 6d076750 PreJIT System.Object.GetHashCode()
6d3616f0 6d076764 PreJIT System.Object.Finalize()
0041c035 00413874   NONE ConsoleApplication2.SomeType..ctor()
004700e0 0041385c    JIT ConsoleApplication2.SomeType.InstanceMethod()
00470110 00413868    JIT ConsoleApplication2.SomeType.TypeMethod()
也就是说,这些方法在实际调用之前不会进行JIT编译


(这是在.NET4.5上完成的)

我认为,在第一次加载类型时,它们就已经被jitted了。这通常是在加载程序集时发生的。您的同事对此有参考吗?也许这也解释了这种行为。否则,你会要求某人解释为什么有些事情可能根本不会发生。+1表示“没有区别对待”;关于静态构造函数,这不再是真的了,请看,我认为这很好地解释了方法是如何以及何时被JIT的。我将与我的同事分享此问答的链接。非常感谢你的帮助。回答得很好。考虑添加CLR/.NET版本,但是,以防万一这种变化在未来(或不总是相同的)。