• 【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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    转储内存信息

    在这里插入图片描述

    分析:回收前

    在这里插入图片描述

    分析:回收后

    在这里插入图片描述

    四、四种引用

    在这里插入图片描述

    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());
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    在这里插入图片描述

    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("========================");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    在这里插入图片描述

    在这里插入图片描述

    4)虚引用

    • PhantomReference:主要配合 ByteBuffer 使用,引用的其实是 直接内存。
    • 当 ByteBuffer 仅有虚引用时被回收:将虚引用入队, 由 Reference Handler 线程调用虚引用相关方法释放 直接内存
    • 必须配合引用队列使用
    5)终结器引用
    • FinalReference:重写 finallize() 的对象自动创建终结器引用。该对象被回收时,不是直接回收,而是将其终结器引用入队。再由 Finalizer 线程通过终结器引用找到被引用对象并调用它的 finalize 方法,第二次 GC 时才 能回收被引用对象
    • 必须配合引用队列使用
  • 相关阅读:
    NATAPP 访问vue-cli启动的项目
    数据结构与算法系列二之链表、哈希表及栈
    112. 使用自开发的代理服务器解决 SAP UI5 FileUploader 上传文件时遇到的跨域访问错误
    EMQX 入门教程③——默认端口、端口策略和端口修改
    【数据结构练习】栈的面试题集锦
    经典CAN2.0 DBC快速切换为CANFD DBC
    渗透测试流程是什么?7个步骤给你讲清楚!
    前期学习练习测试
    C++11: final & override
    记宝塔使用webhook自动化同步gitee代码
  • 原文地址:https://blog.csdn.net/weixin_43401592/article/details/128017137