方法区和堆为线程共享区,虚拟机栈、本地方法栈及程序计数器为线程独占区。
堆(Heap)
为线程共享区,堆内存用于存放由new创建的对象和数组。
堆也是Java垃圾回收的主要区域(重点对象),因此也称作“GC堆”(Garbage Collected Heap)。如果堆中没有内存完成实例分配,并且堆也无法再扩展时,将会抛出OutOfMemoryError异常。
方法区(Method Area)
又叫静态区,跟堆一样,被所有的线程共享。方法区包含所有的class信息、static变量、常量。
当方法区无法满足内存分配需求时,抛出OutOfMemoryError异常。
虚拟机栈(JVM Stacks)
虚拟机栈线程私有,生命周期与线程相同,虚拟机栈动态扩展时无法申请到足够的内存时会抛出OutOfMemoryError异常。
存储局部变量表、操作数栈、动态链接、方法出口等信息。
局部变量表(Local Variable Table)是一组变量值存储空间,用于存放方法参数和方法内定义的局部变量。包括8种基本数据类型、对象引用(reference类型)和returnAddress类型(指向一条字节码指令的地址)。
操作数栈(Operand Stack)也称作操作栈,随着方法执行和字节码指令的执行,会从局部变量表或对象实例的字段中复制常量或变量写入到操作数栈,再随着计算的进行将栈中元素出栈到局部变量表或者返回给方法调用者,也就是出栈/入栈操作。
动态链接:Java虚拟机栈中,每个栈帧都包含一个指向运行时常量池中该栈所属方法的符号引用,持有这个引用的目的是为了支持方法调用过程中的动态链接(Dynamic Linking)。
方法返回:无论方法是否正常完成,都需要返回到方法被调用的位置,程序才能继续进行。
本地方法栈(Native Method Stacks)
本地方法栈(Native Method Stacks)与虚拟机栈作用相似,也会抛出OutOfMemoryError异常。
区别在于虚拟机栈为虚拟机执行Java方法(字节码)服务,而本地方法栈是为虚拟机使用到的Native方法服务。
程序计数器(Program Counter Register)
占用内存较小,线程私有。它是唯一没有OutOfMemoryError异常的区域。
它可以看作是当前线程所执行的字节码的行号指示器。