2020-08-05

Jvm虚拟机模型。## 标题
在这里插入图片描述
总的来说,虚拟机分为三层。
类加载子系统。
运行时数据区
执行引擎。
我们通过字节码文件加载的过程来了解虚拟机的结构。

运行时,数据区包括这几个结构。
在这里插入图片描述

Pc寄存 器 线程序私有
Java虚拟机栈 线程私有
堆 线程公有
方法区 线程公有
本地方法栈。 线程私有

Pc寄存器,在这里插入图片描述
又称程序的钩子。当执行引擎开始执行字节码的时候,会来到PC寄存器,取出每个虚拟机栈中的字节码执行行数。因为县城是不断来回切换的,需要有个容器来记录。中断的代码位置,下次切回县城的时候不会丢失线程

堆,在这里插入图片描述

里面包含这几个结构。
年轻代 老年代 方法区(逻辑包涵)
年轻代方法区有
伊甸园区,新出生的对象在这里。当对象满的时候会触发minor gc,也就是垃圾回收。
幸存者一区,经历过Minor gc。都来这里,
幸存者二区。幸存者一区满的时候再移到幸存者二区。里面的对象每经历过一次搬动会年龄加一。年龄满15岁的进入老年代。年龄满15岁的对象,是可以设置。也可以手动设置为年龄为5进去老年代。

老年代是存储一些不怎么回收的对象。如果老年代满了,他就会出发major gc。但是很多虚拟机和开发者会将major gc与Full gc混淆,Major gc。只回收老年代,而forge the是对整个Java堆和方法区的回收的回收。

堆的另一个部分就是字符串常量池。
堆中的字符串属性会指向这里。

当你的对象进入堆后。
他被实例化会生成这几个部分。
对象头和实例数据。

对象头包括
哈希值 栈帧中的对象引用依靠这个值找到,
gc分代年龄 用来记录该对象多少年龄。用于垃圾回收。
锁状态标志
线程持有的锁
偏向线程ID
偏向时间戳。

方法区的结构在这里插入图片描述

包括类信息,运行时常量池。
类信息就是堆中的类元信息具体指向。比如一个person类实例化在堆中,那他的person类的类型就在法区中被指向。
Person person =new person()
第一个person就是方法区中类元信息
第二个person变量就是栈帧中的变量
New这个关键字就是创建对象。虚拟机系统开始调用init方法

那么该对象中被创建好了。就需要有引用指向。
刚才提到的对象头就是包含对象的信息。对象头里的哈希值就是就是栈帧找到对象的地址值。
该对象的所有属性信息都存储在实例信息中。
如果他有字符串类型的属性,会指向堆中的字符串常量池。
如果他有对象类属性,会指向方法区中的类元信息。

Java虚拟机栈的结构。在这里插入图片描述

Java虚拟机栈是由一个一个栈帧组成的。
每个栈帧都包含着五个组成部分。
局部变量表。 当前运行方法的变量。

操作数栈 当前方法运算的容器

动态链接 方法中的变量具体指向。

方法返回地址 当一个方法运行反后,需要根据他返回下一个方法。

一些附加信息

本地方法栈。
本地方法栈是运行一些本地的程序,他设计的初衷是用来融合其他语言。是现在具体用不上了。
可以把它理解为大使馆。在Java最开始发展的时候,为了抱住c语言的大腿,特此开发了本地方法栈。由于更好的融合c语言使得Java可以迅速开发,如今Java壮大已经不怎么用到本地方法栈了。

运行时数据区
执行引擎在这里插入图片描述

当字节码开始加载的时候,它会被类加载器进行加载。加载器官方定义有两种。一种是bootstrap引导类加载器。它是由c语言写的。用来加载Java的核心类库。剩下的execution class loader,Application class loader全部都是继承class loader类,属于自定义类加载器。
包括我们自己写的加载器都属于自定义类型的加载器。
文件开始加载的时候,它会进行双亲委托机制。就是他不会立马加载会首先委托父类加载,父类在委托父类的父类进行加载。如果该类是核心力库,则由最高父类加载。如果不是,则用反委托向下加载。

举例说明,一个小朋友想吃苹果,他拿着苹果对他爸说,爸你吃。他爸拿过来苹果对他的爷爷说:爸你吃。这个时候会有两种结果。小孩儿的爷爷吃或者是不吃。

如果小孩儿的爷爷吃了,那么孩子和孩儿他爸就看着。
如果小孩儿的爷爷说不吃。他会把苹果给他爸,说苹果太硬也吃不了。
他爹在把苹果给他孩子。说苹果太酸,我吃不了。
还是接过苹果说,又硬又酸,我最爱吃。然后就吃了。这就是双亲委派机制的工作模式。在这里插入图片描述

经过加载完后,该例不会立马进入堆。他会进行第二部动态链接。
链接分为三个部分,验证,准备和解析

验证是看看是不是二进制Java文件,为了确保不损坏虚拟机。Class文件开头是CA FE BA BE

准备就是为累分配变量并设置初始值。但是不包含final和static修饰的,因为final编译的时候就会显示初始化。

在这里插入图片描述

然后就是初始化阶段。
Java虚拟机。调用clint构造器指令。用来初始化类对象。
初始化的类对象开始分配到堆中。进入了运行时数据区。

被初始化的对象进入堆中,
java虚拟机栈中的栈帧,栈帧中有局部变量表,局部变量表中的变量引用根据对象地址值找到堆中的对象。
堆中的对象由两部分组合
对象头
实例数据区

对象的具体实行在实例数据区中,其中的字符串属性指向队中的字符串常量池,类属性指向方法区中的类元信息。

因为堆是线程共有的,所以它有一个机制就是TLAB机制,就是在堆中分配一下快内存,平均分成若干分,每个线程一份,这样就不会存在多个线程争抢一条数据了。

最后感谢尚硅谷的宋红康老师讲解的java虚拟机课程。此文章来此学习总结,图片出自宋红康老师。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值