实现运行时数据区
(run-time data area)
在运行Java程序时,Java虚拟机需要使用内存来存放各式各样的数据。Java虚拟机规范把这些内存区域叫作运行时数据区。
运行时数据区可以分为两类:
a.线程私有的。
创建线程时才创建,线程退出时销毁。用于辅助执行Java字节码。
每个线程都有自己的
pc寄存器(Program Counter)
如果当前方法是Java方法,则pc寄存器中存放当前正在执行的Java虚拟机指令的地址,否则,当前方法是本地方法,pc寄存器中的值没有明确定义。-
Java虚拟机栈(JVM Stack)。
由栈帧(Stack Frame,后面简称帧)构成,帧中保存方法执行的状态,包括-
局部变量表(Local Variable)
大小由编译器预先计算好的, 存储在class文件method_info结构的Code属性中
按索引访问的,所以很自然,可以把它想象成一个数组。根据Java虚拟机规范,这个数组的每个元素至少可以容纳一个int或引用值,两个连续的元素可以容纳一个long或double值。 -
操作数栈(Operand Stack)
大小由编译器预先计算好的, 存储在class文件method_info结构的Code属性中
在任一时刻,某一线程肯定是在执行某个方法。这个方法叫作该线程的当前方法;执行该方法的帧叫作线程的当前帧;声明该方法的类叫作当前类。
-
局部变量表(Local Variable)
b.多线程共享的,
Java虚拟机启动时创建好,在Java虚拟机退出时销毁
主要存放两类数据:
-
类
放在方法区(Method Area)中,包括字段和方法信息、方法的字节码、运行时常量池,等等。从逻辑上来讲,方法区其实也是堆的一部分。 -
对象
放在堆(Heap)中,堆由垃圾收集器定期清理,程序员不需要关心对象空间的释放。
Java虚拟机规范对于运行时数据区的规定是相当宽松的。
堆(heap):
堆可以是连续空间,也可以不连续。
大小可以固定,也可以在运行时按需扩展 [-Xms
和-Xmx
两个非标准选项,用来调整堆的初始大小和最大大小] 。
虚拟机实现者可以使用任何垃圾回收算法管理堆,甚至完全不进行垃圾收集也是可以的。
Java虚拟机栈:
可以是连续的空间,也可以不连续;
可以是固定大小,也可以在运行时动态扩展 [-Xss
选项设置大小] 。
如果Java虚拟机栈有大小限制,且执行线程所需的栈空间超出了这个限制,会导致StackOverflowError
异常抛出。
如果Java虚拟机栈可以动态扩展,但是内存已经耗尽,会导致OutOfMemoryError
异常抛出。
4.2 Java虚拟机数据类型
Java虚拟机可以操作两类数据:
基本类型(primitive type)
基本类型的变量存放的就是数据本身,基本类型可以进一步分为:
- 布尔类型(boolean type)
- 数字类型(numeric type): 整数类型(integral type), 浮点数类型(floating-point type)
引用类型(reference type)
引用类型的变量存放的是对象引用,真正的对象数据是在堆里分配的。
引用类型可以进一步分为3种:
- 类:指向类实例
- 接口:指向实现了该接口的类或数组实例
-
数组:指向数组实例
还有一个特殊的值——null,表示该引用不指向任何对象。