详细大家可以参考我的博客:http://blog.csdn.net/youbl/article/details/9493369
具体测试代码:
项目文件1:
class Program
{
    static void Main(string[] args)
    {
        try
        {
            new MethodNoTest().Run();
        }
        catch(Exception exp)
        {
            Console.WriteLine("外部出错:" + exp);
        }
        try
        {
            new MethodNoTest().aa();
        }
        catch(Exception exp)
        {
            Console.WriteLine("外部出错2:" + exp);
        }
    }
}
项目文件2:
public class MethodNoTest
{
    public void Run()
    {
        Console.WriteLine("开始");
        try
        {
            nameSp.abc.xxx();
        }
        catch (Exception exp)
        {
            Console.WriteLine("内部出错:" + exp);
        }
        Console.WriteLine("完成");
    }
    public void aa(){
        Console.WriteLine("abc");
    }
}
在编译成功后,再把nameSp.abc类的xxx方法删除,编译后的dll拷贝到exe目录下,执行结果是:
外部出错:System.MissingMethodException:找不到方法:“void nameSp.abc.xxx()”很奇怪吧,为什么连“开始”和“完成”都没有输出呢?答案是编译完成的dll,只是il代码,并不是真正的机器码,.net程序在运行前还要把il代码编译转换为机器码执行,上面程序步骤:
1、Program类编译正常,执行到new MethodNoTest().Run();
2、发现MethodNoTest的Run方法未编译为机器码,开始编译,发现方法里引用的abc类没有定义xxx这个方法,就直接抛出异常,所以Run这个方法里的任何一句代码都没有执行,更不要说里面的try能起作用了。但是MethodNoTest类的另外一个方法aa,能正常调用和执行===========================================
不过这时有个疑问,在把il代码编译为机器码时,对同一个dll里的所有类,不是一次性生成机器码吗?
难道是对执行到的类每个方法逐一去生成机器码?
从我的测试结果里,Run方法的任何代码都无法执行,而另一个实例方法aa,却能正常调用执行或者是Run方法直接生成一句抛异常的机器码?对il到机器码这块不了解,希望有大牛指导一下

解决方案 »

  1.   

    CLR在第一次运行Run()之前,要把该方法的il代码,编译成本地代码。
    该编译过程(JIT)如果没有办法找到方法中的调用目标,就可能抛出MissingMethodException。这种情况Run函数没有机会得到运行。
      

  2.   

    也就是说,是一个方法一个方法进行jit的吗?
    如果第一次jit失败,后续就不再对这个方法进行编译了吧?
      

  3.   

    是的,如果assembly没有重新加载,每个方法只会编译一次(针对桌面CLR)
    这里有个简单介绍http://blogs.msdn.com/b/davidnotario/archive/2004/10/26/247792.aspx
      

  4.   

    嗯,自己也找了一篇文章:
    http://www.pin5i.com/showtopic-21313.html
    CLR使用类型的方法表来路由所有的方法调用。只有当要调用某个方法时,JIT编译器才会将IL的方法体编译为相应的本机机器码版本。