JVM内存模型

JVM内存模型

简单来说JVM内存模型是什么样的?

线程私有区:

  • 程序计数器,记录正在执行的虚拟机字节码的地址;
  • 虚拟机栈,方法执行的内存区,每个方法执行时在虚拟机栈中创建栈帧;
  • 本地方法栈,虚拟机的Native方法执行的内存区;

线程共享区:

  • Java堆:对象分配内存的区域;
  • 方法区:存放类信息、常量、静态变量、编译器编译后的代码等数据;
    • 常量池:存放编译器生成的字面量和符号引用,是方法区的一部分。

通常所说的Java堆和Java栈是指什么?

通常所说的Java堆指的是共享数据区的堆,Java栈指的是线程私有的虚拟机栈。

JVM中更详细的内存模型是什么样的?

JVM更详细的内存模型

程序计数器

  1. 每个线程都有计数器,是私有内存空间,该区域是整个内存中较小的一块。
  2. 当线程正在执行一个Java方法时,PC计数器记录的是正在执行的虚拟机字节码的地址。
  3. 当线程正在执行Native方法时,PC计数器则为空

虚拟机栈

栈祯是用于支持虚拟机进行方法执行的数据结构,是属性运行时数据区的虚拟机的栈元素。

  1. 局部变量表,一组变量存储空间,容量以slot为最小单位。
  2. 操作栈(stack大小,编译器确定),操作栈元素的数据必须与字节码指令序列严格匹配。
  3. 动态连接,指向运行时常量池中该栈所属方法的引用,为了动态连接使用。
    • 前面的解析过程是静态解析
    • 对于运行期转化为直接引用,动态解析。
  4. 方法返回地址
    • 正常退出,执行引擎遇到方法返回的字节码,将返回值传递给调用者。
    • 异常退出,遇到Exception,并且方法未捕获异常,不会有任何返回值。
  5. 额外附加信息,由具体虚拟机实现。

异常(Exception)

  • StackOverFlowError:当线程请求栈深度超出虚拟机栈允许深度时抛出
  • OutOfMemoryError:当Java虚拟机动态扩展到无法申请足够内存时抛出

本地方法栈

本地方法栈为虚拟机使用到的Native方法提供内存空间,而虚拟机栈则为Java方法提供内存空间。

Java堆

Java堆是虚拟机管理的最大一块内存,也是GC的主战场,存放的是几乎所有的对象实例和数组数据。

  • 从内存回收角度,Java堆被分为新生代和老年代;为了更快地回收内存。
  • 从内存分配角度,Java堆可以划分出线程私有的分配缓冲区(Thread Local Allocation Buffer,TLAB),为了更快地分配内存。

对象实例结构是什么样的?

对象实例结构

填充数据不一定存在,是为了字节对齐而存在的

此区域可以抛出OOM Error异常

方法区

主要存放被虚拟机加载的类信息、常量、静态变量、编译器编译后的代码数据。

此区域可以抛出OOM Error异常

运行时常量池

属于方法区的一部分,用于存放编译器生成的各种字面量和符号引用。运行时常量池除了编译器产生的Class文件的常量池,还可以在运行期,将新的常量加入常量池,比如String的intern()方法。

  • 字面量:与Java语言层面的常量概念相近,包含文本字符串,声明为final的常量值等等。
  • 符号引用:
    • 类和接口的全限定名
    • 字段的名称和描述符
    • 方法的名称和描述符

此区域不会抛出OOM Error异常