剖析 Java 内存结构,深入了解程序运行机制
2023-12-16 17:36:36
程序计数器(Program Counter Register)属于内存中比较小的一块空间,属于线程私有的,其作用可以大概理解为记录当前线程所执行的字节码位置,或者通俗来说可以理解为代码执行到第几行了。为什么需要这么一小块空间做这种事情呢?因为 JVM 的多线程操作实际上并不是真正意义上的并行,是通过线程轮流切换并分配 CPU 执行时间片实现的。
- 程序计数器
程序计数器(Program Counter Register)是一块较小的内存空间,用于存储当前线程正在执行的指令地址。它的大小取决于底层机器的指令集架构,在 32 位机器上通常为 32 位,在 64 位机器上通常为 64 位。程序计数器由 JVM 维护,并且每个线程都有自己的程序计数器。当一个线程开始执行时,程序计数器被初始化为该线程要执行的第一个指令的地址。随着线程的执行,程序计数器会不断更新,指向下一条要执行的指令。如果线程执行的是一个循环,那么程序计数器会不断地在循环的指令之间来回移动。
- Java 虚拟机栈
Java 虚拟机栈(Java Virtual Machine Stack)是 Java 虚拟机中用于存储方法调用信息的空间。它是一个后进先出(LIFO)的数据结构,这意味着最后被压入栈中的方法调用信息将首先被弹出。当一个方法被调用时,它的参数、局部变量和返回地址都被压入栈中。当方法执行完毕后,它的信息被弹出栈中。Java 虚拟机栈的大小是有限的,如果栈溢出,则会抛出 StackOverflowError 异常。
- 本地方法栈
本地方法栈(Native Method Stack)是 Java 虚拟机中用于存储本地方法调用信息的空间。本地方法是指用 C 或 C++ 等语言编写的代码,可以直接被 Java 虚拟机调用。本地方法栈与 Java 虚拟机栈类似,也是一个后进先出(LIFO)的数据结构。当一个本地方法被调用时,它的参数和局部变量都被压入栈中。当本地方法执行完毕后,它的信息被弹出栈中。本地方法栈的大小也是有限的,如果栈溢出,则会抛出 StackOverflowError 异常。
- 堆
堆(Heap)是 Java 虚拟机中用于存储对象的空间。对象是程序中的基本组成单位,它包含数据和行为。当一个对象被创建时,它被分配到堆中。堆是一个动态分配的空间,这意味着它可以根据需要扩展或缩小。堆的大小通常由 -Xmx 和 -Xms 两个参数控制。
- 方法区
方法区(Method Area)是 Java 虚拟机中用于存储类信息的空间。类信息包括类的名称、方法、字段和常量。当一个类被加载到 Java 虚拟机中时,它的信息被存储在方法区中。方法区的大小通常由 -XX:MaxPermSize 参数控制。
- 元空间
元空间(Metaspace)是 Java 8 中引入的一个新的内存区域,用于存储类信息。元空间与方法区类似,但它不是堆的一部分,而是属于本地内存。元空间的大小通常由 -XX:MetaspaceSize 参数控制。