解释器vs编译器 && C,java,python编译过程对比

自己总结的,以后学了《深入理解Java虚拟机》之后会进一步丰富内容。

  • 解释型语言:python,perl,javascript,shell,java
  • 编译型语言:C,C++
  • 名义上是解释型,实际上有点编译型:python,Java

总结来讲,有两种程序运行过程:

1. 源代码—->字节码(中间代码)—>机器代码

首先将源代码编译为中间代码,然后利用虚拟机将中间代码解释或者编译解释为CPU可以直接执行的机器代码。

2.1 python

python的编译过程是自动进行的,将.py文件编译成.pyc文件(如果没有写权限,.pyc文件放在内存中,在程序结束时简单的丢弃)。这个.pyc文件是一个与平台无关的字节码文件。

Python的传统执行模式

接下来,使用PVM解释这个字节码文件,解释的过程是逐条进行的,每一次负责将一条字节码文件语句翻译成CPU可以直接执行的机器代码,然后运行。之后进行下一步。

综上可以看出解释型语言的特点,那就是没有所谓的编译,或者对于python来讲,没有针对机器代码的编译,所以需要直接对源代码或者中间代码进行解释运行。而少了这个编译的过程,使得解释型语言运行较慢。另外,在逐条解释的过程中,效率也较低。

解释型语言也有优点,比如它的平台无关性,另外,具体逐条解释的时候会进行动态优化,有时不见得比编译型的慢。

最后可以看到,python最开始会有一个编译的过程,所以并不是纯的解释型语言。

2.2 Java

下面说明一下Java。

首先JVM体量上就比PVM大的多。在Java的执行过程中,首先将.java文件利用javac编译成.class字节码文件。但是,与python不同,java的编译并未停止,在JVM中仍然包含编译的过程。

这是为什么呢?观看下图:

这里写图片描述

这幅图形象地说明了Java运行程序的过程。在说明这幅图之前,先稍微了解一下JIT的背景。最开始Sun公司使用classic vm作为JVM,但是饱受“Java比C++慢的多”的诟病。后来Sun公司引入HotSpot作为虚拟机,并引入JIT(Just In Time)技术。

JIT又称即时编译器,虽说是编译器,它跟javac编译器的功能不同。JVM有三种运行模式:解释模式,编译模式,混合模式。上图对应的是混合模式,其流程为:

1、源代码经javac编译成字节码,class文件

2、程序字节码经过JIT环境变量进行判断,是否属于“热点代码”(多次调用的方法,或循环等)

3、如是,走JIT编译为具体硬件处理器(如sparc、intel)机器码

4、如否,则直接由解释器解释执行

5、操作系统及类库调用

6、硬件

所以JIT是一个解释器和编译器的集合,某些“热点代码”可以通过编译来节省逐条解释的耗时,其他代码仍旧通过解释器执行。

这么想的话,解释模式应该就是不通过编译器,全部直接经由解释器,有点类似python;而编译模式应该就是对每条进行编译。

那么为什么编译模式要比混合模式慢呢?博客中给出的回答是:

编译执行不加筛选的将全部代码进行编译机器码不论其执行频率是否有编译价值,在程序响应时间的限制下,编译器没法采用编译耗时较高的优化技术(因为 JIT的编译是首次运行或启动的时候进行的!),所以,在纯编译执行模式下的java程序执行效率跟C/C++也是具有较大差距的。

所以Java也不是纯正的解释型语言。

2.3 总结

与Java和Python不同,Shell语言是真正直接将高级语言解释成CPU可以直接运行的机器语言的。

所以总结起来,所谓的解释型语言有三种:

1. 直接运行高级编程语言(如Shell内置的解释器)

2. 转换高级编程语言码到一些有效率的字节码(Bytecode),并运行这些字节码(如python)

3. 以解释器包含的编译器对高级语言编译,并指示处理器运行编译后的程序(例如:JIT)

2. 源代码—>机器代码

这里从C与Java的对比角度说明。

C的编译过程分为四步:预处理,编译,汇编和链接。前面三步可以合称“编译”,其输出为一条一条的机器指令,因为每一条汇编语句几乎都对应一条机器指令。链接的作用是将程序运行需要的目标文件/库文件链接起来,生成可执行文件exe。

这些步骤与平台有关,生成的都是可以直接执行的文件,不需要解释器解释。其原理是什么呢?

对比一下C/C++与Java的编译过程。

c/c++编译过程:

当C编译器编译生成一个对象的代码时,该代码是为在某一特定硬件平台运行而生成的。因此在编译过程中,编译程序通过查表将所有对符号的引用转换为特定的内存偏移量,以保证程序运行。

Java编译过程:

Java编译程序将java源程序编译成jvm可执行代码–java字节码。Java编译器却不将对变量和方法的引用编译为数值引用,也不确定程序执行过程中的内存布局,而是将些符号引用信息保留在字节码中,由解释器在运行过程中创立内存布局,然后再通过查表来确定一个方法所在的地址,这样就有效地保证了java的可移植性和安全性。

参考博文:
http://blog.csdn.net/cdh1213/article/details/6919143
http://www.cnblogs.com/lyhero11/p/5080306.html
http://developer.51cto.com/art/201503/467055.htm

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值