zoukankan      html  css  js  c++  java
  • 内存泄漏小例子

    1.

        public Object pop(){   
        if(size==0) throw new EmptyStackException();   
        return element[--size]; //短暂造成内存泄露   
        }   

    上面的代码每一次pop()的时候,Stack都会弹出一个元素,在没有加入新元素之前,实际上仍然有一个引用element[x]指向了这个已经 弹出的对象,因此GC是不会对其进行垃圾回收的。只有push()新元素的时候使得element[x]=newObject,才会使得以前创建的对象有 可能被回收。应该把上面的pop()方法改成下面的代码就安全多了:

    public Object pop(){    
           if(element.length==size) throws EmptyStackException();    
           Object o=element[--size];    
           elements[size]=null;  //使得GC有机会回收这个对象     
           return o;    
    }   

    静态集合类

    在使用Set、Vector、HashMap等集合类的时候需要特别注意,有可能会发生内存泄漏。当这些集合被定义成静态的时候,由于它们的生命周期跟应用程序一样长,这时候,就有可能会发生内存泄漏,看下面代码:

    class StaticTest
    {
        private static Vector v = new Vector(10);
    
        public void init()
        {
            for (int i = 1; i < 100; i++)
            {
                Object object = new Object();
                v.add(object);
                object = null;
            }
        }
    }

    在上面的代码中,循环申请了Object对象,并添加到Vector中,然后将对象设置为null,可是这些对象因为被Vector引用着,因此并不能被GC回收,因此造成了内存泄漏。因此,要释放这些对象,还需要被它们从Vector删除,最简单的方法就是将Vector设置为null

    集合里的对象属性值被改变

    看以下代码:

    public static void main(String[] args)
    {
        Set<Student> set = new HashSet<Student>();
        Student s1 = new Student("Jack");
        Student s2 = new Student("Mary");
        Student s3 = new Student("Eason");
    
        set.add(s1);
        set.add(s2);
        set.add(s3);
    
        System.out.println(set.size());//3
        s2.setName("Jackson"); //修改属性,此时s2元素对应的hashcode值发生改变
        set.remove(s2);        // remove不掉,造成内存泄漏
        set.add(s2);           // 添加成功
    
        System.out.println(set.size());//4
    }

    在这个例子中,由于对象s2的属性值被改变了,因此不能从set中删除,所以set中会一直保持着s2的引用,不能被回收,造成了内存泄漏。

    监听器

    在Java中,我们经常会使用到监听器,如对某个控件添加单击监听器addOnClickListener(),但往往释放对象的时候会忘记删除监听器,这就有可能造成内存泄漏。好的方法就是,在释放对象的时候,应该记住释放所有监听器,这就能避免了因为监听器而导致的内存泄漏。

    各种连接

    Java中的连接包括数据库连接、网络连接和io连接,如果没有显式调用其close()方法,是不会自动关闭的,这些连接就不能被GC回收而导致内存泄漏。一般情况下,在try代码块里创建连接,在finally里释放连接,就能够避免此类内存泄漏。

    外部模块的引用

    调用外部模块的时候,也应该注意防止内存泄漏。如模块A调用了外部模块B的一个方法,如:
    public void register(Object o)
    这个方法有可能就使得A模块持有传入对象的引用,这时候需要查看B模块是否提供了去除引用的方法,如unregister()。这种情况容易忽略,而且发生了内存泄漏的话,比较难察觉,应该在编写代码过程中就应该注意此类问题。

    单例模式

    使用单例模式的时候也有可能导致内存泄漏。因为单例对象初始化后将在JVM的整个生命周期内存在,如果它持有一个外部对象(生命周期比较短)的引用,那么这个外部对象就不能被回收,而导致内存泄漏。如果这个外部对象还持有其它对象的引用,那么内存泄漏会更严重,因此需要特别注意此类情况。这种情况就需要考虑下单例模式的设计会不会有问题,应该怎样保证不会产生内存泄漏问题。



    文/zhutoulwz(简书作者)
    原文链接:http://www.jianshu.com/p/93b91ea18c28
    著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
  • 相关阅读:
    LintCode "Maximum Gap"
    LintCode "Wood Cut"
    LintCode "Expression Evaluation"
    LintCode "Find Peak Element II"
    LintCode "Remove Node in Binary Search Tree"
    LintCode "Delete Digits"
    LintCode "Binary Representation"
    LeetCode "Game of Life"
    LintCode "Coins in a Line"
    LintCode "Word Break"
  • 原文地址:https://www.cnblogs.com/da-peng/p/5523440.html
Copyright © 2011-2022 走看看