JVM内存结构

104 阅读2分钟

img

img

程序计数器(Program Counter Register)

当前线程执行的行号指示器,记录的是正在执行的虚拟机字节码指令的地址 线程私有,每个线程都有独立的程序计数器 线程切换的重要工具 唯一没有oom的区域

java虚拟机栈(Java Virtual Machine Stack)

  • 线程私有

  • java方法执行的线程内存模型,每个方法执行时,都会创建一个栈帧,每个栈帧中记录局部变量,方法出口,动态连接,操作数栈,每个方法被调用直至执行完毕的过程,就是一个栈帧从虚拟机栈中入栈到出栈的过程。所以也叫做方法栈。

  • 局部变量表:存放编译期的各种基本数据类型(八大基础出局类型)、对象引用(不是对象本身,只是一个引用)和returnAddress类型。

  • 会有StackOverflowError和OutOfMemoryError异常

本地方法栈(Native Method Stacks)

  • 和虚拟机栈类似,虚拟机栈记录的是虚拟机执行java方法,本地方法栈则是为虚拟机执行本地方法服务

java堆(java heap)

  • 虚拟机管理内存最大的一块

  • 线程共享,随虚拟机启动时创建

  • 保存实例对象和数组

  • GC发生的区域

  • 支持拓展 -Xms,-Xmx

  • 堆中没有内存完成实例分配,并且堆内存无法拓展时,会出现OOM异常

  • 基于经典分代设计:年轻代(Eden区,S0,S1),老年代

方法区(Method Area)

  • 线程共享,别名非堆(non-heap),目的是与java堆区分开来

  • 存储已被虚拟机加载的类型信息,常量,静态变量,即时编译器编译后的代码缓存等数据

  • 基于永久代实现方法区

  • -XX: MaxPermSize设置永久代大小

  • 1.8开始废弃永久代概念,使用本地内存实现的元空间代替

  • 有垃圾回收,但效率不高,条件苛刻

  • 有OOM异常

运行时常量池(Runtime Constant Pool)

  • 方法区的一部分,用于存放编译器生成的各种字面量和符号引用。

  • 可以动态添加,如String.intern()

  • 会OOM

直接内存(Direct Memory)

  • 不是虚拟机运行时数据区的一部分

  • NIO,可以使用native函数库直接分配堆外内存,然后通过DirectByteBuffer对象作为这块内存的引用进行操作。显著提高了性能,避免了java堆和Native对中来回复制数据

  • 也会有OOM