• 07.消除过期对象的引用


    前言

    《Effective Java》中文第三版,是一本关于Java基础的书,这本书不止一次有人推荐我看。其中包括我很喜欢的博客园博主五月的仓颉,他曾在自己的博文《给Java程序猿们推荐一些值得一看的好书》中也推荐过。加深自己的记忆,同时向优秀的人看齐,决定在看完每一章之后,都写一篇随笔。如果有写的不对的地方、表述的不清楚的地方、或者其他建议,希望您能够留言指正,谢谢。

    《Effective Java》中文第三版在线阅读链接

    是什么

    过期对象的引用:指的是永远不会再被解除的引用。为什么会出现这样的情况,这是因为我们的栈在显示增长,然后再收缩,那么从栈中弹出来的对象将不会被当做垃圾回收,即使使用的栈的程序不再引用这些对象,它们也不会被回收。因为,栈内部维护着对这些对象的过期引用。

    没有消除过期对象实例,代码如下:

    /**
     * @author gongguowei01@gmail.com
     * @since 2020-01-19
     */
    public class Stack {
    
        public Object[] elements;
    
        public int size = 0;
    
        private static final int DEFAULT_VALUE = 16;
    
        public Stack() {
            elements = new Object[DEFAULT_VALUE];
        }
    
        public void push(Object e) {
            ensureCapacity();
            elements[size++] = e;
        }
    
        public Object pop() {
            if (0 == size) {
                throw new EmptyStackException();
            }
            return elements[--size];
        }
    
        public void ensureCapacity() {
            if (elements.length == size) {
                elements = Arrays.copyOf(elements, 2 * size + 1);
            }
        }
    }
    

    上方代码测试实例如下

    /**
     * @author gongguowei01@gmail.com
     * @since 2020-01-19
     */
    public class Test {
        public static void main(String[] args) {
            Stack stack = new Stack();
    
            stack.push("1");
    
            stack.push("2");
    
            stack.pop();
    
            stack.push("3");
        }
    
    }
    

    运行结果如下
    在这里插入图片描述
    当我们调用pop()方法时,size变为1,但是elements数组中还存在过期对象“1”的引用。

    消除过期对象的引用,代码实例如下

    /**
     * @author gongguowei01@gmail.com
     * @since 2020-01-19
     */
    public class Stack02 {
        public Object[] elements;
    
        public int size = 0;
    
        private static final int DEFAULT_VALUE = 16;
    
        public Stack02() {
            elements = new Object[DEFAULT_VALUE];
        }
    
        public void push(Object e) {
            ensureCapacity();
            elements[size++] = e;
        }
    
        public Object pop() {
            if (0 == size) {
                throw new EmptyStackException();
            }
            Object result = elements[--size];
            //消除过期对象引用
            elements[size] = null;
            return result;
        }
    
        public void ensureCapacity() {
            if (elements.length == size) {
                elements = Arrays.copyOf(elements, 2 * size + 1);
            }
        }
    }
    
    

    哪里用

    在有可能出现内存泄露的场景

    • 缓存
    • 自己管理内存的场景
    • 监听器和其他回调

    总结

    不消除过期对象的引用,将会引起内存泄露,内存泄漏通常不会表现为明显的故障,所以它们可能会在系统中保持多年。 通常仅在仔细的代码检查或借助堆分析器(heap profiler)的调试工具才会被发现。 因此,学习如何预见这些问题,并防止这些问题发生,是非常值得的。

  • 相关阅读:
    NuGet 包版本引用 | Microsoft Docs
    victoriaMetrics库之布隆过滤器
    记一次victoriaMetrics代理性能优化问题
    victoriaMetrics之byteBuffer
    面试官:什么是MySQL 事务与 MVCC 原理?
    趣说 | 数据库和缓存如何保证一致性?
    VirtualBox复制虚拟机后丢失eth0网卡的解决办法
    VirtualBox安装centos6遇到的问题
    Lambda表达式获得泛型
    springbootxjar加密打包
  • 原文地址:https://www.cnblogs.com/gongguowei01/p/12215831.html
Copyright © 2020-2023  润新知