JVM内存模型

虚拟机栈:
程序计数器(Program Counter):
本地方法栈:主要用于执行本地方法
堆(Heap):JVM管理的最大的一块内存空间
方法区:存储元数据。在HotSpot虚拟机中也叫永久代,从jdk1.8开始,已经彻底废弃了永久代,使用元空间代替
运行时常量池:方法区的一部分内容
直接内存

虚拟机栈:
主要由栈帧(每个方法会生成一个栈帧)构成,栈帧由局部变量表,操作数栈,动态链接,方法出口等。

public class Math{
    public int compute(){
        int a = 1;
        int b = 2;
        int c = a + b;
        return c;
    }
    
    public static void main(String [] args){
         Math math = new Math();
        math.compute();
        Math math2 = new Math();
        math2.compute();
    }
}

上述代码在编译成字节码之后实际上是执行相应的指令,首先会获取常量1将其压入操作数栈中,然后在局部变量表中开辟一段空间给a,接着从操作数栈将1出栈,并将其赋值个局部变量表中的a。然后b的操作与a相同,接着将1从局部变量表中拿出压入操作数栈,将2从局部变量表中拿出压入操作数栈,然后将操作数栈的两个数弹出,执行加法指令并将结果压入操作数栈,在局部变量表中开辟c的内存空间,将操作数栈的结果弹出赋值给c,也就是放入局部变量表中
在这里插入图片描述

程序计数器是和虚拟机栈都是线程独有的,程序计数器是保存当前线程执行指令的地址,当执行一条指令之后,程序计数器会自动更新,指向下一条指令的内存地址

方法出口:在执行完相应的方法之后,要回到调用该方法的位置处,所以需要保存调用出的内存地址

java对象:
在这里插入图片描述
在这里插入图片描述

jvm在装载Math.class时,会将class中的常量、静态变量,类的元数据(方法、接口、类名等)解析出来存放在方法区,例如方法解析之后会如下形式,存放了执行的指令,当new Math对象存放在堆中的时候,Math对象的对象头信息中保存了执行类元数据的地址,在执行相应的方法的时候实际上是一个链接符号,根据链接符号来到元数据中找到相应的方法,这个过程实际上是动态链接

public int compute();
  Code:
     0: iconst_1
     1: istore_1
     2: iconst_2
     3: istore_2
     4: iload_1
     5: iload_2
     6: iadd
     7: istore_3
     8: iload_3
     9: ireturn

public static void main(java.lang.String[]);
  Code:
     0: new           #1                  // class bytecode/Math
     3: dup
     4: invokespecial #22                 // Method "<init>":()V
     7: astore_1
     8: aload_1
     9: invokevirtual #23                 // Method compute:()I
    12: pop
    13: new           #1                  // class bytecode/Math
    16: dup
    17: invokespecial #22                 // Method "<init>":()V
    20: astore_2
    21: aload_2
    22: invokevirtual #23                 // Method compute:()I
    25: pop
    26: return

在这里插入图片描述

虚拟机栈中的局部变量会引用堆中对象的引用,也就是内存地址,而堆中的对象会在对象头中引用该类的元数据,也就是会保存了一个在方法区的类元数据地址。

可达性分析算法:
这个算法的基本思想及时通过一系列的称为GC Roots的对象作为起点,从这些节点开始向下搜索,节点所走过的路径成为引用链,当一个对象到GC Roots没有任何引用链相连的话,则证明此对象是不可用的。
GC Roots根节点:类加载器、Thread、虚拟机栈的局部变量表、static成员、常量引用、本地方法栈的局部变量等

堆:
在这里插入图片描述
堆内存分为新生代和老年代,新生代又细分为Edenq区和Survivor区(Survivor区又分为From区和To),默认情况下Eden区占新生代的8/10,From和To区各占1/10。一般情况下,新创建的对象是存放在堆内存中的Eden区,当Eden区满了的时候会触发jvm进行minor gc,清理Eden区的不可达对象,如果发现还存活的对象,则会将其移到From区,终究From区也会满,当From区满的时候也会触发minor gc,如果对象还存活,则会将存活对象移到To区,这时对象头中的分代年龄属性就会自动+1,记录其存活的状态,如果To区也满了,那么也会触发minor gc,还存活的对象则会被移到From区,同时分代年龄+1,分代年龄超过15的时候,存活对象就会移到老年代中,如果老年代内存已满,那么就会触发full gc

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值