【JVM】JVM03(图解垃圾回收机制)上

  • java虚拟机中的垃圾回收器采用可达性分析来探索所有存活的对象

  • 扫描堆中的对象,看是否能够沿着GC Root对象为起点的引用链找到该对象,找不到,表示可以回收

可以作为GC Root的对象

  • 虚拟机栈(栈帧中的本地变量表)中引用的对象

  • 方法区中类静态变量引用的对象

  • 方法区中常量引用的对象

  • 本地方法栈中JNI(即一般说的Native方法)引用的对象

⭐️2.五种引用

======================================================================

  1. 强引用

  2. 软引用

  3. 弱引用

  4. 虚引用

  5. 终结器引用

下面我们分别进行描述

⭐️2.1强引用

======================================================================

在这里插入图片描述

我们平时所使用的引用便是强引用,比如我们new一个对象A,把这个对象通过等号(赋值运算符)赋值给一个变量m,那么就称这个变量m强引用了刚刚的对象A

强引用的特点:

只要沿着GC root的引用链能够找到该对象,他就不会被垃圾回收,就比如上图中的C对象能找到A1对象,那么A1对象就不能被回收,当B对象和C对象对A1对象的引用都断开时,A1对象才能被垃圾回收

⭐️2.2 软引用

=======================================================================

在这里插入图片描述

如图,A2对象使用过软引用对象被C对象间接引用到,只要满足垃圾回收时,并且回收完内存也不够时,那么软引用所引用的A2对象就会被释放掉

所以软引用引用对象被释放的条件是

  • 没有强引用对象引用它

  • 发生垃圾回收

  • 垃圾回收之后内存不够

软引用的应用案例

public static void soft(){

ArrayList<SoftReference<byte[]>> list = new ArrayList<>();

for (int i = 0; i < 5; i++) {

SoftReference<byte[]> ref = new SoftReference<>(new byte[_4MB]);

System.out.println(ref.get());

list.add(ref);

System.out.println(list.size());

}

System.out.println(“循环结束:”+list.size());

for (SoftReference<byte[]> ref : list) {

System.out.println(ref.get());

}

}

list先引用软引用对象,软引用对象间接的引用byte数组

list和SoftReference之间是强引用,SoftReference和byte数组之间是软引用

内存充足的时候软引用引用的对象保留,但是当内存不足的时候,软引用引用的对象就会被清除

⭐️2.3 弱引用

=======================================================================

在这里插入图片描述

和软引用的区别是,当弱引用引用该对象时,发生垃圾回收不管内存是否充足,弱引用所引用的对象都会被回收

public class Demo03 {

private static final int _4MB = 410241024;

public static void main(String[] args) throws IOException {

List<WeakReference<byte[]>> list = new ArrayList<>();

for (int i = 0; i < 10; i++) {

//关联了软引用对象和引用队列,当软引用所关联的byte[]被回收时,软引用自己会加入到引用队列queue中去

WeakReference<byte[]> ref = new WeakReference<>(new byte[_4MB]);

list.add(ref);

for (WeakReference<byte[]> w: list){

System.out.println(w.get()+“”);

}

System.out.println();

}

System.out.println(“循环结束:”+list.size());

}

}

通过list集合引用WeakReference,通过WeakReference间接的引用byte[]数组,这样进行垃圾回收,就会尝试把WeakReference运用的byte数组所占用的内存做释放

⭐️引用队列

====================================================================

在这里插入图片描述

当软引用所引用的对象或弱引用引用的对象被清除之后,软引用和弱引用本身并不会消失,软引用和弱引用本身也是一个对象,此时软引用和弱引用会进入引用队列

软引用和弱引用自身也要占用一定内存,如果想释放软引用和弱引用的内存,需要使用引用队列找到它们,对其做进一步的处理

引用队列操作代码

public class Demo02 {

private static final int _4MB = 410241024;

public static void main(String[] args) throws IOException {

ArrayList<SoftReference<byte[]>> list = new ArrayList<>();

//引用队列

ReferenceQueue<byte[]> queue = new ReferenceQueue<>();

for (int i = 0; i < 5; i++) {

//关联了软引用对象和引用队列,当软引用所关联的byte[]被回收时,软引用自己会加入到引用队列queue中去

SoftReference<byte[]> ref = new SoftReference<>(new byte[_4MB],queue);

System.out.println(ref.get());

list.add(ref);

System.out.println(list.size());

}

Reference<? extends byte[]> poll = queue.poll();

while (poll != null){

list.remove(poll);

poll = queue.poll();

}

for (SoftReference<byte[]> ref : list) {

System.out.println(ref.get());

}

}

}

关联软引用对象和引用队列,当软引用所关联的byte[]被回收时,软引用自己会加入到引用队列queue中去,之后查看引用队列中是否有软引用,有就将其移出

⭐️2.4虚引用

======================================================================

在这里插入图片描述

ByteBuffer被回收的时候,他分配的直接内存并不能被java的垃圾回收管理,所以我们将虚引用对象Cleaner进入引用队列,虚引用所在队列会有一个叫RefrenceHandlel的线程,来定时到这个引用队列中找新入队的Cleaner,如果有就调用Cleaner中的clean方法,根据记录的直接内存的地址调用Unsafe.freeMemary方法来清理直接内存

在这里插入图片描述

⭐️2.5终结器引用

========================================================================

在这里插入图片描述

所有的java对象都继承自Object类,Object类有finallize()终结方法,当对象重写了终结方法并且没有强引用,他就可以被当成垃圾回收,终结方法的调用依靠终结器引用

在这里插入图片描述

如上图当A4对象被垃圾回收时,在A4对象被真正清除之前,终结期引用进入引用队列,再由一个优先级很低的线程(finallizeHandler)查看引用队列中的终结器引用,通过终结器引用找到将要垃圾回收的对象,调用对象的finallize方法,调用之后,该对象就可以被垃圾回收了

⭐️2.6引用总结

=======================================================================

在这里插入图片描述

⭐️3.垃圾回收算法

========================================================================

⭐️3.1标记清除

=======================================================================

在这里插入图片描述

第一个阶段:标记

顺着GC Root查找没有引用的对象,将其进行标记

在这里插入图片描述

第二个阶段:清除

将垃圾对象所占用的空间释放

在这里插入图片描述

释放不意味着将每一个字节进行清理操作,清除只是把对象所占用内存的起始与结束地址记录下来,放在一个较空闲的地址链表里,下次分配内存的时候会直接覆盖这部分内存

标记清除算法的优点:

  • 速度快

标记清除算法的缺点:

  • 容易产生内存碎片,无法满足大对象的内存分配,造成内存溢出问题

⭐️3.2标记整理

=======================================================================

第一步:标记,和标记删除算法相同

在这里插入图片描述

顺着GC Root查找没有引用的对象,将其进行标记

第二步:整理

在这里插入图片描述

清除垃圾的过程中,它会把可用的对象向前移动,使内存更为紧凑,连续的空间更多

优点:

  • 没有内存碎片,空间连续

缺点

总结

以上是字节二面的一些问题,面完之后其实挺后悔的,没有提前把各个知识点都复习到位。现在重新好好复习手上的面试大全资料(含JAVA、MySQL、算法、Redis、JVM、架构、中间件、RabbitMQ、设计模式、Spring等),现在起闭关修炼半个月,争取早日上岸!!!

下面给大家分享下我的面试大全资料

  • 第一份是我的后端JAVA面试大全

image.png

后端JAVA面试大全

  • 第二份是MySQL+Redis学习笔记+算法+JVM+JAVA核心知识整理

字节二面拜倒在“数据库”脚下,闭关修炼半个月,我还有机会吗?

MySQL+Redis学习笔记算法+JVM+JAVA核心知识整理

  • 第三份是Spring全家桶资料

字节二面拜倒在“数据库”脚下,闭关修炼半个月,我还有机会吗?

MySQL+Redis学习笔记算法+JVM+JAVA核心知识整理
各个知识点都复习到位。现在重新好好复习手上的面试大全资料(含JAVA、MySQL、算法、Redis、JVM、架构、中间件、RabbitMQ、设计模式、Spring等),现在起闭关修炼半个月,争取早日上岸!!!

下面给大家分享下我的面试大全资料

  • 第一份是我的后端JAVA面试大全

[外链图片转存中…(img-q8l0LrSh-1720082040745)]

后端JAVA面试大全

  • 第二份是MySQL+Redis学习笔记+算法+JVM+JAVA核心知识整理

[外链图片转存中…(img-9Uy51XZF-1720082040746)]

MySQL+Redis学习笔记算法+JVM+JAVA核心知识整理

  • 第三份是Spring全家桶资料

[外链图片转存中…(img-7nwBWpiA-1720082040747)]

MySQL+Redis学习笔记算法+JVM+JAVA核心知识整理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值