Java虚拟机内存结构


JVM内存模型分区


  • 运行数据区: Java虚拟机在运行Java程序时,管理的一块内存区域
  • 在运行数据区中,根据用途分为:


    • Java堆
    • Java虚拟机栈
    • 本地方法栈
    • 方法区
    • 程序计数器
      JVM虚拟机Day01-Java虚拟机内存结构_jvm



Java堆


  • Java堆: 堆内存Heap, 堆区. 是垃圾收集器管理的主要区域,所以也称做GC
  • 作用: 用于存放Java对象实例
  • 特点:

  • 线程共享
  • 从内存分配角度来说 ,Java堆相当于多个线程私有的分配缓冲区
  • JVM中占用的内存最大
  • 从内存回收角度 ,Java堆分为:

  • 新生代
  • 老年代


  • Java堆中没有足够的内存完成对象的实例分配时,也就是Java堆无法再扩展时.会抛出内存泄漏异常OutOfMemoryError

Java虚拟机栈


  • Java虚拟机栈: 栈内存Stack, 栈区. 是StackJava方法执行的内存模型
  • 作用: 用于存放Java方法执行时的局部变量

  • 以帧栈的形式存放
  • 包含数据类型和对象的引用
  • 在方法执行结束释放

  • 特点:

  • 线程私有
  • 生命周期与线程相同

  • 每一个Java方法执行时都会创建一个栈帧
  • 一个Java方法从被调用到执行完成就相当于栈帧在Java虚拟机栈中的入栈到出栈
  • 局部变量表所需要的内存空间在方法编译时就会完成内存分配,在方法运行时不会改变大小
  • Java虚拟机栈扩展时无法申请到内存空间时会抛出内存泄漏异常OutOfMemoryError
  • Java运行的线程请求的栈深度大于Java虚拟机栈允许的深度时会抛出StackOverflowError

本地方法栈

  • 本地方法栈的作用和Java虚拟机栈类似.区别在于:

  • Java虚拟机栈是为执行的Java方法服务
  • 本地方法栈是为执行Native本地方法服务

方法区


  • 方法区: 非堆区Non-Heap, 堆的一个逻辑部分
  • 作用: 用于存储已虚拟机加载的类信息, 常量, 静态变量等数据
  • 特点: 线程共享
  • 本地方法区又称为永久代,该区的回收条件苛刻,很少出现垃圾收集
  • 方法区的内存回收主要是针对运行时常量池和类的卸载时的内存回收
  • 方法区当无法满足内存分配需求时会抛出内存泄漏异常OutOfMemoryError

运行时常量池


  • 运行时常量池: 方法区的内部包含一个运行时常量池,属于方法区的一部分
  • 作用: 用于存放类文件编译时生成的各种字面量和符号引用
  • 特点: 动态性,可以在运行时添加新的常量
  • 运行时常量池当常量池无法申请到所需要的内存时会抛出内存泄漏异常OutOfMemoryError

程序计数器


  • 程序计数器: 当前程序所执行的字节码的行号指示器
  • 作用: 用于实现异常处理,线程恢复等基础功能
  • 原理: 通过改变计数器的值,来选取下一条执行的字节码指令
  • 特点:

  • 线程私有
  • 内存空间小

  • 线程私有的内存区域
  • 为了能够使得线程切换后恢复到正确的执行位置,每个线程都有一个独立的程序计数器
  • 各个线程的程序计数器之间互不影响,独立存储的内存区域
  • 程序计数器是JVM中唯一一个不会抛出内存泄漏异常OutOfMemoryError的内存区域

直接内存


  • 直接内存: NIO类中基于通道和缓冲区的IO方式,通过使用Native函数库直接分配的堆外内存
  • 特点:

  • 不受JVM的堆大小的限制
  • 不属于JVM运行时数据区的一部分,不会在堆中分配

  • 直接内存当使用Native函数库直接分配内存时无法获取到内存空间会抛出内存泄漏异常OutOfMemoryError
  • 直接内存的应用场景:

  • 适用于频繁调用的场景
  • 通过一个存储在Java堆中的DirectByteBuffer对象作为直接内存的引用,从而避免在Java堆和Native方法之间频繁复制数据以提高性能