JVM内存知识点(堆、栈、方法区)

204 阅读2分钟

堆(所有线程共享)

JVM中最大的一块内存区域,存储所有的对象实例和数组。

堆内存由垃圾回收器管理,垃圾回收器会自动释放不再被引用的对象占用的内存。

栈(每个线程独立)

每个线程都有自己的栈内存。栈用于存储局部变量、方法参数、返回地址、方法调用链等。

栈具有快速分配和释放的特点。每次方法调用都会在栈中创建一个新的栈帧,方法执行完毕后会呗自动销毁。

什么是栈帧:

栈帧存储方法的局部变量,包括参数和方法内部声明的变量。

为什么需要栈帧,而不是直接将数据存储到线程的栈中:

  1. 方法调用的递归和嵌套

方法递归的时候,每次调用都需要独立维护自己的执行环境和状态。这包括 局部变量、参数和计算得到的结果。每个栈帧单独存储这些信息,确保各个方法调用不干扰。

  1. 便于管理方法的调用和返回、

栈帧是的方法的调用和返回更加的简单。每个栈帧包含方法返回地址,当方法执行完毕时,JVM可以通过栈帧信息找到返回地址并恢复调用方法的执行。

  1. 错误处理和调试

栈帧在处理异常中也起到重要作用。当方法抛出异常的时候,栈帧信息用于构建异常堆栈跟踪(也就是找到代码错误位置)。

小结

栈帧的设计是为了方法间的独立,防止方法间变量冲突、方法返回地址混乱等问题。

方法区

方法区存储已加载类信息、常量池、静态变量、即使编译后的代码等。

方法区也是堆的一部分,所以方法区也是线程间共享的内存。

为什么方法区是共享的?

  1. 类和元数据的统一管理

当一个类被加载时,JVM在方法区创建这个类的元数据结构。这个结构对于所有线程是共享的,因为同一个类只需要在内存中有一个表示。

  1. 常量池共享

常量池中的字面量和符号引用需要被所有线程访问,特别是在类的加载和连接阶段,以及在运行时常量池解析时。

  1. 静态变量共享

静态变量是类级别的变量,所有线程都应当能访问和修改这些变量。

什么是字面量?

字面量是在编译的时候就知道的变量,如字符串常量、整数常量等(存在类中的变量)