历史背景
[图片选自百科]
在60多年前,骨灰级的程序猿是这样子干活的:写一段程序时,找出一条纸带或一张卡片,然后,往上面打孔,没错就是打孔!1打孔,而0不用。
所以,那时候的IDE可想而知,胶水和剪刀就足以~再后来,可怕的人类先后开发出了Fortran、B、C等等。一系列的方便程序员编写的语言就这样腾空出世了。
但也因此带来了新的困扰,同一门语言在不同平台(如:window,Linux)上运行不具有兼容性。
平台、编程语言 | API数量 |
---|---|
C | 200多个 |
Linux | 300多个 |
Windows | 2000多个 |
对,没错。如果你想用c开发既符合Linux和windows平台的程序,除了熟悉C的接口外,你还需熟悉Linux和windows的接口。试问,如今软件更新换代的速度如换衣服一样,谁先开发出来,谁将迅速占有市场,哪有时间给你这样搞?
然后,詹爷出来了。java之父——詹姆斯·高斯林试图设计出另一种语言,它可以1)实现兼容性。2)开发者勿需关注底层平台的异构性。
例如:创建线程时,在Windows调用的接口名称为CreateThread(),而Linux上则叫做pthread_create()。而是否能设计出一种语言——能将开发者写好的的指令,当在不同平台上运输时可以使它自适应。譬如Windows上运行调用CreateThread()接口,而在Linux上则调用pthread_create()。
嗯,对。答案是有的,中间语言就在这样的背景下诞生了。而JVM正是扮演着这种角色——将编译好的java程序(.class文件,中间语言,字节码)翻译成不同平台对应的不同机器指令,而机器指令是能被cpu识别的。
那中间语言怎样翻译成机器语言?
(1)通过C程序翻译第一代的JVM执行引擎(run engine)采用了C来作为中间语言翻译的工具。虽然采用这种方式使得整个执行引擎程序逻辑清晰易懂,但效率真的是很低下!也因此被人们广泛的吐槽,这是第一代JVM的执行引擎所采用的的方式!!原理如下:
//求 A+B
public class Run {
public int add(int a,int b){
return a+b;
}
}
/*
java源程序编译成字节码后,再翻译成对应的机器码,这个过程如下:
执行源程序的jvm本身也被编译——>此时字节码(jvm)对应的c程序一并编译成机器码——>
jvm解释源程序的字节码时自然对应到C程序所对应的机器码。
*/
//字节码
0: iload1
1: iload2
2: iadd
3: ireturn
//C语言的机器码(除去入栈,出栈的操作后)
movl12(%eap),%eax
movl12(%eap),%eax
addl%eax,%eax