• java强引用,软引用,弱引用,虚引用,终结器引用


    强引用

    • 强引用对象是不可以被垃圾回收的,很容易由于代码 不规范产生内存溢出
    • 比如创建了很多对象,压入栈中,后来只是弹出了对象,而没有手动销毁,这样就会内存泄漏,就是引用仍然存在,但是代码逻辑上访问不到了
    • 终结强引用,就是把当前变量指向null,断开栈和堆空间的联系
    public class StrongReferenceTest {
        public static void main(String[] args) {
            StringBuffer str = new StringBuffer ("Hello");
            StringBuffer str1 = str;
    
            str = null;
            System.gc();
    
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            System.out.println(str1);//str1虽然通过null指向空了,但是str1和他还有联系,所以不会被回收
        }
    }
    
    public class StrongReferenceTest {
        public static void main(String[] args) {
            StringBuffer str = new StringBuffer ("Hello,尚硅谷");
            System.gc();
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(str);//仍然没有被回收。因为在方法栈中被引用了
        }
    }
    
    • 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

    软引用

    软引用的对象会在第一次垃圾回收的时候记录,等第一次垃圾回收后发现内存不够才会对软引用做回收

    package src.Tjvm.Yinyong;
    
    import java.lang.ref.SoftReference;
    
    /**
     * 软引用的测试:内存不足即回收
     *
     * @author shkstart  shkstart@126.com
     * @create 2020  16:06
     */
    public class SoftReferenceTest {
        public static class User {
            public User(int id, String name) {
                this.id = id;
                this.name = name;
            }
    
            public int id;
            public String name;
    
            @Override
            public String toString() {
                return "[id=" + id + ", name=" + name + "] ";
            }
        }
    
        public static void main(String[] args) {
            //创建对象,建立软引用
    //        SoftReference userSoftRef = new SoftReference(new User(1, "songhk"));
            //上面的一行代码,等价于如下的三行代码
            User u1 = new User(1,"songhk");
            SoftReference<User> userSoftRef = new SoftReference<User>(u1);
            u1 = null;//取消强引用
    
    
            //从软引用中重新获得强引用对象
            System.out.println(userSoftRef.get());
    
            System.gc();
            System.out.println("After GC:");
    //        //垃圾回收之后获得软引用中的对象
            System.out.println(userSoftRef.get());//由于堆空间内存足够,所有不会回收软引用的可达对象。
    //
            try {
                //让系统认为内存资源紧张、不够
                byte[] b = new byte[1024 * 1024 * 7];
                //byte[] b = new byte[1024 * 7168 - 635 * 1024];
            } catch (Throwable e) {
                e.printStackTrace();
            } finally {
                //再次从软引用中获取数据
                System.out.println(userSoftRef.get());//在报OOM之前,垃圾回收器会回收软引用的可达对象。
            }
        }
    }
    
    • 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
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    -Xmx7m JVM参数

    弱引用

    第一次垃圾回收就会进行回收

     */
    public class WeakReferenceTest {
        public static class User {
            public User(int id, String name) {
                this.id = id;
                this.name = name;
            }
    
            public int id;
            public String name;
    
            @Override
            public String toString() {
                return "[id=" + id + ", name=" + name + "] ";
            }
        }
    
        public static void main(String[] args) {
            //构造了弱引用
            WeakReference<User> userWeakRef = new WeakReference<User>(new User(1, "songhk"));
            //从弱引用中重新获取对象
            System.out.println(userWeakRef.get());
    
            System.gc();
            // 不管当前内存空间足够与否,都会回收它的内存
            System.out.println("After GC:");
            //重新尝试从弱引用中获取对象
            System.out.println(userWeakRef.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

    weakhashmap 就是一个弱引用的HaspMap,里面存放的对象都是弱引用对象,当内存不足的时候可以释放

    虚引用

    虚引用在垃圾回收的时候也会被回收,唯一的不同就是回收的对象会被放到一个自定义的队列里先,从而获得对这个对象被回收的通知

    public class PhantomReferenceTest {
        public static PhantomReferenceTest obj;//当前类对象的声明
        static ReferenceQueue<PhantomReferenceTest> phantomQueue = null;//引用队列
    
        public static class CheckRefQueue extends Thread {
            @Override
            public void run() {
                while (true) {
                    if (phantomQueue != null) {
                        PhantomReference<PhantomReferenceTest> objt = null;
                        try {
                            objt = (PhantomReference<PhantomReferenceTest>) phantomQueue.remove();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        if (objt != null) {
                            System.out.println("追踪垃圾回收过程:PhantomReferenceTest实例被GC了");
                        }
                    }
                }
            }
        }
    
        @Override
        protected void finalize() throws Throwable { //finalize()方法只能被调用一次!
            super.finalize();
            System.out.println("调用当前类的finalize()方法");
            obj = this;
        }
    
        public static void main(String[] args) {
            Thread t = new CheckRefQueue();
            t.setDaemon(true);//设置为守护线程:当程序中没有非守护线程时,守护线程也就执行结束。
            t.start();
    
            phantomQueue = new ReferenceQueue<PhantomReferenceTest>();
            obj = new PhantomReferenceTest();
            //构造了 PhantomReferenceTest 对象的虚引用,并指定了引用队列
            PhantomReference<PhantomReferenceTest> phantomRef = new PhantomReference<PhantomReferenceTest>(obj, phantomQueue);
    
            try {
                //不可获取虚引用中的对象
                System.out.println(phantomRef.get());
    
                //将强引用去除
                obj = null;
                //第一次进行GC,由于对象可复活,GC无法回收该对象
                System.gc();
                Thread.sleep(1000);
                if (obj == null) {
                    System.out.println("obj 是 null");
                } else {
                    System.out.println("obj 可用");
                }
                System.out.println("第 2 次 gc");
                obj = null;
                System.gc(); //一旦将obj对象回收,就会将此虚引用存放到引用队列中。
                Thread.sleep(1000);
                if (obj == null) {
                    System.out.println("obj 是 null");
                } else {
                    System.out.println("obj 可用");
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    • 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
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68

    终结器引用

    终结器引用和虚引用类似,可以把回收的对象放到队列,不同的是这个终结器可以自动开启一个线程依次调用对象的finilaze方法试图复活对象。

  • 相关阅读:
    springboot基础(69):Controller相关注解
    【Java】抽象类&继承的综合案例
    Leetcode1845. Seat Reservation Manager (堆的应用)
    电脑特别卡,但是看cpu和内存使用量并不大,该如何提升电脑运行速度
    视频融合平台EasyCVR语音播报功能无法关闭,且告警信息与其需要警告的内容不匹配该如何解决?
    Ruoyi从mysql切换到postgresql的几个坑
    【TensorFlow2 之014】在 TF 2.0 中实现 LeNet-5
    Python 生成器
    25.0 MySQL 数据库概述
    通过高分辨照片中激光图形对应的hsv值对图形进行提取
  • 原文地址:https://blog.csdn.net/qq_37771209/article/details/126336659