JVM运行时内存分区

image-20221120194326276

1️⃣程序计数器
  • 记录正在执行的虚拟机字节码指令的地址

  • 字节码解释器通过改变程序计数器来依次读取指令,从而实现代码的流程控制

  • 在多线程的情况下程序计数器用于记录当前线程的执行位置,当线程切换回来时,能够知道上次运行到哪里了

2️⃣虚拟机栈

方法调用的数据需要通过栈进行传递,每一次方法调用就会压入一个栈帧,每一个方法调用结束后就会有一个栈帧弹出

每个栈帧中包含:

  • 局部变量表:存放了方法的参数和局部变量

  • 操作数栈:存放方法执行过程中产生的中间计算结果,临时变量

  • 动态链接:主要服务与一个方法调用其他方法的场景,当一个方法要调用其他方法时,需要将常量池中指向方法的符号引用转化为在内存中的直接引用

  • 方法返回地址

栈中可能出现的两种错误:

  • StackOverFlowError:若栈内存大小不允许动态扩展,那么当栈的深度超过最大深度时抛出

  • OutofMemoryError:若栈内存大小允许动态扩展,如果虚拟机在动态扩展时无法申请到足够的内存空间时,则抛出

3️⃣本地方法栈

本地方法栈与 Java 虚拟机栈类似,它们之间的区别只不过是本地方法栈为本地方法(Native)服务

本地方法一般是用其它语言(C、C++ 或汇编语言等)编写的,并且被编译为基于本机硬件和操作系统的程序,对待这些方法需要特别处理。

4️⃣堆

存放对象实例,几乎所有的对象实例和数组都是在这里分配内存,是垃圾收集的主要区域

堆不需要连续内存空间,并且可以动态增加其内存,增加失败会抛出 OutOfMemoryError 异常

5️⃣方法区

方法区是规范,元空间是实现

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

它是线程共享的,所有线程可以共同访问方法区中的数据。 它主要用于存储字符串池、方法数据、常量数据等,以加速类的加载和执行,减少运行时的内存消耗。

在HotSpot JVM中,方法区的实现为永久代(Permanent Generation),但从JDK1.8开始,已经不再使用永久代,而是使用元空间(Metaspace)代替。元空间不再受堆内存大小限制,它的大小由操作系统内存限制和-XX:MaxMetaspaceSize参数等因素决定。

运行时常量池:运行时常量池是方法区的一部分,用于存放编译期生成的各种字面量和符号引用

和堆一样不需要连续的内存,并且可以动态扩展,动态扩展失败一样会抛出 OutOfMemoryError 异常

HotSpot 虚拟机把它当成永久代来进行垃圾回收。但很难确定永久代的大小,因为它受到很多因素影响,并且每次 Full GC 之后永久代的大小都会改变,所以经常会抛出 OutOfMemoryError 异常。为了更容易管理方法区,从 JDK 1.8 开始,移除永久代,并把方法区移至元空间,它位于本地内存中,而不是虚拟机内存中。

方法区是一个 JVM 规范,永久代与元空间都是其一种实现方式。在 JDK 1.8 之后,原来永久代的数据被分到了堆和元空间中。元空间存储类的元信息,静态变量和常量池等放入堆中。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值