所以我试图准确理解.NET程序集何时被加载到.NET进程中。我读了this blog entry,它很好地解释了事情并证实了我认为已经知道的很多东西,但它也提出了一个我认为我有点误解的观点。
首次引用时,依赖程序集刚刚加载 代码
我认为这意味着何时以及第一次调用程序集时,程序集被加载到程序中。因此,如果我有一个类似于下面示例的程序,其中实例化RasDialer
类的行将永远不会被调用 - 我相信DotRas
程序集永远不会被加载到进程中而且我肯定是错了。
但是,如果代码在我注释掉的部分中确实无法访问 - 那么程序集将永远不会加载,但似乎如果有机会则会加载程序集。
这是我的小测试应用程序:
static void Main(string[] args)
{
Console.WriteLine("Before");
var dictionary = new Dictionary<int, string>();
PrintAssemblies(); // <- DotRas is loaded here for null check variant
if (dictionary == null)
{
// This line will never execute, but it does not matter
var dialer = new RasDialer();
}
// DotRas will not be loaded if I uncomment this and comment
// out the other if statement since it is truly unreachable
//if (false)
//{
// var dialer = new RasDialer();
//}
Console.WriteLine(Environment.NewLine + "After");
PrintAssemblies();
Console.ReadLine();
}
public static void PrintAssemblies()
{
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (var assembly in assemblies)
{
Console.WriteLine(assembly.GetName());
}
}
有没有简单的方法来判断何时将程序集加载到内存中?
在我在顶部链接的博客条目中 - 他的依赖程序集在调用PrintAssemblies()
之后才加载,但是对于我的依赖程序集在调用之前加载。所以它似乎不容易预测。
我是否正确地假设如果JIT编译器有可能需要依赖程序集中的类型,它将导致程序集被加载?
答案 0 :(得分:6)
只要检查引用程序集的方法,就会加载程序集。
粗略地说,当从IL转换为机器代码时。因此,只要您的方法引用另一个程序集中的代码,即加载程序集。
因此,在您的示例中,包含RasDialer
类的程序集将在第一次调用Main
时加载,就在方法执行开始之前。
你应该知道一些小方法是内联的(但可能不是在调试时)。因此,内联的代码将在内联后立即加载引用的程序集。
void A(object arg0) {
if (argO == null) {
ClassFromAssembly1.Call();
B();
C();
}
}
void B() {
ClassFromAssembly2.Call();
}
[MethodImpl(MethodImplOptions.NoInlining)]
void C() {
ClassFromAssembly3.Call();
}
第一次调用方法A
时,就在方法A
的代码开始执行之前,加载了Assembly1和Assembly2。
一旦第一次调用方法C
,就会加载Assembly3。
arg0
的值不能用于控制Assembly1的加载。当Assembly2将被加载时,无法确定(取决于B的内联)。可以使用arg0
的值来控制Assembly3的加载。