运行时数据区包括:
本地方法栈,虚拟机栈区,程序计数器,方法区,堆区。
本地方法栈(Native Method Stack):用于保存本地方法信息。对每一个线程,将创建一个单独的本地方法栈。
Java 虚拟机实现可能会使用到传统的栈(通常称之为“ C Stacks”)来支持 native 方( 指使用 Java 以外的其他语言编写的方法)的执行,这个栈就是本地方法栈( Native MethodStack)。
虚拟机栈 :也就是我们常说的栈区,线程私有,存放基本类型的变量数据,对象的引用变量和返回地址,在编译期间完成分配。
栈的优势是,存取速度比堆要快,仅次于寄存器,栈数据可以共享。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。栈中主要存放一些基本类型的变量数据(int, short, long, byte, float, double, boolean, char)和对象句柄(引用)。
程序计数器(PC寄存器) :线程私有,每个线程都有自己独立的寄存器来保存当前指令的地址,一旦该指令被执行,寄存器变会被更新至下条指令的地址 。
方法区(持久代) :所有线程共享,存储已被虚拟机加载的,在编译期被确定并保存在.class文件中的一些类级别的数据,如类信息,常量,静态变量,即编译器编译后的代码等数据。这个区域的内存回收目标主要是针对常量池的对象的回收和对类型的卸载。
堆区(年轻代+老年代) : JAVA 堆,也称 GC 堆,所有线程共享,存放new创建的对象实例和数组, JAVA 堆是垃圾收集器管理的主要区域。
堆是由垃圾回收来负责的,堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的,但这也导致了它的缺点:存取速度较慢。
由于方法区和堆区的内存由多个线程共享,所以存储的数据不是线程安全的。