当前位置: 首页 > article >正文

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! 


http://www.kler.cn/a/512065.html

相关文章:

  • Docker配置国内镜像源
  • 在 Babylon.js 中使用 Gizmo:交互式 3D 操作工具
  • 【统计的思想】假设检验(一)
  • STM32 学习笔记【补充】(十)硬件I2C读写MPU6050
  • 计算机毕业设计PySpark+Hadoop+Hive机票预测 飞机票航班数据分析可视化大屏 航班预测系统 机票爬虫 飞机票推荐系统 大数据毕业设计
  • LLM - 大模型 ScallingLaws 的 C=6ND 公式推导 教程(1)
  • 2025.1.16——四、get_post 传参方式
  • VIVADO ILA IP进阶使用之任意设置ILA的采样频率
  • 人形机器人将制造iPhone!
  • 在Spring Boot中使用SeeEmitter类实现EventStream流式编程将实时事件推送至客户端
  • 后端架构学习笔记
  • Go语言的正则表达式
  • leetcode 221. 最大正方形
  • 提升大语言模型的三大策略
  • NLP 单双向RNN+LSTM+池化
  • 苍穹外卖 项目记录 day07 商品缓存-购物车模块开发
  • [实战]Ubuntu使用工具和命令无法ssh,但使用另一台Ubuntu机器可以用命令ssh,非root用户。
  • 『 实战项目 』Cloud Backup System - 云备份
  • Kotlin 2.1.0 入门教程(五)
  • 【useImperativeHandle Hook】通过子组件暴露相应的属性和方法,实现在父组件中访问子组件的属性和方法
  • React 中hooks之useDeferredValue用法总结
  • 深度学习 | 基于 LSTM 模型的多电池健康状态对比及预测
  • 【柱状图】——18
  • 【玩转全栈】----Django制作部门管理页面
  • 基于SpringBoot的智能家居系统的设计与实现(源码+SQL脚本+LW+部署讲解等)
  • XAMPP运行没有创建桌面图标