1 Java虚拟机简介
Java虚拟机是整个Java平台的基石,是Java技术用以实现硬件无关与操作系统无关的关键部分,是Java语言生成出极小体积的编译代码的运行平台。
Java虚拟机与Java语言无必然联系,它只与特定的二进制文件格式——class文件格式所关联。class文件包括:
- Java虚拟机指令集(字节码)
- 符号表
- 其他辅助信息
Java虚拟机在class文件中施加了许多强制性的语法和结构化约束,凡是能用class文件正确表达出来的编程语言,都可放在Java虚拟机里面执行。由于它是一个通用的、机器无关的执行平台,所以其他语言的实现者都可以考虑将Java虚拟机作为那些语言的交付媒介。
2 Java虚拟机结构
2.1 class文件格式
编译后被Java虚拟机执行的代码使用平台中立(不依赖特定硬件和操作系统)的二进制文件表示,经常以文件形式存储,因此这种格式被称为class文件格式。
2.2 数据类型
与Java程序中数据类型相似,Java虚拟机可以操作的数据类型分为:原始类型(原生/基本)、引用类型。
2.3 原始类型与值
2.4 引用类型与值
Java虚拟机有以下三种引用类型:
- 类类型:指向动态创建的类实例,
- 数组类型:指向数组实例
- 接口类型:指向实现某个接口的类实例或数组实例
数组类型最外面那一维元素的类型(此维度的长度不由数组类型来决定),叫做该数组类型的组件类型( component type)。°一个数组的组件类型也可以是数组。从任意一个数组开始,如果发现其组件类型也是数组类型,那就继续取这个小数组的组件类型,不断执行这样的操作,最终一定可以遇到组件类型不是数组的情况,这时就把这种类型称为本数组类型的元素类型(element type)。数组的元素类型必须是原生类型、类类型或者接口类型之一。
2.5 运行时数据区
2.5.1 pc寄存器
Java虚拟机支持多条线程同时执行,每条线程都有自己的pc寄存器。
任意时刻,一条Java虚拟机线程只会执行一个方法的代码,该方法称为“当前方法”(current method)。
- 如果当前方法不是本地(native)的,那pc寄存器保存JVM正在执行的字节码指令地址
- 如果当前方法是本地的,则pc寄存器值是undefined
2.5.2 Java虚拟机栈
每条JVM线程都有自己私有的Java虚拟机栈,这个栈与线程同时创建,用于存储栈帧。
Java虚拟机栈用于存储局部变量和尚未计算好的结果。
Java虚拟机栈可以被实现为固定大小,也允许动态扩缩,可能发生的异常:
- 线程请求分配的栈容量超过JVM栈允许的最大容量,JVM将会抛出一个
StackOverflowError
异常 - 如果JVM栈是可动态扩展,但在扩展时无法申请到足够内存,或者创建新线程时无足够内存去创建JVM栈,则会抛出
OutOfMemoryError
异常
2.5.3 Java堆
堆是可供各个线程共享的运行时内存区域,也是供所有类实例和数组对象分配内存的区域。
Java堆在虚拟机启动时被创建,它存储了被自动内存管理系统(GC)管理的各种对象。
2.5.4 方法区
方法区是可供各个线程共享的运行时内存区域,与传统的编译代码存储区类似,存储每个类的结构信息,例如:运行时常量池、字段和方法数据、构造函数和普通方法的字节码内容,还包括一些在类、实例、接口初始化时用到的特殊方法。
2.5.5 运行时常量池
运行时常量池是class文件中每一个类或接口的常量池表的运行时表示形式,包括若干种不同的常量,从编译期可知的数值字面量到运行期解析后才能获得的方法或字段引用。类似于传统符号表,不过存储范围更广泛。
2.5.6 本地方法栈
Java虚拟机实现可能会使用到传统的栈(通常称为C stack)来支持native方法(指使用Java 以外的其他语言编写的方法)的执行,这个栈就是本地方法栈( native method stack)。