zoukankan      html  css  js  c++  java
  • 第6条:消除过期的对象引用

      虽然当我们用完对象后,java有垃圾回收机制进行回收,但是并没有那么的智能,对于某些被引用的对象,就算我们已经不在使用它了,但是java的回收机制是不会回收他们的,人们称之为“内存泄漏”。

      很多时候内存泄漏都是“人们无意识的内存引用”造成的,举个简单的例子:

    List<String> list = new ArrayList<>();
    String str = "testString";
    list.add(str);
    str  = null;

      看似上面的str被回收了,但是,事实上创建str时所开辟的内存空间是不会被回收的,因为list依然持有对str的引用这就是一个典型的“无意识的内存引用”。为了防止这些“无意识的内存引用”,我们应该了解对象相互引用的时候是存在怎样的依赖关系的。

      下面我们在看看一个简单的栈实现例子:

    public class Stack{
        private Object[] elements;
        private int size = 0;
        private static final int DEFAULT_INITIAL_CAPACITY = 16;
        
        public Stack(){
            elements = new Object[DEFAULT_INITIAL_CAPACITY];
        }
    
        public void push(Object e){
            //判断是否放的下,放不下进行扩展
            ensureCapacity();
            elements[size++] = e;
        }
    
        private void ensureCapacity(){
            if(elements.length == size){
                elements = Arrays.copyOf(elements,2*size+1);
            }
        }
      
      public Object pop(){
        if(size == 0){
          throw new EmptyStackException();
        }
        Object result = elements[--size];
        return result;
      }
    }

      看似这段程序没有明显的错误,也能运行,但是这里面存在一个内存泄漏问题,如果栈先增长了,然后在收缩,那么栈中弹出的对象将不被当做垃圾回收,即使使用栈的程序不在引用这些对象了,它们也不会被回收,因为栈内部维护着对这些对象的过期引用,所谓的过期引用是指永远不在会被解除的引用,这里就是凡在elements数组的活动部分之外的任何引用都是过期的。

      对于上述这些修复的方法还是比较简单的,一旦对象是过期引用,只需要清空这些引用即可,对应上述例子中的Stack而已,只要一个单元被弹出栈,那就是过期引用,只需要在pop方法的return result上面加上elements[size] = null;即可。

      当然,我们不要因为害怕内存泄漏而在所有的地方都手动回收内存,这样会导致我们的代码凌乱臃肿,不利于管理,我们应该把目标集中在那些长声明周期的变量中,哪些是长生命周期的变量呢,最明显的一个就是static修饰的变量,我们应该把目光放在这些变量上。  

    作者:哀&RT
    出处:博客园哀&RT的技术博客--http://www.cnblogs.com/Tony-Anne/
    您的支持是对博主最大的鼓励,感谢您的认真阅读。
    本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    C语言,C++,static
    英语自我介绍
    总线接口与计算机通信(五)CAN总线
    总线接口与计算机通信(二)SPI总线
    总线接口与计算机通信(一)I2C总线
    总线接口与计算机通信
    C语言函数指针
    服务器体系(SMP, NUMA, MPP)与共享存储器架构(UMA和NUMA)
    实时调度类
    Linux CFS调度器之唤醒抢占--Linux进程的管理与调度(三十)
  • 原文地址:https://www.cnblogs.com/Tony-Anne/p/6695461.html
Copyright © 2011-2022 走看看