面试必问,JVM内存模型扫盲

运行时常量池(Runtime Constant Pool)是方法区中的一部分 , 用于存储编译期间生成的各种字面量和符号引用 。在JAVA程序运行时 , JVM将编译期生成的class文件中的常量池内容读取到运行时常量池中 。JVM简介JVM(Java Virtual machine , Java虚拟机)是Java语言的核心 , 是一个用于解释Java字节码的虚拟计算机 。它可以在运行Java程序时自动管理内存、处理异常等 。Java程序员不需要关心底层硬件和操作系统的细节 , 只需要编写符合Java语法规范的代码 , 就可以实现跨平台的编程 。
当我们编写Java程序时 , Java源代码会被编译成为Java字节码( .java 文件被编译成 .class 文件) 。这些字节码可以在任何安装了Java虚拟机的平台上运行 。JVM在执行Java字节码时 , 将其转换成特定于底层CPU和操作系统的机器代码 。
运行时数据区简介为了执行字节码 , JVM在内存中定义了一系列的数据区 , 用于在运行时存储各类数据 , 即运行时数据区(Runtime Data Areas) 。理解这些数据区及其作用 , 是掌握Java性能调优和错误排查的关键 。
JVM 运行时数据区是 Java 虚拟机在执行 Java 程序时用于数据存储的内存区域 , 这些区域各司其职 , 确保了 Java 程序的正确执行 。JVM 运行时数据区主要分为五个部分:程序计数器(Program Counter Register)、虚拟机栈(VM Stack)、本地方法栈(Native Method Stack)、堆(Heap)、方法区(Method Area) 。JVM运行时数据区在程序运行时动态地分配和释放内存 , 内存管理由JVM自动完成 。不同的数据区域有不同的内存管理机制和垃圾回收算法 , 以保证程序运行的效率和稳定性 。
其中程序计数器、虚拟机栈、本地方法栈属于线程私有区域 , 跟随线程的启动和结束而建立和销毁 。堆和方法区是线程共享区域 , 跟随虚拟机进程的启动而存在 。
程序计数器(Program Counter Register) 是一块较小的内存空间 , 作用是指示当前线程正在执行的 JVM 字节码指令地址 。
虚拟机栈(VM Stack) 存放的是一些基本类型的变量(如int, long)和对象引用 。Java 方法执行的内存模型是以栈帧(Stack Frame)为基础的 , 每个方法在执行的时候都会创建一个栈帧 , 栈帧中存放了局部变量表、操作数栈、动态链接、方法出口等信息 。
本地方法栈(Native Method Stack) 与虚拟机栈类似 , 其主要服务于 JVM 使用到的 Native 方法 。
堆区(Heap) 是 JVM 所管理的最大一块内存空间 , 主要用于存放所有线程共享的 Java 对象实例 。这也是垃圾回收器主要活动区域 。
方法区(Method Area) 是用来存储加载的类信息、常量、静态变量等数据的 。这个区域是线程共享的 。

面试必问,JVM内存模型扫盲

文章插图
1. 程序计数器程序计数器(Program Counter Register)是线程私有区域 , 生命周期与线程一致 , 也是 JVM 内存中唯一一个没有任何 OutOfMemoryError 的区域 。
程序计数器的作用是记录当前线程正在执行的指令地址 , 换句话说 , 它指向了下一条将要被执行的 JVM 字节码指令 。在 JVM 的概念模型中 , 字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令 。
当线程执行的是 Java 方法时 , 这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是 Native 方法 , 这个计数器的值则为空(Undefined) 。
程序计数器对于现代多线程而言至关重要 , 因为在 CPU 切换各个线程时 , 需要将各个线程的程序计数器记录下来 , 以便在下一次切换回这个线程时 , 能知道该从哪里继续执行 。
总结: