Java虚拟机相关八股一>jvm分区,类加载(双亲委派模型),GC

目录:

一.jvm的分区:

二. jvm类加载:

三. 双亲委派模型:

四.垃圾回收机制(GC):



一.jvm的分区:

jvm是仿照操作真实的系统设计的,主要仿照操作分区,也跟着分了很多区域

大致分部: sl


1.核心分区划分:

注意:

类信息元:类叫什么名字,权限修饰限定符是什么public还是什么,继承哪些类,实现哪些接口。。

Java8之前元数据区,也叫方法区


1.1.程序计数器:很小的区域的一个内存空间,用来记录当前指令执行到哪个地址


1.2.元数据区:保存当前类被加载好的的数据(. class文件数据加载进来内存中),保存一些类对象


1.3. 栈:保存方法调用关系保存和局部变量(包括引用类型局部变量)


1.4.堆:保存new的对象

eg: Test t = new Test ();

t 是一个局部变量就在栈上

t 是一个成员变量就在堆上

t 是一个静态 成员成员变量就在元数据区


注意:

元数据区和堆在整个Java进程中公用同一份

程序计数区和栈一个进程可能有好多份 (一个线程一份)



二. jvm类加载:

类加载本身是一个很复杂的问题,这里从Java官方文档和面试角度出发


步骤:

1.)加载阶段:找到 .class文件 (根据类的全限定名 (包名+类名)eg:java.lang.String),找到打开文件,读取到内存里


2.)验证阶段:解析校验.class文件内容是否合法,并把内容转换成结构化的数据


.class文件也有其格式:


3.)准备:给类对象申请内存空间 (还没有填充只是申请)


4.)解析:给字符串常量分配空间

字符串常量本来就包含在 .class 文件中,通过.class 文件解析出来的字符串常量放到内存区(元数据区,常量池)


5.)初始化:针对 3.)中的类对象初始化,如果这个类还有父类,会针对这个父类进行类加载



三. 双亲委派模型:

双亲委派模型其实就是整体从模块来说,如何进行类加载,jvm中有专门的模块进行类加载

jvm提供了三个类加载器来加载类:

1.BootstrapClassLoader : 负责记载java标准库目录
2.ExtensionClassLoader:负责加载Java扩展库的目录

3.AplicationClassLoader:负责加载Java第三方库/当前项目


双亲委派模型加载步骤:

进行加载类的时候,先通过权限限定类名找到.class文件,会以AplicationClassLoader作为入口开始,AplicationClassLoader会委托给他的父亲ExtensionClassLoader来加载,然后 ExtensionClassLoader****也会委托给他的父亲 BootstrapClassLoader****来加载,BootstrapClassLoader 没有父亲,所以会从他开始从上往下进行找根据自己的库来查找

找不到会向下抛让他的孩子找,最后也没找到就会抛出异常


总结:就是从下往上委托甩锅,然后从上往下开始找



四.垃圾回收机制(GC):

1.为什么要有垃圾回收:

我们知道C语言中,申请内存空间->malloc 需要我们手动释放内存->free; 但是手动释放有时候会,忘记或者代码来不及释放(前面已经return), 导致内存泄漏; 所以Java中引入了垃圾回机制,来自动释放,jvm会自动帮我们完成。


2.垃圾回收主要回收哪个内存区域?

**GC主要回收jvm中的->**堆内存区域

程序计数区,线程结束就会销毁,栈区方法栈帧结束就会销毁,元数据区的类对象一般不用销毁。


3.垃圾回收的过程:

首先找到垃圾 (不在使用的对象),其次释放垃圾(对应的内存释放掉)

找垃圾的方式有两种 :引用计数,和****可达性分析(JAVA采用的方式)


3.1.引用计数:

主要是python和PHP采用的回收机制,每个对象在new的时候,会搭配一个小的内存空间来计数指向这个对象的引用个数,如果引用个数为0,表示这个对象不在使用,就GC

缺点:

首先内存消耗过多,其次会出现循环引用的问题


循环引用就是:两个对象的引用相互指向,两个对象的引用被释放后,两个对象的引用计数却不为0,但是也没有引用来使用这两个对象了


3.2. 可达性分析(JAVA采用的方式):

以代码中的一些特定对象作为遍历的起点,(栈上局部变量的引用,常量池引用指向的对象,静态成员变量的引用) ,尽可能的遍历判断某个对象是否访问到,每次访问到一个对象都会把这个对象标记成可达,未标记成可达的对象就是不可达

这里遍历到一个节点就标记为可达,如果某一个断开了后面的引用就不可达,有点像树的遍历,深度优先遍历


可达性优缺点:

优点:有点就是不会出现出现循环引用问题;

缺点:但是遍历需要的时间开销还是很大的

4. 释放垃圾:

Java中的垃圾回收是通过:标记-清除,复制算法,标记-整理三种方法结合"分代回收"综合进行GC。


4.1.标记-清除:

把垃圾对象的内存直接进行释放


缺点:会产生内存碎片化问题

内存碎片化问题,就是空闲空间东一点西一点,可能会导致下次申请空间失败


4.2.复制算法:

一次只使用其中的一半,把不是垃圾的对象拷贝到一侧,垃圾对象一侧回收掉


缺点:虽然不会出现内存碎片,但是内存空间利用率很低;如果对象很大很多复制成本很高可能无法进行


4.3.标记-整理:

让所有不是垃圾的对象都向一端移动,然后直接清理掉端边界以外的内存。类似顺序表的搬运


缺点:虽然解决了内存碎片化还保证了空间利用概,但是类似****顺序表的搬运还是有很大成本


4.4.分代回收:

分代算法是通过区域划分,实现不同区域和不同的垃圾回收策略从而实现更好的垃圾回收

根据对象存活不同的年龄,进行不同的回收。也会结合以上三种回收算法来进行回收



新生代可以GC频率高一点,老年代GC频率低一点; 老年代一般会进行标记-整理算法,

新生代复制算法。


一个对象经历的过程: 在新生代中,伊甸区如果没有被GC,会到幸村区,在幸村区也会经过多次GC,还存活着就到老年代,类似我们投递简历,前面大片被刷,经过多次笔试,面试存活下来拿到offer!

相关推荐
有来技术1 分钟前
「youlai-boot」入门篇:从0到1搭建 Java、Spring Boot、Spring Security 企业级权限管理系统
java·spring boot
Watermelo61711 分钟前
使用JSONObject.getString()时报错:Cannot resolve method ‘getString‘ in ‘JSONObject‘,详解JSONObject三种库的用法
java·开发语言·spring boot·后端·java-ee·json·springboot
灰色孤星A14 分钟前
MyBatisPlus详解(三)lambdaQuery、lambdaUpdate、批量新增、代码生成、Db静态工具、逻辑删除
java·mybatis·mybatisplus·代码生成器·逻辑删除·lambdaquery
Tp_jh20 分钟前
Navicat社区版终于来了!!!
java·数据库·ide·sql·mysql·云原生·oracle
苍老流年24 分钟前
2. Flink分区策略
android·java·flink
五味香1 小时前
Java学习,List移动元素
android·java·开发语言·python·学习·kotlin·list
NUZGNAW1 小时前
Java连接TDengine和MySQL双数据源
java·mysql·tdengine
曲奇是块小饼干_2 小时前
leetcode刷题记录(七十三)——543. 二叉树的直径
java·数据结构·算法·leetcode·职场和发展
文盲青年2 小时前
菜系-干锅鱼
java
小容小容2 小时前
图书管理系统
java