最近一段时间面试经常被问到java中堆和栈的问题,为了后面不会忘,于是整理一份。其实这是java内存区域划分的问题,也就是jvm内存区域划分的问题(如何分配和回收内存空间)。
java数据区通常包括这几个部分:程序计数器(Program Counter Register)、Java栈(VM Stack)、本地方法栈(Native Method Stack)、方法区(Method Area)、堆(Heap)。
程序计数器:用于指示需要执行的指令,每个进程各自拥有独立的程序计数器。
Java栈:由栈帧组成。栈帧在一个方法被调用时创建,并压栈。在方法结束时出栈。故当前java栈顶部的栈帧必对应正在执行的方法。每个进程各自拥有独立的java栈。栈帧中记录的内容包含:局部变量表(Local Variables)、操作数栈(Operand Stack)、指向当前方法所属的类的运行时常量池的引用(Reference to runtime constant pool)、方法返回地址(Return Address)和一些额外的附加信息。
局部变量表:对于基本数据类型的变量直接存储它的值,对于引用类型的变量则存储指向对象的引用。
操作数栈:可理解为java虚拟机栈中的一个用于计算的临时数据存储区,用于方法执行时零时存储数据的。
指向常量池的引用:常量不存储在java栈中,所以栈用需要使用常量就需要存储常量的引用。
方法返回地址:方法完成后,需要返回之前调用该方法的方法,所以需要存储方法返回前的地址。
本地方法栈:与java栈作用类似,一个用于执行java方法,一个用于执行本地方法。
堆:用于存储对象实例和数组实例的。由所有线程共享。
方法区:存储类信息(类名、方法信息、字段信息)、静态变量、常量(运行时常量池)、以及编译器编译后的代码。