JVM概述

历史背景

[图片选自百科]
JVM概述_第1张图片


在60多年前,骨灰级的程序猿是这样子干活的:写一段程序时,找出一条纸带或一张卡片,然后,往上面打孔,没错就是打孔!1打孔,而0不用。

JVM概述_第2张图片

所以,那时候的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

(2)由于效率原因使得java变得寸步难行,于是为了java的生存改用了另一种方法,将中间语言直接翻译为机器码。即通过将cpu的cs:ip段寄存器(cpu内部的寄存器)指向代码段入口即可。注:cs保存段地址,ip保存偏移地址,了解过操作系统原理的道友肯定熟知这个!!!


虽然解决办法有了,但由于java有自己的一套内存管理机制和代码执行方式,比起C直接编写机器码,还要多出很多指令,因此效率不高。不过呀,人类还是聪明的,时至今日,由于大牛们天马行空却又切实可行的想法,使得代码运行速度得到大幅度的提升。采用的方法有如:将中间语言的翻译过程从运行期转到编译期!!!(如,安卓和部分jvm实现的AOT(静态编译技术)特性。)


另外,由于jvm可以在运行时基于上下链路(为了cpu可以执行代码所需要做的一些工作)做各种优化,也是使得它效率不断提高的原因之一。时至今日,java已然广受欢迎,而在并发技术方面,更需要我们深入了解jvm底层原理。

你可能感兴趣的:(JVM深入学习,JVM,java,静态编译,汇编)