关于类的实例方法副本问题.

关于实例方法,在我头脑中也基本能理清了...只是不知对否,现将它说出来.
的确,过于死钻.net平台的细节并不是明智的学习方法.然而我觉得要编写出优秀,高效的托管代码,必须要对.net下的方法调用机制有个准确的理解.要明白当一个实例类的方法被调用时,在高级语言提供的简洁语法背后,CLR如何为我们找到该方法,并调用它...

请注意,我并非要探求CLR将实例方法处理成哪些数据格式,只是要清楚地理解它的原理...
一般来说,原理通常是简单的,而实现是复杂的.
比如就我目前所知的:
类型分为值类型和引用类型;

值类型的储存位置有两种情况:
1)当值类型作为类的成员被定义时,如int型,它将随着类的实例化而在托管堆上被分配空间.
2)当值类型作为方法的局部变量时,它将随着方法的调用被分配在线程的调用堆栈上,并随着方法的调用结束而自动pop出堆栈.

引用类型的储存位置也有两种情况:
1)当引用类型作为类 classA 的成员被定义时,存放实例引用的变量被分配在托管堆上classA的所属空间内,而它指向的实例对象则分配在托管堆上的另一处.所以当classA被GC回收后,其内部的引用也不存在了,同时该引用所指向的对象也因为成为不可达对象而在下一次GC运行时被GC回收.
2)当引用类型作为类的方法(不管是实例方法还是静态方法)内的局部引用变量实现时,该引用变量被分配在线程的调用堆栈上,而它所指向的实例则在托管堆上分配,同样,方法调用结束后,引用变量被弹出,它所指向的托管堆上的实例也成为不可达对象,将被GC回收.

类的方法被编译后,形成一串IL指令,当该方法第一次使用时,CLR将这些IL指令载入内存,并存放在程序区.可能在此之前,CLR已经提前将该类的方法表也载入内存了,方法表存放的是该类的每个方法的地址.如下:
--------------------
| method1--->地址1 |
| method2--->地址2 |
| method3--->地址3 |
 -------------------
而在每个类实例(注意是实例)内部,都有一个类的附加成员(相对于值类型而言):一个方法表指针,它指向的是上图这个方法表在内存中的地址.(我们不考虑更细节的东西,否则会增加理解的难度,实际上也不用我们去理解,否则微软靠什么吃饭??^^,另外还有一个附加成员是一个同步块之类的东东吧,用于线程的同步的.)

这样当我们在程序中调用一个方法时,在运行时,CLR会根据该类的方法表指针找到方法表,然后在方法表中找到对应的方法的IL指令的存放地址,以此将IL指令加载到线程的调用堆栈中,同时还会在堆栈上为该方法内的值类型分配空间,为该方法内声明的引用类型分配内存(在托管堆上),
调用结束后,即堆栈用IL指令转换的操作数完成计算操作后,所有分配的变量(值类型或引用类型)都会被弹出.(引用类型变量所指向的实例会成为不可达对象,会被GC回收)

注意,我现在只是将IL指令作为讨论对象...实际上执行的还是JIT编译器编译的本地机器码.只是它更涉及到更复杂的操作,如本地机器码还有自己的调用堆栈..等...这就不是我的脑袋所能相通的了...所以不用去想它..我只要想通这样流程就可以对我写程序有针对性的指导了.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值