C和Java编译执行的过程比较

编译

不论是物理机还是虚拟机,大部分的程序代码从开始编译到最终转化成物理机的目标代码或虚拟机能执行的指令集之前,都会按照如下图所示的各个步骤进行:

其中绿色的模块可以选择性实现。分为解释执行编译执行

  1. 上图中间的那条分支是解释执行的过程(即一条字节码一条字节码地解释执行,如 JavaScript)。
  2. 而下面的那条分支就是传统编译原理中从源代码到目标机器代码的生成过程。

如今,基于物理机、虚拟机等的语言,大多都遵循这种基于现代经典编译原理的思路,在执行前先对程序源码进行词法解析和语法解析处理,把源码转化为抽象语法树。对于一门具体语言的实现来说,词法和语法分析乃至后面的优化器和目标代码生成器都可以选择独立于执行引擎,形成一个完整意义的编译器去实现,这类代表是 C/C++语言。
也可以把抽象语法树或指令流之前的步骤实现一个半独立的编译器,这类代表是Java语言。
又或者可以把这些步骤和执行引擎全部集中在一起实现,如大多数的 JavaScript执行器。

javac 字节码编译器与虚拟机内的 JIT 编译器的执行过程合起来其实就等同于一个传统的编译器所执行的编译过程。
Java与C/C++的编译器对比实际上代表了最经典的即时编译器与静态编译器的对比,很大程度上也决定了Java与C/C++的性能。

Java和C/C++比较

JVM的即时编译器与C/C++的静态编译器相比,可能会由于以下原因存在导致输出的本地代码有一些劣势:

  1. 即时编译器运行占用的是用户程序的运行时间。
  2. Java语言是动态的类型安全语言,实现上会进行各种安全检查。
  3. Java语言没有virtual关键字,但是使用虚方法的频率却远远大于C/C++,这意味着运行时对方法接收者进行多态选择的频率要远远大于C/C++。
  4. Java语言是可以动态扩展的语言,运行时加载新的类可能改变程序类型的继承关系,使得很多全局优化难以进行,JIT编译器不得不时刻关注类型的变化并在运行时撤销或重新进行一些优化。
  5. Java语言中对象的内存分配都是在堆上进行的,只有方法中的局部变量才能在栈上分配。而C/C++的对象有多种内存分配方式(栈上分配线程私有的对象,将减轻内存回收的压力)。

Java语言上性能的劣势换取开发效率上的优势,动态安全、动态扩展、垃圾回收都为开发效率做出了很大贡献。

C

编译和连接过程

整个过程会有这样4个步骤:

  1. 预处理(Preprocessing):静态替换,处理预编译指令。
  2. 编译(Compilation):预处理完的文件进行一系列的词法分析,语法分析,语义分析及优化后生成相应的汇编代码。
  3. 汇编(Assembly):汇编代码转变成机器可以执行的命令,每一个汇编语句几乎都对应一条机器指令。
  4. 连接(Linking):通过调用链接器ld来链接程序运行需要的一大堆目标文件,以及所依赖的其它库文件,最后生成可执行文件。

最终得到的是一个.exe(windows)或.out(linux)文件。

执行过程

在运行的时候,是将整个输出文件(a.exe)读到内存里运行的。

可见,经过编译和汇编步骤,会生成直接给CPU执行的机器指令。机器码就是0101的二进制代码。所以,执行C语言的时候,实际上是运行最底层的语言,这样的代码高效,却和芯片,操作系统紧密耦合在一起了。

Java

Java的平台无关性的基础:

  1. 字节码存储格式。Java编译器会将.java文件编译为.class文件,.class文件就是能被JVM执行的代码,它包含Java虚拟机的指令集,符号表和其他辅助信息。
  2. Java虚拟机(JVM)。顾名思义它是加在应用层的一层抽象。从上层看,它就是CPU:加载并运行字节码代码,屏蔽了操作系统和硬件细节,对下,它将字节码翻译为CPU能执行的机器指令。

Java编译和执行整个过程:

编译过程

Java的编译过程就是将.java文件编译成.class文件。

执行过程

当JVM运行时,再按需加载这些.class到内存中。

Java和C在编译过程中的一个差异是:在Java语言里面,类型的加载,连接,和初始化是在运行期间完成的。

JVM 是基于栈的体系结构来执行 class 字节码的。线程创建后,都会产生程序计数器(PC)和栈(Stack),程序计数器存放下一条要执行的指令在方法内的偏移量,栈中存放一个个栈帧,每个栈帧对应着每个方法的每次调用,而栈帧又是有局部变量区和操作数栈两部分组成,局部变量区用于存放方法中的局部变量和参数,操作数栈中用于存放方法执行过程中产生的中间结果。


感谢:
http://afghl.github.io/2016/10/23/java-jvm-classloader-1.html
http://wiki.jikexueyuan.com/project/java-vm/javac-jit.html