认识JVM的内存模型

从上一节了解到整个JVM大的内存区域,分为线程共享的heap(堆),MethodArea(方法区),和线程独享的 The pc Register(程序计数器)、Java Virtual Machine Stacks(Java虚拟机栈)、Native Method Stacks(本地方法栈),如下图

同时也大概了解到各个内存区域主要存储的数据类型,根据之前的了解,明白了作为开发者要关注的是堆、方法区和Java虚拟机栈,先从Java虚拟机栈开始

Java虚拟机栈

Java虚拟机栈是线程独享 的一个栈结构,遵循先进后出的原则,栈中存放着一个一个栈帧,每个栈帧代表着一个方法的调用,或者说,每调用一个方法,就向该线程的虚拟机栈中压入一个栈帧,当方法执行完成就弹出 ,栈帧中存放着对应的方法执行的数据

栈帧

如上图所示,每个栈帧中存放着以下数据

  1. 局部变量表 Array数组,存放着方法内的变量
  2. 操作数栈 栈结构,存放着操作数栈和中间计算结果,比如方法中代码int a=3,数值3就是操作数
  3. 动态链接 一种用于实现运行时动态绑定的机制,主要是指在运行时确定引用方法的实际方法体,用于实现多态和动态绑定
  4. 返回地址 当前方法执行结束后调用者的执行位置

通过代码和反编译代码理解Java虚拟机栈和栈帧

了解栈之后,需要明确一个事情,栈帧中局部变量表里的局部变量如果是引用类型,它实际存储的是内存地址,指向对应的堆中的对象

如下一段代码:

java 复制代码
public class Person {
    public static int a = 100;
    public int b = 90;
    public static Object obj1 = new Object();
    
    public static int add(int i, int j) {
        Object obj2 = new Object();
        int k = 80;
        int result = i + j;
        return result;
    }

    public static void main(String[] args) {
        add(100,200);
        System.out.println("method add done");
    }
}
// 反编译后的指令码 只展示add方法
public static int add(int, int);
    Code:
       0: bipush        80 	//把数值80压入操作数栈的栈顶,供后续的运算或方法调用使用
       2: istore_2		   	//将操作数栈顶的整数值存储到局部变量表索引为2的位置
       3: iload_0			//从局部变量0中装载一个int类型值到操作数栈中
       4: iload_1			//加载位于局部变量表第2个位置的int类型变量
       5: iadd				//将两个栈顶的整数相加,然后将相加的结果压入栈顶
       6: istore_3			//将栈顶的整数存储到局部变量3中
       7: iload_3			//将第3个局部变量槽中的整型值加载到操作数栈的栈顶
       8: ireturn			//当前方法将执行完毕,并将栈顶的整数作为方法的返回值返回给调用者

根据上面代码,画出他在虚拟机栈中的存储

由上图也可以看出方法区和堆有互相引用

方法区中会存储静态变量,常量等信息,上面代码中public static Object obj1 = new Object();obj1存放在方法区中,对应的对象在堆中,就是方法区指向堆

对象头中记录的信息包含着指向对象对应的类元数据的内存地址,即堆指向了方法区

对象的内存布局

一个Java对象在内存中包括三个部分:对象头、示例数据和对齐填充

内存模型

根据以上信息引入Java虚拟机内存模型

主要是堆和非堆

堆分为Yong区和Old区

Yong区

Yong区又分为Eden,S0和S1,或者将S0和S1成为from和to,主要是为了垃圾回收

Old区
对象在内存中存储的变化
  1. 首先创建对象会分配在Eden区
  2. Eden区满,发生YongGC,扔存活的对象会放进S0,S0空间不足则直接放进Old区
  3. Eden区再次满,再次YongGC,多次YongGC使得对象年龄超过15的放进Old区或当S区中某一年龄以上的对象占用到S区一半时,将该年龄和以上的所有对象放进Old区
  4. Old区满是发生MajorGC,发生MajorGC时一般都伴随着YongGC,所以一般发生的是FullGC
  5. 当FullGC后仍无法存放时就会抛出OOM

非堆

相关推荐
橘子编程3 分钟前
仓颉语言变量与表达式解析
java·linux·服务器·开发语言·数据库·python·mysql
pcm12356710 分钟前
java中用哈希表写题碰到的误区
java·前端·散列表
雨中飘荡的记忆14 分钟前
财务核算系统设计与实现
java
期待のcode17 分钟前
Springboot数据层开发
java·spring boot·后端
上78将19 分钟前
JVM回收垃圾机制
java·开发语言·jvm
Evan芙19 分钟前
shell编程求10个随机数的最大值与最小值
java·linux·前端·javascript·网络
BD_Marathon22 分钟前
【IDEA】IDEA的详细设置
java·ide·intellij-idea
未来coding22 分钟前
Spring AI ChatModel API 详解【基于官方文档】
java·后端·spring
忘记92626 分钟前
重复注解的机制是什么
java
喜欢流萤吖~26 分钟前
Servlet 生命周期详解
java·servlet