JVM把虚拟机的内存区域划分为方法区(Method Area)、堆(Heap)、栈(Java Stack)、本地方法栈(Native Method Stack)、和一个PC寄存器(程序计数器,Progam Counting Register)。
栈
栈是计算机内存中的一个用于处理函数调用和局部变量存储的数据结构。它是操作系统或虚拟机为每个线程分配的一块内存空间,用于存储函数调用时相关的信息。
当一个函数被调用时,栈会分配一片内存区域来存储该函数的局部变量、参数和返回地址等信息。这些信息会按照特定的格式被依次压入栈中。随着函数的执行结束,栈中的数据会被逐个弹出,恢复到调用该函数的上下文环境。
栈具有"先进后出"的特点,也就是最后进入栈的数据会最先被处理。栈上的数据按照严格的顺序操作,保证了函数调用在执行过程中的正确性和完整性。
堆
堆是计算机内存中的一块动态分配的内存区域,用于存储程序运行时创建的对象和数据。
堆的管理通常使用一种称为"垃圾回收"的机制,它会自动识别不再使用的对象,并将其空间回收,以便重新利用。
方法区
方法区,也称为永久代,是一种用于存储类的元数据(Metadata)和静态变量的内存区域。它是虚拟机中的一部分,用于保存类信息、常量、静态变量、即时编译器编译后的代码等数据。
需要注意的是,从Java 8开始,永久代(Permanent Generation)被移除,取而代之的是元空间(Metaspace),它使用本机内存来存储元数据和类信息。元空间的大小可以根据需要进行自动调整,不再受限于固定大小的永久代。
PC寄存器/程序计数器
程序计数器又称指令计数器(Instruction Counter)或程序指针(Program Pointer),是一种用于指示正在执行的程序的指令位置的寄存器。
程序计数器是CPU中的一个独立寄存器,它保存着当前正在执行的指令的地址。每当CPU从内存中取出一条指令并执行时,程序计数器的值就会自动增加,指向下一条即将执行的指令的地址。也就是说,程序计数器跟踪着CPU下一条将要执行的指令的位置。它还具有保存返回地址和支持循环等功能。
需要注意的是,程序计数器是一个较小的寄存器,它的大小取决于计算机体系结构的位数。例如,在32位架构中,程序计数器通常是一个32位的寄存器,可以表示2^32个内存地址。当程序计数器达到最大值时,将发生溢出并重新从0开始计数。
本地方法栈
本地方法栈是Java虚拟机中用于支持本地方法调用的一块内存区域,与虚拟机栈相对应。它承担着管理本地方法的调用和返回的任务,保存了本地方法的状态信息,包括方法的参数、局部变量和返回值。通过本地方法栈,Java程序可以与底层的本地代码进行交互和调用。本地方法是指在Java代码中调用的由底层语言(如C或C++)编写的方法。
需要注意的是,本地方法栈与虚拟机栈之间是相互独立的,它们分别用于支持Java方法和本地方法的调用。在Java程序中,当调用本地方法时,JVM会通过本地方法栈进行跳转和管理。本地方法栈的生命周期和线程的生命周期一致,当线程结束时,对应的本地方法栈也会被销毁。