jvm垃圾回收机制

本文介绍了Java的垃圾回收机制,包括引用计数法及其缺点,以及可达性分析算法的工作原理和GC Root对象。讨论了四种不同类型的引用:强引用、软引用、弱引用和虚引用,其中软引用和弱引用在内存管理中的应用场景和优化效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

垃圾回收

以前的垃圾回收机制

1.引用计数法

每个创建出来的对象通过某种方法记录他被引用的数量,当引用的数量变为0时,说明该对象已经没有人去使用,回收该对象

缺点:

当两个对象互相引用时,那么无论这两个对象被不被使用都不会触发垃圾回收机制

image-20220909142939793
2.可达性分析算法

如果一个对象直接或者间接的被根对象(GC Root)引用那么这个对象不用被回收

根对象

一定不会被当成垃圾回收的对象

实现步骤

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

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

哪些对象可以作为 GC Root ?
1.系统类
image-20220909144309960
2.操作系统引用的java对象
image-20220909144416314
3.被加锁的对象

image-20220909144505182

4.正在活动的线程中局部变量引用的对象
image-20220909144538065

4种引用

1.强引用

​ 只有所有 GC Roots 对象都不通过(强引用)引用该对象,该对象才能被垃圾回收

image-20220909145158777
2.软引用(SoftReference)

​ 仅有软引用引用该对象时,在垃圾回收后,内存仍不足时会再次出发垃圾回收,回收软引用对象可以配合引用队列来释放软引用自身**(两次垃圾回收)**

image-20220909145300059
3.弱引用(WeakReference)

​ 仅有弱引用引用该对象时,在垃圾回收时,无论内存是否充足,都会回收弱引用对象可以配合引用队列来释放弱引用自身**(一次垃圾回收)**

image-20220909145240777
4.虚引用(PhantomReference)(直接内存地址)

​ 必须配合引用队列使用,主要配合 ByteBuffffer 使用,被引用对象回收时,会将虚引用入队,由 Reference Handler 线程调用虚引用相关方法释放直接内存

image-20220909150030340
5.终结器引用(FinalReference)(不建议使用)

​ 无需手动编码,但其内部配合引用队列使用,在垃圾回收时,终结器引用入队(被引用对象暂时没有被回收),再由 Finalizer 线程通过终结器引用找到被引用对象并调用它的 fifinalize方法,第二次 GC 时才能回收被引用对象

image-20220909150242347

软引用使用场景

在内存空间比较紧张时,一些占用空间较大而又不是很重要的资源就可以使用软引用声明,在内存不足时可以将这些软引用声明的资源回收

例如

我们堆内存中只有20MB的大小,现在要连续声明5个大小为4Mb的不重要的对象,如果我们想要程序执行结束的优先级高于不重要的对象被回收,那么这个代码一定会造成堆溢出(因为是强引用)

image-20220909164953125

堆内存不足:

image-20220909165403639

优化:

使用软引用来存储对象,这样在内存紧张时可以通过Full GC (Allocation Failure)将软引用回收

image-20220909165833913

当内存不足时系统会逐步进行垃圾回收,第一次GC回收无用的新生代对象,第二次GC回收无用的老年代对象,第三次回收与第一次回收类似,第四次回收软引用的新年代和老年代对象,此时内存足够进行下一次操作,垃圾回收结束

image-20220909170356485

结果:

可以看出垃圾回收时将先前声明为软引用的四个对象全部回收了

image-20220909214140711

弱引用使用场景

和软引用使用场景类似,也是当内存不足时将一些占用空间较大而又不是很重要的资源就可以使用弱引用声明,区别在于在GC阶段就会回收弱引用对象

image-20220909215817442

弱引用声明
public static void main(String[] args) {
        //  list --> WeakReference --> byte[]
        List<WeakReference<byte[]>> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            WeakReference<byte[]> ref = new WeakReference<>(new byte[_4MB]);
            list.add(ref);
            for (WeakReference<byte[]> w : list) {
                System.out.print(w.get()+" ");
            }
            System.out.println();

        }
        System.out.println("循环结束:" + list.size());
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值