这是我参与更文挑战的第11天,活动详情查看:更文挑战
Java虚拟机在执行Java程序的过程中,会把它所管理的内存区域划分为若干个不同的数据区域。这些区域有着各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而一直存在,有些区域则是随着用户线程的启动和销毁而建立和销毁。JVM所管理的内存区域包括以下几个区域。

1 方法区
方法区属于线程共享区域,用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。如果方法区内的数据量超过了这个大小,将导致 OutOfMemoryError。
在Java 6之前,人们常用永生代来称呼方法区,但实际上两者并不等价,只是由于HotSpot开发者用永生代来实现方法区以方便方法区的垃圾回收,才出现把方法区称为永生代。在Java 7中,字符串常量池、静态变量被移出“永生代”,大大增加了字符串常量池的容量上限,从而降低了OutOfMemoryError 发生的概率。在 Java 8之后,完全废弃了”永生代”的概念,又将方法区移到本地内存的元空间(Metaspace)中。
2 堆
Java 堆是虚拟机所管理的内存区域最大的一块,也是属于线程共享区域。Java堆的唯一目的就是存放对象示例,Java 中“几乎”所有的对象实例都是在这里分配内存。Java 堆是垃圾收集器管理的内存区域。
从内存分配的角度看,Java 堆可以划分出多个线程私有的分配缓冲区(TLAB),以提升对象分配的效率。可扩展设计的 Java 堆的大小可通过参数-Xmx 和 -Xms 设定。如果在Java 堆中没有内存完成实例分配,并且堆无法再扩展(物理内存已满无法提供堆内存扩展或者堆的大小已经达到-Xmx 设定的大小),则会抛出OutOfMemoryError异常。
3 程序计数器
程序计数器用于指示当前线程所执行的字节码行号,所以属于线程私有的区域。在 JVM 的模型概念里,字节码解释器工作时就是通过改变这个计数器值来选取下一条需要执行的字节码指令。它是线程控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都需要程序计数器来完成。
如果线程正在执行一个Java方法,则计数器记录的是正在执行的虚拟机字节码指令的地址。如果线程正在执行一个本地方法,则计数器值为空。
4 Java 虚拟机栈
Java 虚拟机栈也是线程私有的,生命周期与线程相同。虚拟机栈记录的是Java方法执行的内存模型。每个方法执行时,JVM都会同步创建一个栈帧,并将栈帧压入虚拟机栈中。方法执行完毕后,对应的栈帧会出栈。每个栈帧一般包括以下四个部分:
- 局部变量表:用于存放方法参数和方法内部定义的局部变量。
- 操作数栈:字节码指令的操作数存储栈
- 动态连接:用于存放指向运行时常量池的引用
- 返回地址:记录上层调用方法调用位置
虚拟机栈存在两类异常情况:如果线程请求的栈深度大于虚拟机允许的最大深度,会抛出StackOverflowError异常;当栈扩展时无法申请到足够的内存则会抛出OutOfMemoryError异常。
5.本地方法栈
与虚拟机栈类似,区别是本地方法栈服务于本地调用。同样,本地方法栈存在两种异常情况:StackOverflowError异常和OutOfMemoryError异常。
6.运行时数据区内存模型























![[桜井宁宁]COS和泉纱雾超可爱写真福利集-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/4d3cf227a85d7e79f5d6b4efb6bde3e8.jpg)

![[桜井宁宁] 爆乳奶牛少女cos写真-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/d40483e126fcf567894e89c65eaca655.jpg)