C#源代码编译成为本地代码的编译过程

如题所述

很有兴趣的话,可以去阅读下Jeffrey Ritchie的《Clr via C#》,目前出到第三版,英文好的话强烈推荐看英文版的,而且我有该电子书和实体书。

下面讲下我的理解:大致上不会出什么差错的,细节部分你可以参照上面的书籍!

1. 首先,c#源码经过c#编译器被编译成托管模块(IL中间代码、元数据(Metadata))

2. 然后,使用C#编译器以及程序集链接器(Assembly Linker ---- AL.exe)将上述托管模块以及项目的资源文件Combine(整合)成一个程序集(Assembly)

上述程序集就是你所看到的exe文件或者dll文件等等,程序集中包含了manifest描述文件,是该程序集内容以及关系的一个清单,具体的内容你可以参见JR的书跟Java中的类似!

双击该exe运行的时候:

3. 最后,运行时,CLR装载对应的程序集,使用内部的三个即时编译器(常用的为JIT),再去根据本机的环境去进行相应的优化(针对CPU优化等等),即时的翻译成本地机器指令去执行。

还有一个本地化代码生成工具,NGen.exe~~

这个最好能去看看那本JR的神作!细节不是我三言两语能讲清的~~

温馨提示:答案为网友推荐,仅供参考
第1个回答  推荐于2017-11-24
很抱歉,这是不可能的。C#语言程序不可能脱离.net框架,就像Java一样,C#语言的运行环境是.net framework,.net对于C#就像Java虚拟机对于Java语言一样。另外,C#是一种有限制语言,.net负责保证代码访问的安全特性,C++是唯一可以允许程序员开发无限制低级程序的语言,.net不仅负责为代码提供运行支持,还负责保证程序的安全性,一种受限制的语言是不能脱离限制程序的控制的,对于C#,.net就是控制系统,因此,C#程序不可能脱离.net环境。

===================================================
对补充的答复:

这恐怕也是不行的。在以往的PE结构的程序中,因为不同的CPU拥有不同的指令集,所以为了适应客户机的硬件的不同,往往会开发一个程序的不同版本,微软为了解决这个问题,在.net中准备了多个即时编译器(JIT),当一个中间语言的程序在客户机上运行时,JIT会根据客户机当前的硬件配置和操作系统等方面的情况对代码进行优化,然后生成本地化的机器代码,这个机器代码并不是全部程序的代码,而是只生成程序运行必须的部分,其它的会在执行时根据需要动态生成。微软官方对项技术的解释为:
“JIT 编译考虑了在执行过程中某些代码可能永远不会被调用的事实。它不是耗费时间和内存将可移植可执行 (PE) 文件中的所有 MSIL 转换为本机代码,而是在执行期间根据需要转换 MSIL 并存储生成的本机代码以供后继的调用使用。当加载类型时,加载器创建存根 (stub) 并将其附加到类型的每个方法。当对方法进行初始调用时,存根 (stub) 将控制传递给 JIT 编译器,而编译器将该方法的 MSIL 转换为本机代码并修改存根 (stub) 以直接执行到本机代码的位置。后面对 JIT 编译的方法的调用将直接进行到以前生成的本机代码,从而减少了进行 JIT 编译和运行代码所需的时间。”(原文)

此外,当一个程序开始运行后,JIT首先开始进行即时编译,当某个被编译过的方法被再次执行时,将直接执行它的本地代码。

希望这些信息对您有所帮助。
本回答被提问者采纳
第2个回答  2015-07-07
1..NET语言的编译器接受源代码文件,并生成名为程序集的输出文件。

程序集要么是可执行的,要么是DLL
程序集里的代码并不是本机代码,而是一种名称为CIL的中间语言
程序集包含如下信息:
程序的CIL
程序中使用的类型的元数据
对其他程序集引用的元数据
2. 程序的编译过程
程序的CIL直到它被调用运行时才会被编译成本机代码。在运行时,CLR执行下面步骤:

检查程序集的安全特性
在内存中分配空间
把程序集中的可执行代码发送给实时编译器(JIT),把其中的一部分编译成本机代码。
程序集中的可执行代码只在需要的时候由JIT编译器进行编译,然后它就被缓存起来以备在后来的程序中执行。这就意味着不被调用的代码不会被编译成本机代码,而且被调用的代码只被执行一次。

一旦CIL被编译成本机代码,CLR就在它运行时管理它,执行像内存释放、数组边界检查、检查参数类型、异常管理等任务。有两个重要的术语由此而生。

托管代码:为.NET框架编写的代码称为托管代码,需要CLR
非托管代码:不在CLR控制下运行的代码,比如Win32 C/C++ DLL,称为非托管代码
第3个回答  2011-07-01
你妹的,我也在找答案
相似回答