常常提到JAVA内存,都会想起“堆”与“栈”。对JAVA内存结构,并没有很详细的认识,现对JAVA内存结构的一些主要信息进行整理,以作备忘之用。
JAVA内存结构,又称运行时数据区。JAVA虚拟机定义了若干种程序运行期间会使用到的运行时数据区。其中一些会随着虚拟机的启动而创建,随着虚拟机的退出而销毁。另一些与线程一一对应,随着线程的开始和结束而创建和销毁。
PC寄存器
PC寄存器是每个JAVA虚拟机线程私有的。一个JAVA虚拟机线程只会执行一个方法的代码,这个正被线程执行的方法称为该线程的当前方法。如果该方法是native的,PC寄存器的值是undefined;如果这个方法不是native的,那么PC寄存器就保存JAVA虚拟机正在执行的字节码指令的地址。
JAVA虚拟机栈
JAVA虚拟机栈是每个JAVA虚拟机线程私有的。它用于储存栈帧,在方法调用和返回结中扮演非常重要的角色。
JAVA虚拟机规范允许JAVA虚拟机栈被实现成固定大小的或者是根据计算动态扩展和收缩的。
当分配的栈容量超过 Java 虚拟机栈允许的最大容量时,Java 虚拟机将会抛出一个StackOverflowError 异常。
当JAVA虚拟机栈可以动态扩展时,如果经过扩展仍无法申请足够内存或者创建新线程时无足够内存创建JAVA虚拟机栈,那么 Java 虚拟机将会抛出一 个 OutOfMemoryError异常。
JAVA堆
JAVA堆在虚拟机启动时就被分配,它是各线程共享的运行时内存区域。JAVA堆的容量可以是固定大小的,也可以随着程序执行的需求动态扩展,并在不需要过多空间时自动收缩。所有类实例和数组对象将分配到该内存的区域。它储存的的各种对象,无法显示地销毁,统一由垃圾回收器进行管理。如果实际所需的堆超过了自动内存管理系统能提供的最大容量,那 Java 虚拟机将会抛出一个OutOfMemoryError 异常。
方法区
方法区在虚拟机启动时就被分配,它是各线程共享的运行时内存区域,用于存储的是每个类的结构信息。如果方法区的内存空间不能满足内存分配请求,那 Java 虚拟机将抛出一个OutOfMemoryError 异常。
运行时常量池
运行时常量池是每个类或者接口的常量池运行时的表现形式。每一个运行时常量池都分配在 Java 虚拟机的方法区之中,在类和接口被加载到虚拟机后,对应的运行时常量池就被创建出来。
本地方法栈
如果JAVA虚拟机不支持native方法,就不需要支持本地方法栈,它在JVM的实现上并不是必须的。相反,如果支持native方法,那它会在线程创建时,按线程分配。