有一个旧问题询问C#是否每次都进行JIT编译,著名的Jon Skeet回答说:“只要我们谈论的是没有NGENed的桌面应用程序,它只会编译一次”。我想知道这个2009年的信息是否仍然正确,我想通过实验和调试来弄清楚这一点,可能需要在JITter上设置断点,并使用WinDbg命令检查对象和方法。
到目前为止我的研究
我知道.NET内存布局考虑了每个对象的头(位于地址A-4)和方法表(位于地址A+0),然后才是实际数据(位于地址A+4)。因此,每个对象都可能具有不同的方法表,因此可以具有不同的JIT方法。
为什么我对该语句的正确性表示怀疑?
我们进行了并行编程的研讨会,培训师声称每个线程的每个对象都会进行JIT编译。这显然对我来说毫无意义,我能够编写一个反例应用程序。
很不幸,以下其他主题也出现了,我也想写一个演示:
- 新的.NET框架
- 应用程序域
- 代码访问安全性
链接的答案是在.NET 3.5发布时编写的。自那以后它没有实质性地改变过,即它没有为.NET 4.0、4.6和4.6接收更新。
关于应用程序域,我个人认为我可以卸载应用程序域,这将卸载程序集。如果一个程序集被卸载了,它就不存在了,IL代码也随之消失。因此,我可以想象创建一个应用程序域并重新加载程序集可能会导致再次JIT方法。
关于代码访问安全性,我不确定JIT编译器是否根据当前权限考虑它,或者它是否在运行时通过反射完成。如果它是由JIT编译器完成的,那么编译后的代码将有所不同,取决于权限集。