源代码,IL和JIT编译器之间的关系:
prologue:序幕 epilogue:尾声 序幕代码执行时必须在线程栈中为局部变量分配内存。CLR会自动将所有的局部变量初始化为null或0.
托管堆 堆上的所有对象都包含两个额外的成员:类型对象指针(type object pointer)和同步块索引(sync block index)
在每个类型对象中都包含一个方法表,在方法表中,类型定义的每个方法都对应一个记录项。
任何时候在堆上新建一个对象,CLR都会自动初始化内部类型对象指针成员,让它引用与对象对应的类型对象。此外,CLR会先初始化同步块索引,并将对象的所有实例字段设为null或0.再调用类型的构造器。new操作符会返回对象的内存地址。
调用一个静态方法时,CLR会定位与定义静态方法的类型对应的类型对象,然后JIT编译器在类型对象的方法表中查找与被调用的方法对应的记录项,对方法进行JIT编译,再调用JIT编译的代码。
调用一个非需实例方法时,JIT编译器会找到与发出调用的那个变量的类型对应的类型对象,然后JIT编译器在类型对象的方法表中查找引用了被调用方法的记录项,对方法进行JIT编译,然后再调用JIT编译后的代码。
调用一个虚实例方法时,JIT编译器要在方法中生成一个额外的代码,方法每次调用时,都会执行这些代码。这些代码首先检查发出调用的变量,然后跟随地址来到发出调用的对象。然后代码检查对象内部的“类型对象指针”成员,这个成员指向对象的实际类型。然后,代码在类型对象的方法表中查找引用的被调用方法的记录项,对方法进行JIT编译(如果需要的话),再调用JIT编译过的代码。
System.Object的GetType()方法返回的是存储在指定对象的“类型对象指针”成员中的地址。换言之,GetType()方法返回的是指向类型对象的一个指针。