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修饰 每个内存独有的内存区域