jvm 笔记

jvm

主要做什么:
从软件层面屏蔽不同操作系统在底层硬件和指令上的区别
类加载:加载出运行时数据区(内存模型)

  • 栈(线程栈):
    · 每个线程独享的,每个线程开启时,会开辟一个内存,调用时,遇到局部变量,会在开辟的线程栈上开辟一块区域,栈帧来存放局部变量,局部变量在调用到另外一个方法时,又会为这个方法再开辟一块栈帧来存放这个方法的局部变量,不同的方法有独立的栈帧区域
    · 栈:先进后出,后进先出,一个方法执行完成后对应的栈帧区域立即释放
    · 栈帧组成:
        · 局部变量表
            第三步:局部变量表中有一个 a=1
        · 操作数栈
            int a = 1;
            jvm编译后的字节码指令:
            第一步:iconst_1; 在方法对应的栈帧区域的操作数栈上放入1;
            第二步:istore_1;在局部变量表中给a创建一块内存区域,把1赋值给a
            操作数栈就是变量的临时计算区,计算完成之后就会把变量放入对应的局部变量表
        · 动态链接
            User user = new User();
            user.queryUser();
            动态链接放的就是user对象里调用queryUser在jvm指令码的内存地址,jvm加载的时候会把queryUser加载到方法区,当调用方法时,会根据动态链接找到指令码的内存地址,然后执行方法
        · 方法出口
  • 线程计数器
    方当前线程即将执行的指令码内存地址
    作用:当线程sleep时,会记录当前线程的位置,当被唤醒时,从之前的位置继续执行
  • new 出的对象都放在堆内存中
    User user = new User() 栈内存中也会有局部变量user,然后它的指针指向堆内存中的User()
    对象有头指针,会指向方法区中的类元信息
    年轻代:占堆内存的1/3
        **** Eden:占年轻代的 8/10 ,new出来的对象一般都放到该区域;
                如果该区域满了,会触发minor gc,对该区域无效的对象进行清理,把还有引用的对象存入Survivor区的From区,把该对象头里的分代年龄+1(经历过一次minor gc就会执行一次);
        ~ Survivor    占年轻代的 2/10
            From区:
                    如果Survivor的From区满了后,也会触发minor gc,无效的清理,有指针引用的放入To区
            To区:
                    如果To区满了后,也会触发minor gc ,无效的清理,有指针的在放入From区,复制算法
    **** 老年代 占堆内存的2/3
            当分代年龄到达15后,也就是经过minor gc 还存活的对象,会放入老年代区域;
            如果老年代区域满了后,会触发full gc ,如果gc后还是满的,那么代码会抛出 OutOfMemoryError内存溢出异常
  • 方法区(元空间)
    ·常量
    ·静态变量
    ·类元信息
  • 本地方法栈
    本地方法,用native修饰
    每个内存独有的内存区域