编译&解释 Java&Python
编译流程
graph LR;
A([源代码])-->B[编译器];
B[编译器]-->C([目标代码]);
C([目标代码])-->D[程序运行];
E([程序输入代码])-->D[程序运行];
D[程序运行]-->F([输出结果])
源代码:在IDE中采用某编程语言写的程序,人类可读性强。
目标代码:根据规则转换的计算机可执行程序,人类不可读(底层相关专家除外)。
执行编译过程的程序叫编译器。
目标代码由机器指令组成,一般不能独立运行,因为源代码中可能使用了某些汇编程序不能解释引用的库函数,而库函数代码又不在源程序中,此时还需要链接程序完成外部引用和目标模块调用的链接任务,最后输出可执行代码。
用编译的方式执行的语言叫静态语言,包括C/C++语言、Java语言等。
解释流程
graph LR;
A([源代码])-->D[解释器];
E([程序输入代码])-->D[解释器];
D[解释器]-->F([输出结果])
执行解释过程的程序叫解释器。用解释的方式执行的语言叫脚本语言,包括Python语言、JavaScript语言、PHP语言等。
编译和解释的对比
编译 | 解释 | |
---|---|---|
特点 | 一次性将源代码转换成目标代码 | 逐条提取源代码,再转换成目标代码 |
过程 | 经过编译、汇编和链接才能输出目标代码,然后机器执行目标代码,得出运行结果 | 每次运行都转换成字节码,再由虚拟机转换成机器语言,最后在硬件上运行 |
eclipse、idea(开发)JIT(服务器) | VScode、PyCharm(开发) | |
实操例子 | 编译成的jar文件可以直接发给其他服务器或开发环境中运行 |
语言 | 优点/缺点 | 原因 |
---|---|---|
静态语言 | 优化的更充分,运行更快 | 编译器可一次性生成目标代码 |
老旧版本容易流失源代码 | 编译完成,只运行目标代码即可,源代码被弃置 | |
脚本语言 | 源代码不会丢失 | 执行时必须源代码 |
部分修改源代码可不必再次执行即可输出结果 | 解释时不解释非必要参数,运行中才会解释 |
再看Java & Python
Java很特殊,在编译的基础上又添加了Java虚拟机(JVM)。Java程序需要编译,但是没有直接编译称为机器语言,而是编译称为字节码(.class文件),然后在Java虚拟机上用解释方式执行字节码。
(Java虚拟机对字节码的执行相当于用软件模拟一个cpu,而ruby1.8–在虚拟机还未出现前–是通过解释成语法树执行。)
所以说Java运行过程中既需要编译器,又需要解释器(jdk或jre目录下bin目录中的java.exe文件,是JVM非常重要的一部分)。
那么Java的解释器是如何运行的呢?
Java配置环境变量时,其中CLASSPATH包含一个或多个目录,用来查找.class文件(字节码)的根目录。Java执行过程中,将得到根目录与CLASSPATH中的各个不同的项相连接,解释器就在这些目录中查找与开发人员创建的类名称相关.class文件的。
然后解释器将这些字节码翻译为机器码,机器码是直接跨过操作系统的cpu指令代码。JVM虽然运行在操作系统上,但是它生成的机器码文件是直接对应与不同指令集架构的cpu。
graph LR;
A([Java源代码])
B[Java编译器 java.exe]
C([字节码.class])
D[Java解释器]
E([程序输入代码])
F([机器码])
G[操作系统]
H([输出结果])
A-->B;
B-->C;
C-->D;
E-->D;
D-->F;
F-->G;
G--运行-->H
Python是一个解释型的语言。但是为了效率上的考虑,Python也提供了编译的方法。
(就是说Python也有类似Java的编译模式,先将Python程序编译成Python字节码,然后由一个专门的Python字节码解释器负责解释执行字节码。)
源代码编译之后是bytecode的形式。Python也提供了和Java类似的VM来执行这样的bytecode。不同的是,因为Python是一个解释型的语言,所以编译(compile)不是一个强制的操作。事实上,编译是一个自动的过程。多数情况下,你甚至不会在意他的存在。编译成bytecode可以节省加载模块的时间,从而提高效率。
.pyc文件就是Python编译后生成的文件,pyc的目的是重用,即编译成.pyc的文件,最大的优点在于我们在运行程序时,不需要重新对该模块进行重新的解释。Python的解释器认为:只有import进来的模块,才是需要被重用的模块。
import源码,在每次执行前都会检查py文件和pyc文件最后修改日期,不一致就会重新生成pyc文件。
除了效率原因,bytecode也增加了反向工程的难度,在某种程度上保护你的代码。当然,反编译仍然是可以的。所以如果真的想保护代码,还是用别的方法吧。另外Python还提供了-O选项,可以编译生成”优化”的bytecode,文件扩展名是.pyo。但实际上优化的内容有限,作用不大。如果希望生成可执行文件,就要依赖于第三方的工具了。
graph LR;
A([Python源代码])
B[解释器]
C[翻译器]
D([字节码.pyc/.pyo])
F([机器码])
G[操作系统]
H([输出结果])
A--from-->B
A-->C-->D--import-->B
B-->F-->G-->H