大家都知道,vs
生成的是托管理程序(不管是VB.net
还是C#
),托管理程序是什么呢?托管这个词就能隐约得告诉我们,这个程序运行时不那么“单纯”,其实,托管理程序是不可以直接在CPU
上运行的,至于为什么,我们先看一下托管程序的组成部分。
一般托管理程序分为
PE
文件头:包含文件的类型,还有生成文件的时间
CLR
头:包含CLR
版本,入口方法的元数据标记
元数据:定义的类型和成员,引用的类型和成员
IL
(中间语言):编译源代码时生成的代码
现在来看一下托管理代码的运行,有这样一个简单的方法
using System;
class Democlass
{
static void Main()
{
Console.WriteLine("
谢谢!");
Console.WriteLine("
阅读。");
Console.WriteLine("
再见!");
}
}
当IDE
把把这个代码编译成exe
后,我们运行起这个exe(
当然是在装有.net Framework
的计算机上)
,首先CLR
会扫描所有这个Main
方法中的类型,然后会创建一个用于管理这些类型的数据结构,虽然本例中只有一种类型Console
,并且还是一个静态类。在这个数据结构中,存放着很到记录,每个记录与Console
的一个方法对应着,每个记录中,包含着一个指向方法实现的内存地址。
当这个数据结构初始化时,CLR
就将数据结构中的每条记录指向一个在CLR
中已定义好的方法CallMethod(
我假设的名子)
,这个方法能根据记录找到方法实现,当执行Console.WriteLine(“
谢谢!”)
时,会在数据结构中找到对应的记录,这个记录会调起CallMethod
方法,CallMethod
这个方法要实现
步骤如下:
A.
调用元数据中的WriteLine
方法(
因为记录与CallMethod
关联,记录指向方法的实现地址,所以CallMethod
能调用WriteLine
方法)
B.
从元数据中得到这个方法的IL
C.
申请一块内存空间
D.
把这个方法编译成CPU
指令,放到申请的内存空间中
E.
然后这个方法返回到这个数据结构中的WriteLine
方法对应的那条记录,用申请的内存地址替换掉这个记录包含指向方法实现的内存地址(这里就是用CPU
指令所在的内存地址替换掉了实现方法的内存地址)
F.
返回Main
方法的Console.WriteLine(“
阅读”)
当CLR
执行Main
方法的Console.WriteLine(“
阅读”)
时,因为记录中的内存地址已变成了CPU
指令所在的内存地址,所以这次,CallMethod
方法就不用被重新调用,这就说明,一旦该方法第一次被调用过,以后的调用就相对的节省资源了。直到该程序中止退出。
如果该程序在一台计算机上启动了两个,它们的这个该方法的CPU指令是不会被共用的,因为他们不在一个Application Domain,不能跨域访问。
本文转自桂素伟51CTO博客,原文链接:http://blog.51cto.com/axzxs/149964 ,如需转载请自行联系原作者