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

    过期对象引用没有清理掉,会导致内存泄漏。对于没有用到的对象引用,可以置空,这是一种做法。而最好的做法是,把保存对象引用的变量清理掉,多用局部变量。

     
    什么是内存泄漏?
    在Java中,对象的内存空间回收是由Java垃圾回收器回收的。而Java垃圾回收器判定一个对象能否被回收的依据是,该对象是否可达。如果该对象可达,则垃圾回收器不会回收该对象的内存空间,反之,则回收。垃圾回收器判定一个对象是否可达,是根据该对象的引用链来决定的。
    如果没有变量持有指向该对象的引用,那么,该对象就是不可达的。那么,垃圾回收器在下次回收的时候,就可以回收该对象。
    如果,依然有变量持有指向该对象的引用,但是,我们找不到该变量,那么,就称为该对象泄漏了-----垃圾回收器不可以回收该对象,因为它依然可达;但是,我们不知道如何使用该对象,因为我们找不到指向该对象的引用。
    当程序中,这种情况积聚很多的时候,就会导致内存泄漏。
     
    场景一:
    内存泄漏,丢失了指向该对象的引用
    import java.util.Arrays;
    import java.util.EmptyStackException;
    
    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;
      }
    
      public Object pop() {
        if (size == 0)
          throw new EmptyStackException();
        return elements[-- size];
      }
    
      /**
       * Ensure space for at least one more element, roughly doubling the capacity each time the array
       * needs to grow.
       */
      private void ensureCapacity() {
        if (elements.length == size)
          elements = Arrays.copyOf(elements , 2 * size + 1);
      }
    }
    
    --------------------------
    问题出在这里:
      public Object pop() {
        if ( size == 0)
          throw new EmptyStackException();
        return elements[-- size];
      }
    
    比方说,我入栈了10个元素,然后,我调用pop()方法,我调用6次pop()方法,这时,size是4,表明elemnts中还有4个元素。但是,实际上,elements还有另外6个存在,但是,这6个我们访问不到它们,但是它们是存在。这6个我们访问不到的元素,均持有指向相应对象的引用。
     
    于是,就内存泄漏了----6个对象依然存在,垃圾回收器不会回收它们,因为有变量持有指向它们的引用;而我们访问不到这些变量。
     
    将pop方法修改为:
      public Object pop() {
        if (size == 0)
          throw new EmptyStackException();
        Object result = elements [--size ];
        elements[size] = null;
        return result ;
      }
    这样,出栈的元素,在elements中不再保留出栈元素中指向对应对象的引用。
     
     
    场景二:
     
    “内存泄漏的另一个常见来源是缓存。一旦你把对象引用放到缓存中,它就很容易被忘掉,从而使得它不再有用之后很长一段时间内依然留在缓存中。”
     
    缓存的实现。
     
    使用WeakHashMap。WeakHashMap适合的场景是,如果你要缓存的项(作为Map中的项),它的生命周期(也就是说,它什么时候被删除掉)是由该项的键(K)的外部引用决定的,而不是由该项的值(Value)决定的,那么,就可以使用WeakHashMap<K,V>来实现。
     
    WeakHashMap<K,V>是这么个东西,它的K是一个对象,它有相应的内容。指向K的引用时一个弱引用,当K被置空的时候,或者当内存不够用的时候,垃圾回收器会回收K对象。当K对象被回收的时候,系统也会回收该K所在的项(K,V)。也就是说,Map中的项的存活是由K对象来决定的。
     
    这里要考虑的问题是,K什么时候被置空。
    WeakHashMap使用的一个例子:
    实现需求的需求---保存每个存活的线程的信息,然后,可以在一个地方,根据线程来查询相应的信息。当线程死掉的时候,自动将其对应的信息清除掉。
     
    这里面,线程什么时候死掉,也就是什么时候为空,这个是不确定的。这个适合使用WeakHashMap<K,V>数据结构来实现。
    WeakHashMap<Thread,SomeMetaData>
    当线程Thread死掉了,为空了,那么系统就会自动将相应的条目从WeakHashMap<Thread,SomeMetaData>中清除掉。
     
     
    场景三:
     
  • 相关阅读:
    websphere安装及部署
    ant的安装及使用
    JAVA多线程线程阻塞与唤醒
    Win2008 404 找不到文件或目录。
    cmd命令大全和IIS服务命令
    phpcgi.exe上传大量数据
    phpcgi.exe多个进程 ,cpu跑满
    php shopex显示乱码
    ie中td空值不显示边框解决办法
    Win2003服务器主机下无法/不能播放FLV视频的设置方法!
  • 原文地址:https://www.cnblogs.com/ttylinux/p/4358364.html
Copyright © 2011-2022 走看看