• java中的引用类型:强软弱虚


    java中的引用类型共4种:强软弱虚,具体每种类型的特点和应用场景。记录下。本文是看了马士兵老师的视频后记录整理的。加深印象。

    基本概念

    1. 强引用

    强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。当内存空间不足时,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。

    显式地设置M对象为null,或让其超出对象的生命周期范围,则gc认为该对象不存在引用,这时就可以回收这个对象
    示例代码

    声明一个M类

    public class M {
    
        /**
         * 当这个对象会被回收的时候,finalize会被调用
         *
         * @throws Throwable
         */
        @Override
        protected void finalize() throws Throwable {
            System.out.println("finalize");
        }
    }
    

    强引用调用

    public class NormalReference {
    
        public static void main(String[] args) throws IOException {
            M m = new M();
            m = null;
            System.gc();
    
            // 如果不写 main方法退出。System.gc()在垃圾回收线程里;
            // 有可能还没来得及回收main方法就退出了
            System.in.read();
        }
    }
    

    输出结果

    finalize
    

    2. 软引用

    软引用对象是在jvm内存不够的时候才会被回收

    代码示例

    public class Soft {
    
        public static void main(String[] args) {
            System.out.println(Runtime.getRuntime().totalMemory() / 1024 / 1024);
            //10m
            SoftReference<byte[]> m = new SoftReference<>(new byte[1024 * 1024 * 10]);
    
            System.out.println(m.get());
            System.gc();
            try {
                Thread.sleep(1500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(m.get());
    
            // 再分配一个数组,heap装不下去,这时候系统会垃圾回收,
            // 先回收一次,如果不够,会把软引用回收
            byte[] b = new byte[1024 * 1024 * 11];
    
            System.out.println(m.get());
        }
    }
    

    设置程序运行参数:-Xmx20M

    运行结果

    19
    [B@1540e19d
    [B@1540e19d
    null
    

    我们可以看到,这个时候已经被回收了。

    应用场景:软引用时候做缓存

    3. 弱引用

    弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存

    代码示例

    public class Weak {
    
        public static void main(String[] args) {
            WeakReference<M> m = new WeakReference<>(new M());
    
            System.out.println(m.get());
            System.gc();
            System.out.println(m.get());
        }
    }
    

    执行结果

    M@1540e19d
    null
    finalize
    

    4. 虚引用

    如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。
    虚引用必须和引用队列(ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。

    示例

    public class Phantom {
    
        private static final List<Object> LIST = new LinkedList<>();
        private static final ReferenceQueue<M> QUEUE = new ReferenceQueue<>();
    
        public static void main(String[] args) {
            PhantomReference<M> phantomReference = new PhantomReference<>(new M(), QUEUE);
    
            new Thread(
                    () -> {
                        while (true) {
                            LIST.add(new byte[1024 * 1024]);
                            try {
                                Thread.sleep(1000);
                            } catch (InterruptedException e) {
                                Thread.currentThread().interrupt();
                            }
                            System.out.println(phantomReference.get());
                        }
    
                    }
    
            ).start();
    
            new Thread(() -> {
                while (true) {
                    Reference<? extends M> poll = QUEUE.poll();
                    if (poll != null) {
                        System.out.println("-------虚引用对象被jvm回收了------" + poll);
                    }
                }
            }).start();
        }
    }
    
    

    运行结果

    finalize
    null
    Exception in thread "Thread-0" java.lang.OutOfMemoryError: Java heap space
    	at Phantom.lambda$main$0(Phantom.java:18)
    	at Phantom$$Lambda$1/1078694789.run(Unknown Source)
    	at java.lang.Thread.run(Thread.java:748)
    -------虚引用对象被jvm回收了------java.lang.ref.PhantomReference@688ee48d
    
    
    

    应用场景:堆外内存的管理

    总结

  • 相关阅读:
    C/C++中变量的作用域和存储类型简介
    Java与JavaScript的区别你明白吗?
    js-2018-11-09 关于Array中的srot()方法和compare()方法
    js-2018-11-01 关于break和continue语句
    0427表格学习
    0426基础标签学习
    css3部分整理
    img图片占不满整个div
    基于google protobuf 的 socket udp 通信
    微信小程序echarts学习记录
  • 原文地址:https://www.cnblogs.com/zhenghengbin/p/13121722.html
Copyright © 2020-2023  润新知