Java虚拟机(Java Virtual Machine)在执行Java程序时会把它所管理的内存划分为如下5个不同的运行时数据区域。
1. 程序计数器(Program Counter)
对于一个运行中的Java程序来说,每当启动一个线程时都会创建一个属于自己的程序计数器,各个线程之间的计数器互不影响。如果线程执行的是一个方法(非本地方法),那么计数器记录的是正在执行的虚拟机字节码指令的地址;要是线程执行的是一个本地方法(Native Method),那么计数器则为空(Undefined)。
2. 虚拟机栈(Virtual Machine Stack)
与程序计数器一样,每当启动一个线程时都会创建一个属于自己的虚拟机栈,各个线程之间的虚拟机栈互不影响。线程执行时每调用一个方法,就会创建一个栈帧(Stack Frame)压到虚拟机栈中,当方法执行完正常返回或者抛出异常导致终止都会弹出栈帧。栈帧用于存储本地变量表,操作数栈,动态链接,方法出口等信息。本地变量表的大小在编译时就已经确定并存在于class文件中,在方法运行时大小不会再改变。
3. 堆(Heap)
堆是所有线程共享的内存区域,几乎所有的对象实例和数组都在堆上分配。
4. 本地方法栈(Native Method Stack)
本地方法栈是为执行本地方法服务的。
5. 方法区(Method Area)
方法区是所有线程共享的内存区域,用于存储类信息,常量,静态变量,即时编译器编译后的代码等数据。其中方法区有一个常量池(Constant Pool),在编译期间确定用于存放编译期生成的字面值常量和符号引用,这部分将在类加载后进入方法区的常量池存放。