走进JAVA虚拟机(一)
-------Java虚拟机的体系架构
说起Java这门语言,很多人都知道它具有跨平台的特性,真正做到了“一次编译,到处运行”。而Java能做到与具体平台的无关性则要归功于Java虚拟机,Java虚拟家如同一个翻译家,将同样的Java代码翻译成不同平台认同的相对应指令运行。那么这么一个能力超强的“翻译大家”又是如何工作的呢,我们先从Java虚拟机的体系结构谈起,整体上做个认识,看看庐山真面目!
Java虚拟机有五部分组成,分别是JVM字节码指令集、类加载器、执行引擎、内存区、本地方法栈。其体系结构如下图所示:
提醒:javac编译器不是Java虚拟机的一部分,它是把java源文件编译成字节码文件作为JVM运行的“原材料”。
下面简单介绍一下Java虚拟机这五部分的功能:
JVM字节码指令集:能被JVM解析执行的指令集合。
‚类加载器:把字节码文件读取到虚拟机内存中。
③执行引擎:解析Java虚拟机的字节码指令并执行得到结果,相当于实际机器上的CPU。
④内存区:存储程序运行时的一些数据。
⑤本地方法栈:为虚拟机调用本地方法(native)服务。
JVM执行字节码指令是基于栈的架构,也就是说所有的操作数必须入栈,然后根据指令中的操作码选择从栈顶弹出若干个元素进行计算后在将结果压入栈中。
JVM中操作数可以存放在每一个栈帧中的一个本地变量集中,即每个方法调用时就会再给这个方法分配一个本地变量集,这个本地变量集在编译时就已经确定,所以操作数入栈可以直接是常量入栈或者从本地变量集中取一个变量压入栈中。这和基于寄存器的操作数有所不同。
那么JVM架构为何要基于栈来设计呢?
一是因为JVM要设计成平台无关的,而平台无关性就要保证在没有或者有很少寄存器的机器上也要同样能正确地执行Java代码,如果基于寄存器来设计JVM架构则很难做到这一点。二是因为指令的紧凑性。由于Java字节码可能在网络上传输,故设计JVM字节码指令集时必须考虑到class文件的大小。
执行引擎的架构设计:每当创建一个新的线程时,JVM会为这个线程创建一个Java栈,同时会为这个线程分配一个PC寄存器,并且这个PC寄存器会指向这个线程的第一行可执行代码。每当调用一个新方法时会在这个栈上创建一个新的栈帧数据结构,这个栈帧会保留这个方法的一些元信息,如这个方法中定义的局部变量,一些用来支持常量池的解析、正常方法返回以及异常处理机制等。