[整理]执行引擎,编译器,概念理解

Rosalia ·
更新时间:2024-11-10
· 676 次阅读

最近又把《深入理解Java虚拟机》捡起来读,从引言第一章看对后续章节的总结,看到两个概念不理解。
一个是执行引擎,一个是编译器。
格物致知,扔到google里去搜一下,看维基百科的概念定义。消化理解一下。
这些基本概念,应该是计算机必修课程《编译原理》里的,有空需要翻一翻编译原理了。
(编译原理–该课程主要讲授编译器设计与实现的主要理论和技术。主要内容包括词法分析、语法分析、语法树构造、语义分析、中间代码生成、代码优化、目标代码生成等主要内容。)

执行引擎

虚拟机是一个相对于物理机的概念,物理机执行引擎是基于处理器,硬件,指令集以及操作系统层面上的,而虚拟机引擎完全是有自己实现的,因此格式与结构体系可以自行定制。执行引擎是整个JVM的核心,没有执行引擎
前面所讲的都是白搭。

取自 虚拟机的执行引擎,2018-4,风一样的行者

JVM的执行引擎
1.运行时栈帧
2.方法的调用(重点)
3. 基于栈的字节码解释执行引擎

下边这一篇分析的更清楚:
深入理解Java虚拟机(字节码执行引擎),2019-5,掘金,BaronTalk
哇哇哇,今天发现了宝藏,BaronTalk的公众号真的是排版又好,又有内容。他19年做了一系列java虚拟机的总结,果断关注。

指令集,wuzguo
编译优化技术,csdn

编译器

百度百科:
编译器将汇编或高级计算机语言源程序(Source program)作为输入,翻译成目标语言(Target language)机器代码的等价程序。
维基百科:
Compiler (编译器)
A compiler is a computer program that translates computer code written in one programming language into another language. The name compiler is primarily used for programs that translate source code from a high-level programming language to a lower level language to create an executable program
再看一下阮一峰2014年的博客,编译器的工作过程, 是对c的编译过程做了分析。题文第一句,

源码要运行,必须先转成二进制的机器码。这是编译器的任务。

第一步 配置(configure)
第二步 确定标准库和头文件的位置
第三步 确定依赖关系
第四步 头文件的预编译(precompilation)
第五步 预处理(Preprocessing)
第六步 编译(Compilation)
第七步 连接(Linking)
第八步 安装(Installation)
第九步 操作系统连接
第十步 生成安装包
第十一步 动态连接(Dynamic linking)

编译器 vs 解释器

编译器的实质是一个 程序。其核心功能是将 源代码 翻译成 目标

源代码: C/C++, Java, …
目标代码:x86, ARM, …

在这里插入图片描述

解释器 和编译器相同都是一种程序,源代码输入通过编译器输出得到的是可执行程序。输入通过解释器得到的输出得到的直接就是一个结果。

相对来说,编译器是一种离线的模式,解释器是一种在线的模式。

编译器结构

由于编译器实现的是将源代码转化为目标代码的功能。所以对于编译器的结构可以大致分为前端和后端两部分,前段处理输入源程序,后端处理输出目标代码。
在这里插入图片描述
因此,编译器可以看成是一个由多个阶段构成的流水线结构。

如下,给出的是一种没有优化的编译器结构。
在这里插入图片描述

我们可以看见,最开始的输入是一个字符序列,也就是没有处理过的程序代码。之后进行词法分析,得到一个记号序列。语法分析接着检查程序的语法是否合法,在内存中建立一个抽象语法树的数据结构。之后,进行语义分析,判断语法树的合法性,变量是否已经提前声明,函数是否已经定义…生成中间代码。最终通过代码生产得到目标代码。

静态编译,动态编译

这是C语言的概念?

静态链接库和动态链接库理解,
静态编译:
静态lib将导出声明和实现都放在lib中。编译后所有代码都嵌入到宿主程序。
动态编译:
动态lib相当于一个h文件,是对实现部分(.dll文件)的导出部分的声明。编译后只是将导出声明部分编译到宿主程序中,运行时
候需要相应的dll文件支持。

1.静态编译:编译器在编译可执行文件时,把需要用到的对应动态链接库(.so或.ilb)中的部分提取出来,链接到可执行文件中去,
使可执行文件在运行时不需要依赖于动态链接库.

2.动态编译: 动态编译的可执行文件需要附带一个的动态链接库,在执行时,需要调用其对应动态链接库中的命令。所以其优点一
方面是缩小了执行文件本身的体积,另一方面是加快了编译速度,节省了系统资源。缺点一是哪怕是很简单的程序,只用到了链接
库中的一两条命令,也需要附带一个相对庞大的链接库;二是如果其他计算机上没有安装对应的运行库,则用动态编译的可执行文
件就不能运行。

动态链接库:

创建一个动态链接库,会生成x.dll,x.lib
动态链接库有两种加载方式:
1.一种是静态加载,就是在编译的时候就载入动态链接库。此种方法可调用类方法.
可执行程序静态加载动态链接库需要三个文件 x.dll, x.lib, x.h
可执行程序的头文件加入:
#include “x.h”
#pragma comment(lib,“x.lib”)
编译时还要附加库目录,防止程序编译时无法找到x.dll。
2.动态加载
只需要x.dll文件。
在程序执行需要该动态链接库的地方加载x.dll。
然后获取需要的x.dll库里面的函数或数据.
该方法不能调用类方法.

可执行程序调用了动态链接库,其运行不能缺少动态链接库.

静态链接库:

创建一个静态链接库,会生成x.lib文件
想要调用静态链接库里面的内容需要x.lib文件和x.h文件
库中内容会直接编译到x.exe文件中。
可执行程序使用静态库编译成x.exe后,x.exe的运行就不在需要静态链接库了,可以独立运行了。

一般的静态编译可以理解为加载静态链接库;动态编译理解我加载动态链接库。
静态链接库中不能包含其他库,动态链接库中能包含其他库。

静态依赖 vs 动态依赖??


作者:TTKatrina



编译器

需要 登录 后方可回复, 如果你还没有账号请 注册新账号