概述
对编译器、编译型与解释型语言、compiler assembler interpreter、jvm等内容做简单的了解。可能有错误之处。
想要进一步了解某个技术的话,需要继续深入研究。
Phases of a Compiler
https://www.geeksforgeeks.org/introduction-of-compiler-design/
https://www.geeksforgeeks.org/phases-of-a-compiler/
编译型语言&compiler assembler
使用专门的编译器,针对特定的平台,将高级语言源代码一次性的编译成可被该平台硬件执行的机器码。平台间区别主要是CPU(arm、x86、mips等)架构和文件格式(ELF\PE)
在编译型语言写的程序执行之前,需要一个专门的编译过程,把源代码编译成机器语言的文件。如PE格式的可执行文件exe,以后要再运行时,直接使用编译结果即可,如直接运行exe文件。
优点:只需编译一次,以后运行时不需要编译。执行效率高。
缺点:代码在编译过程中就已经被翻译成了目标 CPU 指令、文件格式,所以,如果程序需要在另外一种 CPU 、文件格式不同的操作系统上面运行,这个代码就必须重新编译。
典型的编译型语言:.C、C++、Pascal、Object-C,Swift
要注意,具体语言和具体的编译器,具体分析。
GCC
例如使用gcc编译C语言。 源文件(.c)->预处理(.i)->编译(compile)得到汇编指令文件(.s)->汇编(assemble)得到机器语言的目标文件(.o .obj)->链接得到可执行文件
这几个步骤分别有 preprocessor、compiler、assembler、linker完成
对应的disassembler是机器语言到汇编语言,而Decompile是汇编到高级语言
解释型语言与解释器
解释型语言执行时,由解释器 逐条 ,直接翻译为 CPU指令(机器码),执行。边解释边执行,且必须在运行时解释。好处就是方便,但缺点是效率低。
典型的解释型语言有:Python/JavaScript / Perl /Shell
但是需要注意的是,不同的解释型语言也有实现上的不同。
Javascript
比如javascript,不同浏览器有不同的JS引擎。 ,也就有不同的执行方式。
传统的引擎,词法分析和语法分析得到语法树,然后有一个“预编译”过程,然后按照逐条解释执行。
部分引擎先转换为字节码,然后解释。
然而google的V8,为了提高效率,直接编译成原生机器码。 https://zhuanlan.zhihu.com/p/295179301
对于不同的引擎,要具体分析
Python
比如python,会预先编译为字节码,然后python虚拟机会逐条的解释字节码。和下面要提到的Java有些类似(从这个角度看,python似乎不是典型的解释型语言,和java更类似,除非把python虚拟机看作python解释器) https://www.cnblogs.com/webber1992/p/6597166.html
此外,解析器是parser,而解释器是interpreter。前者是编译器/解释器的重要组成部分,也可以用在IDE之类的地方;其主要作用是进行语法分析,提取出句子的结构。广义来说输入一般是程序的源码,输出一般是语法树(syntax tree,也叫parse tree等)或抽象语法树(abstract syntax tree,AST)。 https://www.iteye.com/blog/rednaxelafx-492667
总结1
解释和编译以及虚拟机等等技术,更多的是概念上的区别。很多语言并不是严格的只有解释、完全只有静态编译。
随着技术的发展,各种技术互相结合以提高语言编译执行的效率。
虚拟机
虚拟机分为两大类:系统虚拟机和进程虚拟机。这两种虚拟机都提供一种对“真实的”计算硬件的不同级别的抽象,不过它们的作用域不同。系统虚拟机是一个提供物理硬件的替代品的软件,而进程虚拟机则被设计用来以一种“系统独立”的方式执行程序。
在编译和程序执行的角度来看,当然是指进程虚拟机,接下来提到的的VM都是进程虚拟机。
进程虚拟机(的作用域和解释器的比较类似,因为也是先将程序编译成一个中间形态,然后虚拟机再执行这个中间形态。
虚拟机和解释器的主要区别在于,虚拟机创造了一个虚拟的 CPU,以及一套虚拟的指令集。有了这层抽象,我们就可以编写前端工具来把不同语言的程序编译成虚拟机可以接受的程序。最流行也最知名的虚拟机就是 Java 虚拟机(JVM)。https://zhuanlan.zhihu.com/p/70949843
JAVA
Java和其他的语言不太一样,不是完全的解释型也不是完全的编译型。
前端编译
把Java源码文件(.java)编译成Class文件(.class)的过程
后端编译/即时(JIT)编译
通过Java虚拟机(JVM)内置的即时编译器(Just In Time Compiler,JIT编译器);在运行时把Class文件字节码编译成本地机器码的过程;
静态提前编译(Ahead Of Time,AOT编译)
直接把CLASS字节码文件(.java)编译成本地机器码的过程,省掉了JVM的过程。
跨平台
java针对不同的平台有不同的JVM,实现了跨平台。
1.你可以说它是编译型的:因为所有的Java代码都是要编译的,.java不经过编译就什么用都没有。 (此处考虑的是编译为class,然后jvm执行,而非AOT)
2.你可以说它是解释型的:因为java代码编译后不能直接运行,它是解释运行在JVM上的。
JVM
程序员在编写Java程序时,利用Java编译器,将Java语言编译为Java ByteCode;之后,执行过程中需要使用相应平台的JVM(Java虚拟机)将ByteCode转化为相应平台的机器代码,如JVM for Windows、JVM for UNIX。从而实现跨平台运行
对于JVM的设计有三种
1. 运行时,BYTECODE由JVM逐条解释执行,即解释器模式。 java interpreter。
2. 运行时,部分代码可能由JIT翻译为目标机器指令(以method为翻译单位,还会保存起来,第二次执行就不用翻译了)直接执行;
3. RTSJ。继JAVAC生成class文件后,之后执行AOT二次编译,生成静态的目标平台代码(典型的就是IBM WEBSHPERE REAL TIME)。
有的时候,可能是以上三种方式同时在使用。至少前两者是结合的。例如下图就是JIT和Java interpreter结合的示例
Java的JIT&&AOT
这部分只是简单的看了看,可能有理解错误。若有需要,应该进一步查找相关资料。
AOT:
直接把CLASS字节码文件(.java)编译成本地机器码的过程,省掉了JVM的过程。
完全的JIT:
所有代码都提前编译。然而显然代价过高。
热点型的JIT:
当JVM发现某个方法或代码块运行特别频繁的时候,就会认为这是“热点代码”(Hot Spot Code)。然后JIT会把部分“热点代码”编译成本地机器相关的机器码,并进行优化,然后再把编译后的机器码缓存起来,以备下次使用。 从而节省时间。 https://www.zhihu.com/question/37389356/answer/73820511
需要注意的是,JIT编译器将语言 X 转化为机器代码时,需要解释器的参与。可以认为,没有解释器,亦不存在JIT编译器。
GCC gcc g++
GCC:GNU Compiler Collection(GUN 编译器集合),它可以编译C、C++、JAVA、Fortran、Pascal、Object-C等语言。
gcc是GCC中的GUN C Compiler(C 编译器)
g++是GCC中的GUN C++ Compiler(C++编译器)
就本质而言,gcc和g++并不是编译器,也不是编译器的集合,它们只是一种驱动器,根据参数中要编译的文件的类型,调用对应的GUN编译器而已
GCC是许多现代类 Unix 操作系统默认的编译器,包括 Mac OSX 系统,但后来 Mac OSX 改为用 Clang 编译器了。
PS:
GNU: https://www.zhihu.com/question/319783573
glibc、glib、libc
Clang&LLVM
Clang
LLVM
LLVM与JVM
二者根本不是一个范畴的技术,JVM是虚拟机而LLVM是编译器框架。
但是可以在某些特定的角度下进行比较,
1.实现一门语言时在选择代码生成器(code generator)的解决方案时,是选择LLVM、GCC等,还是JVM、.NET等,还是自己手写
2.二者相结合:Azul Systems公司就在做基于LLVM的JVM JIT编译器,微软也有一个组在做基于LLVM的.NET JIT/AOT编译器
https://www.zhihu.com/question/47819047
参考
编译器:
https://www.geeksforgeeks.org/phases-of-a-compiler/
https://www.geeksforgeeks.org/introduction-of-compiler-design/
解释型与编译型:
https://www.jianshu.com/p/54e2aeca013b
https://www.cnblogs.com/zy1987/p/3784753.html
https://www.iteye.com/blog/rednaxelafx-492667
https://zhuanlan.zhihu.com/p/70949843
python:
https://www.cnblogs.com/webber1992/p/6597166.html
v8:
https://zhuanlan.zhihu.com/p/295179301
java&JVM:
https://www.zhihu.com/question/19608553
https://blog.csdn.net/qq_34902684/article/details/85538895
https://www.zhihu.com/question/37389356/answer/73820511
https://www.cnblogs.com/mzywucai/p/11053485.html
GCC gcc:
https://zhuanlan.zhihu.com/p/100050970
https://www.cnblogs.com/liuzhenbo/p/11027197.html
LLVM:
https://www.zhihu.com/question/47819047
https://zhuanlan.zhihu.com/p/140462815
https://www.cnblogs.com/flipped/p/15234552.html