程序计数器
指示当前线程需要执行哪条指令;
线程私有的:JVM中,多线程是通过线程轮流切换来获得CPU执行时间的,因此,任意时刻,一个CPU内核只能执行一条线程中的指令,线程完成切换后,需要恢复到正确的执行位置,所以每条线程都需要有一个独立的程序计数器;
如果执行的是一个非native方法,计数器记录的是当前需要执行的指令的地址,如果时一个native方法,则计数器值为undefined;
唯一一个不会发生内存溢出现象(OutOfMemoryError):程序计数器中存储的数据所占空间的大小不会随程序的执行而发生变化
虚拟机栈
存放的是一个个栈帧,每个栈帧对应一个被调用的方法,栈帧中包含:局部变量表,操作数栈,指向运行时常量池的引用,方法返回地址等信息;线程执行一个方法时,创建一个对应的栈帧,并压入栈,执行完成后,将栈帧出栈,(栈顶存放的是该线程正在执行的方法的栈帧);
生命周期与线程相同;
线程私有的:每个线程执行的方法不同;
抛出两种异常:
StackOverflowError:线程请求的栈深度大于虚拟机所允许的深度;
OutOfMemoryError异常:如果虚拟机栈可以动态扩展,扩展时无法申请到足够的内存;
为非Native方法服务;
局部变量表:java基本数据类型(8种),reference(对象引用),returnAddress等
操作数栈:程序中的计算过程(表达式求值)
指向运行时常量池的引用:方法执行过程中需要用到类中的常量
方法返回地址:方法执行完成之后,要返回到调用它的地方
本地方法栈
为Native方法服务;
是线程私有的;
抛出两种异常:
StackOverflowError:线程请求的栈深度大于虚拟机所允许的深度;
OutOfMemoryError异常:如果虚拟机栈可以动态扩展,扩展时无法申请到足够的内存;
堆
存放对象实例以及数组(数组引用是存放在Java栈中的)
线程共享的:JVM中只有一个堆
是垃圾收集器管理的主要区域,也可成为“GC堆”
逻辑上连续,物理上不连续
抛出OutOfMemoryError异常(堆中没有内存完成实例分配,堆也无法再扩展时)
方法区
存储已被虚拟机加载的类信息、常量、静态变量以及编译器编译后的代码等;
是线程共享的;
运行时常量池:用于存放编译期生成的各种字面量和符号引用;
在类和接口被加载到JVM后,对应的运行时常量池就被创建出来;
并非Class文件中常量池的内容才能进入运行时常量池,在运行期间也可将新的常量放入池中,比如String类的intern()方法