C、C++是典型的编译型编程语言,编译链接后,点击则可执行。
JS,解释型脚本语言,则不需要进行编译,直接解释执行。
Java和C#则是所谓的高级语言,编译执行的方式做了很多处理,
尤其是C#,VS编译后生成的exe文件并非机器码,让很多程序员误解。
 
下文笔者将自己的理解和查阅的资料,和大家分享。有疏漏之处,请大家指出,共同学习。
 
1、C、C++
C、C++是典型的编译型编程语言,编译链接后,点击则可执行。
C、C++ 编译执行的原理,也比较简单,直接是源码经过编译链接之后,生成机器码组成的可执行文件,直接由OS进行Load加载执行。机器码对应硬件的指令,所以,可以直接点击执行。
 
2、JS
JS,解释型脚本语言,则不需要进行编译,直接解释执行。
 
3、Java
.java->编译->.class,Java源码经过编译后,生成.class文件,.class需要jvm解释执行,有部分.class文件也会通过JIT技术来直接生成机器语言,以提高执行效率。
Java这个语言很特殊。
你可以说它是编译型的。因为所有的Java代码都是要编译的,.java不经过编译就什么用都没有。
你可以说它是解释型的。因为java代码编译后不能直接运行,它是解释运行在JVM上的,所以它是解释运行的,那也就算是解释的了。
现在的JVM为了效率,都有一些JIT优化。它又会把.class的二进制代码编译为本地的代码直接运行,所以,又是编译的。
 
4、C#
C#的编译执行过程如下:
(1)C# => C#编译器 => IL(中间代码)
(2)IL => JIT => Native Code(目标程序)
(3)输入 => 目标程序 => 输出。
C#一共编译了两次,第二次发生在运行时,也就是你点击exe文件之后。
 
以HelloWorld程序为例,来说明exe文件的本质,和运行原理:
 
  1. HelloWorld.cs
  2. //HelloWorld.cs by Cornfield,2001
  3. //csc HelloWorld.cs
  4. using System;
  5. class HelloWorld
  6. {
  7. public static void Main()
  8. {
  9. Console.WriteLine("Hello World !");
  10. }
  11. }

需要指出的是,我们一般使用C#编写生成一个HelloWorld的exe文件,其实,内部存放的并不是机器可以解读的机器码,不要被后缀名exe欺骗了。

 编译输出的HelloWorld.exe是一个由中间语言(IL),元数据(Metadata)和一个额外的被编译器添加的目标平台的标准可执行文件头(比如Win32平台就是加了一个标准Win32可执行文件头)组成的PE(portable executable,可移植执行体)文件,而不是传统的二进制可执行文件--虽然他们有着相同的扩展名。
 
中间语言是一组独立于CPU的指令集,它可以被即时编译器Jitter翻译成目标平台的本地代码。中间语言代码使得所有Microsoft.NET平台的高级语言C#,VB.NET,VC.NET等得以平台独立,以及语言之间实现互操作。元数据是一个内嵌于PE文件的表的集合。元数据描述了代码中的数据类型等一些通用语言运行时(Common Language Runtime)需要在代码执行时知道的信息。元数据使得.NET应用程序代码具备自描述特性,提供了类型安全保障,这在以前需要额外的类型库或接口定义语言(Interface Definition Language,简称IDL)。 
这样的解释可能还是有点让人困惑,那么我们来实际的解剖一下这个PE文件。我们采用的工具是.NET SDK Beta2自带的ildasm.exe,它可以帮助我们提取PE文件中的有关数据。我们键入命令"ildasm /output:HelloWorld.il HelloWorld.exe",一般可以得到两个输出文件:helloworld.il和helloworld.res。其中后者是提取的资源文件,我们暂且不管,我们来看helloworld.il文件。我们用"记事本"程序打开可以看到元数据和中间语言(IL)代码,由于篇幅关系,我们只将其中的中间语言代码提取出来列于下面,有关元数据的表项我们暂且不谈:
 
  1. // Microsoft (R) .NET Framework IL Disassembler. Version 1.1.4322.573
  2. // Copyright (C) Microsoft Corporation 1998-2002. All rights reserved.
  3.  
  4. .assembly extern mscorlib
  5. {
  6. .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
  7. .ver 1:0:5000:0
  8. }
  9. .assembly Class2
  10. {
  11. // --- 下列自定义属性会自动添加,不要取消注释 -------
  12. // .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(bool,
  13. // bool) = ( 01 00 00 01 00 00 )
  14. .hash algorithm 0x00008004
  15. .ver 0:0:0:0
  16. }
  17. .module Class2.exe
  18. // MVID: {A9D4A2DC-A401-4F5F-B16F-B3D40F584E59}
  19. .imagebase 0x00400000
  20. .subsystem 0x00000003
  21. .file alignment 512
  22. .corflags 0x00000001
  23. // Image base: 0x070c0000
  24. //
  25. // ============== CLASS STRUCTURE DECLARATION ==================
  26. //
  27. .class public auto ansi beforefieldinit Test
  28. extends [mscorlib]System.Object
  29. {
  30. } // end of class Test
  31.  
  32. // =============================================================
  33. // =============== GLOBAL FIELDS AND METHODS ===================
  34. // =============================================================
  35. // =============== CLASS MEMBERS DECLARATION ===================
  36. // note that class flags, 'extends' and 'implements' clauses
  37. // are provided here for information only
  38.  
  39. .class public auto ansi beforefieldinit Test
  40. extends [mscorlib]System.Object
  41. {
  42. .method private hidebysig static void Main() cil managed
  43. {
  44. .entrypoint
  45. // 代码大小 72 (0x48)
  46. .maxstack 4
  47. .locals init (int32[] V_0,
  48. int32 V_1,
  49. int32 V_2)
  50. IL_0000: ldc.i4.5
  51. IL_0001: newarr [mscorlib]System.Int32
  52. IL_0006: stloc.0
  53. IL_0007: ldc.i4.0
  54. IL_0008: stloc.1
  55. IL_0009: br.s IL_0015
  56.  
  57. IL_000b: ldloc.0
  58. IL_000c: ldloc.1
  59. IL_000d: ldloc.1
  60. IL_000e: ldloc.1
  61. IL_000f: mul
  62. IL_0010: stelem.i4
  63. IL_0011: ldloc.1
  64. IL_0012: ldc.i4.1
  65. IL_0013: add
  66. IL_0014: stloc.1
  67. IL_0015: ldloc.1
  68. IL_0016: ldloc.0
  69. IL_0017: ldlen
  70. IL_0018: conv.i4
  71. IL_0019: blt.s IL_000b
  72.  
  73. IL_001b: ldc.i4.0
  74. IL_001c: stloc.2
  75. IL_001d: br.s IL_003b
  76.  
  77. IL_001f: ldstr "arr[{0}]={1}"
  78. IL_0024: ldloc.2
  79. IL_0025: box [mscorlib]System.Int32
  80. IL_002a: ldloc.0
  81. IL_002b: ldloc.2
  82. IL_002c: ldelem.i4
  83. IL_002d: box [mscorlib]System.Int32
  84. IL_0032: call void [mscorlib]System.Console::WriteLine(string,
  85. object,
  86. object)
  87. IL_0037: ldloc.2
  88. IL_0038: ldc.i4.1
  89. IL_0039: add
  90. IL_003a: stloc.2
  91. IL_003b: ldloc.2
  92. IL_003c: ldloc.0
  93. IL_003d: ldlen
  94. IL_003e: conv.i4
  95. IL_003f: blt.s IL_001f
  96.  
  97. IL_0041: call int32 [mscorlib]System.Console::Read()
  98. IL_0046: pop
  99. IL_0047: ret
  100. } // end of method Test::Main
  101.  
  102. .method public hidebysig specialname rtspecialname
  103. instance void .ctor() cil managed
  104. {
  105. // 代码大小 7 (0x7)
  106. .maxstack 1
  107. IL_0000: ldarg.0
  108. IL_0001: call instance void [mscorlib]System.Object::.ctor()
  109. IL_0006: ret
  110. } // end of method Test::.ctor
  111.  
  112. } // end of class Test
  113.  
  114. // =============================================================
  115. //*********** 反汇编完成 ***********************
  116. // WARNING: Created Win32 resource file Class2.res

  

我们粗略的感受是它很类似于早先的汇编语言,但它具有了对象定义和操作的功能。我们可以看到它定义并实现了一个继承自System.Object 的HelloWorld类及两个函数:Main()和.ctor()。其中.ctor()是HelloWorld类的构造函数,可在"HelloWorld.cs"源代码中我们并没有定义构造函数呀--是的,我们没有定义构造函数,但C#的编译器为我们添加了它。你还可以看到C#编译器也强制HelloWorld类继承System.Object类,虽然这个我们也没有指定。

一起来看看典型的C#/.NET应用程序的执行过程:
那么PE文件是怎么执行的呢?下面是一个典型的C#/.NET应用程序的执行过程:

(1)用户执行编译器输出的应用程序(PE文件),操作系统载入PE文件,以及其他的DLL(.NET动态连接库)。 
(2)操作系统装载器根据前面PE文件中的可执行文件头跳转到程序的入口点。显然,操作系统并不能执行中间语言,该入口点也被设计为跳转到mscoree.dll(.NET平台的核心支持DLL)的_ CorExeMain()函数入口。 
(3)CorExeMain()函数开始执行PE文件中的中间语言代码。这里的执行的意思是通用语言运行时按照调用的对象方法为单位,用即时编译器JIT将中间语言编译成本地机二进制代码,执行并根据需要存于机器缓存。 
程序的执行过程中,垃圾收集器负责内存的分配,释放等管理功能。 
程序执行完毕,操作系统卸载应用程序。

 
总之,在运行 Microsoft 中间语言 (MSIL) 之前,也就是我们使用VS编译后生成的exe文件,必须先根据公共语言运行库将其编译为适合目标计算机体系结构的本机代码。
 
C#将IL转为机器码的两种方法及区别 :
.NET Framework 提供了两种方式来执行此类转换:.NET Framework 实时 (JIT) 编译器 和 .NET Framework 本机映像生成器 (Ngen.exe)。
 
JIT方式:由于编译器将本地代码保存在动态内存中,所以关闭程序时本地代码将发生丢失。当再次启动程序或者同时运行程序的两个实例时,JIT编译器将再次将IL代码编译为本地指令。
Ngen方式:公共语言运行库支持一种提前编译模式。此提前编译模式使用本机映像生成器 (Ngen.exe) 将 MSIL 程序集转换为本机代码,其作用与 JIT 编译器极为相似。
Ngen.exe 的操作与 JIT 编译器的操作有三点不同:
(1)它在应用程序运行之前而不是运行过程中执行从 MSIL 到本机代码的转换。
(2)它一次编译一个整个的程序集,而不是一次编译一个方法。
(3)它将本机映像缓存中生成的代码以文件的形式持久保存在磁盘上。
 
引用:

C C++ Java C# JS编译、执行过程的原理入门分析的更多相关文章

  1. java代码的编译执行过程

  2. 动图+源码,演示Java中常用数据结构执行过程及原理

    最近在整理数据结构方面的知识, 系统化看了下Java中常用数据结构, 突发奇想用动画来绘制数据流转过程. 主要基于jdk8, 可能会有些特性与jdk7之前不相同, 例如LinkedList Linke ...

  3. 动图+源码,演示 Java 中常用数据结构执行过程及原理

    ​阅读本文大概需要 3.7 分钟. 作者:大道方圆 cnblogs.com/xdecode/p/9321848.html 最近在整理数据结构方面的知识, 系统化看了下Java中常用数据结构, 突发奇想 ...

  4. 【JS】js引擎执行过程

    概述 js引擎执行过程主要分为三个阶段,分别是语法分析,预编译和执行阶段,上篇文章我们介绍了语法分析和预编译阶段,那么我们先做个简单概括,如下: 语法分析: 分别对加载完成的代码块进行语法检验,语法正 ...

  5. C#编译执行过程

    前言 大家好,我是卫斯理(Wesley).喜欢武侠的朋友可能知道小说中也有个卫斯理,他是位冒险家,财力充沛,极富冒险精神,并且有着超强的好奇心,对奇异的事情总有"打破沙锅问到底"的 ...

  6. C程序编译执行过程

    C程序编译执行过程   认识C编译执行过程,是C学习的开端. 简单说C语言从编码编译到执行要经历一下过程:   C源代码 编译---->形成目标代码,目标代码是在目标机器上运行的代码. 连接-- ...

  7. go 编译:交叉编译&编译执行过程

    1. 交叉编译 编译Windows程序和mac程序 GOOS=windows GOARCH-amd64 go build main.go 转自:https://www.cnblogs.com/mafe ...

  8. c语言编译执行过程

    <h4>认识C编译执行过程</h4>认识C编译执行过程,是C学习的开端.简单说C语言从编码编译到执行要经历一下过程: C源代码编译---->形成目标代码,目标代码是在目标 ...

  9. 四、Struts2的执行过程和原理

    执行过程和原理(可能面试题) 学习目标:熟知struts2的执行过程(下图记住).源码可以不看 a.过滤器的初始化 .StrutsPrepareAndExecuteFilter是一个过滤器,过滤器就有 ...

随机推荐

  1. Arcgis api for javascript学习笔记(4.5版本)-三维地图并叠加天地图标注

    1.三维地图实现 在官网的demo中就有三维地图的实现,如下图所示 <!DOCTYPE html> <html> <head> <meta charset=& ...

  2. 「两」创建一个带 ssh 镜座服务(修订版)--采用 Dockerfile 创

    创建目录 首先,创建一个叫做 sshd_ubuntu 的目录,用于存放我们的 Dockerfile .脚本文件.以及其它文件. $ mkdir sshd_ubuntu $ ls sshd_ubuntu ...

  3. Facebook巴特尔与谷歌移动广告 急于打开中国市场

    随着Facebook(62.5, -0.69, -1.09%)即将设立了销售办事处在北京发酵消息.谷歌(556.33, 2.43, 0.44%)似还差点自觉保护国内市场. 6月5日,谷歌在深圳举行了面 ...

  4. Android--数据持久化存储概述

    Android数据持久化存储共有四种方式,分别是文件存储.SharedPreferences.Sqlite数据库和ContentProvider.在本篇幅中只介绍前面三种存储方式,因为ContentP ...

  5. IT引导学生成长的文章链接(十二)

    链接:IT学子成长指导类文章链接(1)(2)(3) (4) (5)(6)(7)(8)(9)(10)(11) "IT学子成长指导"类我收藏过的好文(十二期:至2014年4月26日) ...

  6. UWP 中的各种文件路径(用户、缓存、漫游、安装……)

    原文 UWP 中的各种文件路径(用户.缓存.漫游.安装……) UWP 提供了多种不同文件路径访问方式,对应到不同的文件路径中.可能我们只是简单用 ApplicationData.Current 获取一 ...

  7. 1.跟着微软 https://docs.microsoft.com/zh-cn/dotnet/core/ 学习.net core

    10分钟快速使用 安装之后 打开cmd 第一步. dotnet new console -o firstApp 第二步. cd firstApp 第三部.dotnet run 这样就运行了hello ...

  8. 方阵的迹(trace)及其微分(导数)

    trace 的一个十分重要的性质在于线性性, Tr(A+B)=Tr(A)+Tr(B)Tr(cA)=cTr(A) 1. 基本性质 Tr(A)=Tr(AT) Tr(AB)=Tr(BA) Tr(ABC)=T ...

  9. python3 基本使用多线程

    #coding=utf-8 import threading #进口threading from time import sleep import time def task1(): print (& ...

  10. 在运行Hfile的MR如果任务client结束OOM

    在运行MR将HDFS转换成HFile什么时候.例如,会发生以下的异常: 14/07/09 18:02:59 INFO mapred.JobClient:  map 83% reduce 0% 14/0 ...