Java内存区域

Java内存区域

Java内存区域就是Java运行时数据区

  • 线程私有的:程序计数器、虚拟机栈、本地方法栈
  • 线程共享的:堆、方法区

1.程序计数器

程序计数器是什么:可以看作是当前线程所执行的字节码的行号指示器

程序计数器的作用:

  • 实现代码的流程控制
  • 确保线程切回时抵达正确位置

2.虚拟机栈

栈是 JVM 运行时数据区域的一个核心,除了一些 Native 方法是本地方法栈实现的

其他所有 Java 方法的调用都是由虚拟机栈协助执行的

虚拟机栈由一个个栈帧组成,栈帧的组成有:

  • 局部变量表
  • 操作数栈
  • 动态链接
  • 方法返回地址

接下来我们一个个说明他们的作用

局部变量表

局部变量表用来存放:

  • 方法的this对象
  • 方法的参数
  • 方法内部定义的局部变量

局部变量表是一组变量值存储空间,用于存放方法参数和方法内部定义的局部变量。在Java程序被编译成Class文件时,就在方法的Code属性的max_locals数据项中确定了该方法所需要分配的最大局部变量表的容量。

操作数栈

操作数栈也是栈结构,可以简单的理解它的作用就是方法中变量进行运算

动态链接

主要服务一个方法调用另一个方法的场景

动态链接的作用就是为了将符号引用转换为直接引用

方法返回

无论方法采用何种方式退出,在方法退出后都需要返回到方法被调用的位置,程序才能继续执行,方法返回时可能需要在当前栈帧中保存一些信息,用来帮他恢复它的上层方法执行状态。
方法退出过程实际上就等同于把当前栈帧出栈,因此退出可以执行的操作有:恢复上层方法的局部变量表和操作数栈,把返回值(如果有的话)压入调用者的操作数栈中,调整PC计数器的值以指向方法调用指令后的下一条指令。
一般来说,方法正常退出时,调用者的PC计数值可以作为返回地址,栈帧中可能保存此计数值。而方法异常退出时,返回地址是通过异常处理器表确定的,栈帧中一般不会保存此部分信息。

3.本地方法栈

调用Native方法

4.堆

堆是线程共享的。

JDK7版本以及JDK7版本之前,堆内存通常分为下面三部分:

  1. 新生代(年轻代)内存
  2. 老年代
  3. 永久代

下图中的Eden区、两个S区S0、S1都属于新生代

在这里插入图片描述

在这里插入图片描述

JDK8版本之后永久代被元空间取代,元空间使用的是直接内存

在这里插入图片描述

元空间,不再与堆连续,而是直接存在于本地内存,也就是机器的内存。理论上机器内存有多大,元空间就有多大。

在之前的版本中,字符串常量池存在于永久代中,在大量使用字符串的情况下,容易出现OOM异常,此外JVM加载的class总数、方法的大小等都很难确定,因此对永久代大小难以确定。

5.方法区

当虚拟机要使用一个类时,它需要读取并解析 Class 文件获取相关信息,再将信息存入到方法区。方法区会存储已被虚拟机加载的 类信息、字段信息、方法信息、常量、静态变量、即时编译器编译后的代码缓存等数据

主要是存放一个类的:

基础信息

常量池

字段

方法

法区会存储已被虚拟机加载的 类信息、字段信息、方法信息、常量、静态变量、即时编译器编译后的代码缓存等数据

主要是存放一个类的:

基础信息

常量池

字段

方法

属性

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值