类型,对象,线程栈,托管堆在运行时的关系,以及clr如何调用静态方法,实例方法,和虚方法
1、线程栈
window的一个进程加载clr。该进程可能含有多个线程,线程创建的时候会分配1MB的栈空间。
如图:
void Method()
{
string name=”zhangsan”; //name 被放入栈里面
Method2(name); //1参数变量s 被压入栈,s引用name的地址 2.返回地址被压入栈,方法执行完(method2的 return)指针指向此返回地址
return;
}
void Method2(string s)
{
int32 length=s.Length;
int32 tally;
return; //methed2执行完后,指针指向线程栈的返回地址,method2的栈帧展开
}
2.运行时关系
现有如下2个类型
internal class Employee
{
public int32 M1(){…..};
public virtual string M2(){…..};
public static Employee M3(string name){…..};
}
internal sealed class Manager:Employee
{
public override string M2(){…..};
}
准备:window进程已经开启,clr已经加载到进程里面,托管堆已经初始化,线程栈也已经被创建(连同它的1MB的栈空间)
void M4()
{
Employee e;
int32 age;
e=new Manager();
e=Employee.M3(“zhangsan”);
age=e.M1();
e.M2();
}
a.首先介绍下new 关键字的执行的时候会执行什么
1.clr计算出类型的所有实例字段的字节和所有基类型的实例字段的字节长度,创建类型对象指针和同步块索引(也计算在字节长度内)
2.在托管堆上分配第一步长度的空间
3.初始化类型对象指针(指向类型对象)和同步块索引
4.调用类型的实例构造器。
b.运行关系图
c.详细解释
1.M4运行的时候 先在线程栈 压入e和age两个局部变量
2.e=new Manager();会在托管推上分配Manager和所有基类的实例字段字节大小,初始化类型对象指针,指向Manager类型对象。
3 Employee.M3(“zhangsan”); 第一个对象将被垃圾回收器回收。他会找到调用它的类型,然后去类型对象的方法列表中找到这个方法,
然后JIT进行编译,然后执行。
4.e.M1();找到e对象类型对应的对象类型Manager(没有,回溯到Employee中找),在方法列表中找到对应的方法,编译执行(能够向上回溯是因为在派生类中有指向基类的引用)
5.e.M2()找到e对象的的对象类型(Manager),调用Manager类型对象方法列表中的M2 而不是Employee中的。