【JVM】垃圾回收:判断可回收对象

一、分析算法

  • 引用计数法

    • 存在问题

      在这里插入图片描述

  • 可达性分析算法

二、可达性分析算法

  • Java 虚拟机中的垃圾回收器采用可达性分析来探索所有存活的对象
  • 回收过程:扫描堆中的对象,看是否能够沿着 GC Root对象 为起点的引用链找到该对象,找不到的表示可以 回收

三、GC Root 实验

  • 哪些对象可以作为 GC Root ?肯定不能当成垃圾被回收的对象
/**
 * 1.运行程序
 * 2.jps 查看运行中的进程id
 * 3.jmap -dump:format=b,live,file=1.bin 27300 转储内存信息
 */
public static void main(String[] args) throws IOException {
    List<Object> list=new ArrayList<>();
    list.add("1");
    list.add("2");
    System.out.println("回收前");
    System.in.read();
    
    list=null;
    System.out.println("回收后");
    System.in.read();
    System.out.println("end...");
}

转储内存信息

在这里插入图片描述

分析:回收前

在这里插入图片描述

分析:回收后

在这里插入图片描述

四、四种引用

在这里插入图片描述

1)强引用

  • 只有所有 GC Roots 对象都不通过【强引用】引用该对象,该对象才能被垃圾回收

2)软引用

  • 仅有软引用引用该对象时,在垃圾回收后,内存仍不足时会再次出发垃圾回收,回收软引用 对象。
  • 可以配合引用队列来释放软引用自身
/**
 * 软引用(SoftReference)
 * -Xmx20m -XX:+PrintGCDetails -verbose:gc
 */
public class SoftReferenceTest {
    private static final int _4M=1024*1024*4;
    public static void main(String[] args) {
        //GC_Root
        List<SoftReference<byte[]>> list=new ArrayList<>();
        //关联引用队列:当对象被回收时加入队列
        ReferenceQueue<byte[]> queue=new ReferenceQueue<>();
        //1.添加5个软引用
        for (int i = 0; i < 5; i++) {
            SoftReference<byte[]> ref=new SoftReference<>(new byte[_4M],queue);
            System.out.print(ref.get());
            list.add(ref);
            System.out.println(" "+list.size());
        }
        //2.判断5个软引用是否被回收了对象,是的话移除软引用
        Reference<? extends byte[]> poll = queue.poll();
        while(poll!=null){
            list.remove(poll);
            poll=queue.poll();
        }
        //3.输出当前list中的所有引用
        System.out.println("========================");
        for (SoftReference<byte[]> item: list) {
            System.out.println(item.get());
        }
    }
}

在这里插入图片描述

3)弱引用

  • 仅有弱引用引用该对象时,在垃圾回收时,无论内存是否充足,都会回收弱引用对象
  • 可以配合引用队列来释放弱引用自身
/**
 * 弱引用
 * -Xmx20m -XX:+PrintGCDetails -verbose:gc
 */
public class WeakReferenceTest {
    private static final int _4M=1024*1024*4;
    public static void main(String[] args) {
        //GC_Root
        List<WeakReference<byte[]>> list=new ArrayList<>();
        //1.添加5个弱引用
        for (int i = 0; i < 6; i++) {
            WeakReference<byte[]> ref=new WeakReference<>(new byte[_4M]);
            list.add(ref);
            System.out.print("第"+(i+1)+"次:");
            for (WeakReference<byte[]> item: list) {
                System.out.print(item.get()+" ");
            }
            System.out.println();
        }
        
        System.out.println("========================");
    }
}

在这里插入图片描述

在这里插入图片描述

4)虚引用

  • PhantomReference:主要配合 ByteBuffer 使用,引用的其实是 直接内存。
  • 当 ByteBuffer 仅有虚引用时被回收:将虚引用入队, 由 Reference Handler 线程调用虚引用相关方法释放 直接内存
  • 必须配合引用队列使用
5)终结器引用
  • FinalReference:重写 finallize() 的对象自动创建终结器引用。该对象被回收时,不是直接回收,而是将其终结器引用入队。再由 Finalizer 线程通过终结器引用找到被引用对象并调用它的 finalize 方法,第二次 GC 时才 能回收被引用对象
  • 必须配合引用队列使用
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

愿你满腹经纶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值