黑马程序员技术交流社区

标题: 内存泄漏问题 [打印本页]

作者: as_heima    时间: 2014-8-10 14:37
标题: 内存泄漏问题
本帖最后由 as_heima 于 2014-8-16 20:50 编辑

Vector v=new Vector(10);
for (int i=1;i<100; i++)
{
        Object o=new Object();
        v.add(o);
        o=null;        
}
上面这段代码,发生内存泄漏了。但是我不怎么明白~求大神指教~~~~谢谢
作者: fantacyleo    时间: 2014-8-10 15:01
本帖最后由 fantacyleo 于 2014-8-10 15:10 编辑

这段代码在IBM的技术文章库中出现过,但我认为它很难说是内存泄露。我猜作者的本意是想说:变量o通过new指向了一个Object对象,把o加入v后,v中有对Object对象的引用,但当o=null后,外界就失去了对o所指对象的直接引用(也就是说没法直接访问之前创建的10个new Object对象了),而v中对Object的引用依然存在,导致垃圾回收器不会回收之前创建的10个new Object对象。

但是,从逻辑上来说,既然你把对象加入了Vector,自然是要使用它们的,既然要使用它们,而且可以通过Vector类的各种方法来访问到它们,又何来内存泄露之说呢?所以我觉得用这个例子来说明内存泄露并不恰当。还是张孝祥老师在高新技术视频中的那个内存泄露例子比较合适:
  1. public class HashCodeDemo {

  2.         public static void main(String[] args) {
  3.                   
  4.                 Point p1 = new Point(3, 3);
  5.                 Point p2 = new Point(3, 5);
  6.                 Point p3 = new Point(3, 5);
  7.          
  8.                 Collection<Point> hset =  new HashSet<Point>();
  9.                 hset.add(p1);
  10.                 hset.add(p2);
  11.                 hset.add(p2);

  12.                 System.out.println(hset.size());
  13.                 p1.x = 4;
  14.                 hset.remove(p1); // p1没有被移走。因为虽然p1的域x被修改了,但其在哈希表中的存储位置没有被修改。导致找不到p1
  15.                 System.out.println("after remove: " + hset.size());
  16.                 for (Point p : hset)
  17.                         System.out.println(p.getY());
  18.          
  19.                 System.out.println(hset.remove(new Point(3,3)));// 这样也删除不了,实际上p1已经无法再放访问到
  20.                 System.out.println(hset.contains(p1));
  21.                 System.out.println(hset.size());

  22.         }

  23. }
复制代码



作者: masai158    时间: 2014-8-10 15:05
本帖最后由 masai158 于 2014-8-10 15:06 编辑
  1. import java.util.HashSet;


  2. /**hashCode的作用:当需要在hash结构的集合中存储时就需要根据自己的属性来覆写hashCode。为什么呢?
  3. * 因为在hash结构中,必须要确保元素的唯一性,在判断唯一性的最重要的依据就是 hashCode 和 equals。如果这2个都相等的那就是同一个元素。
  4. * 程序是有限判断 hashCode值,如果相等在判断equals。所以提高程序的效率 最好就根据 自己的属性来覆写hashCode.
  5. * */
  6. public class HashCode {

  7.         public static void main(String[] args)
  8.         {
  9.                 HashSet hs = new HashSet();
  10.                 hs.add(new Person5("xiaozhang",20));
  11.                 hs.add(new Person5("xiaozi",10));
  12.                 hs.add(new Person5("xiaoxia",20));        //不写hashCode的话。和下面的对象都可以同时存入集合中
  13.                 hs.add(new Person5("xiaoxia",20));
  14.                
  15.                 Person5 xiaojian = new Person5("xiaojian",15);
  16.                 hs.add(xiaojian);
  17.                 System.out.println(hs.size());//        4
  18.                
  19.                 xiaojian.age = 10;                //我修改一个对象的成员属性以后。
  20.                 System.out.println(hs.remove(xiaojian));        //在删除对象,是没办法删除的
  21.                 /**我在创建的时候是记录的是一个哈希值,我删除的时候也必须是当时记录的哈希值,
  22.                  * 当我修改对象的属性后,他的哈希值将随之改变,肯定不是 之前的哈希值,所以没办法删除。
  23.                  *
  24.                  * 这种现象叫内存泄漏:当我需要删除一个对象时。这个对象已经不可达,而且也无法回收内存的话,这样白白的占用了内存的空间,
  25.                  * 当我的对象很多的,同时这种浪费资源的空间越来越多的时候,就会造成内存溢出
  26.                  * 内存溢出:递归的时候也应该尽量控制递归次数,不然也容易引发内存溢出。
  27.                  * */                                
  28.                 System.out.println(hs.size());//        4

  29.         }
  30. }

  31. class Person5
  32. {
  33.         public String name;
  34.         public int age;
  35.         public Person5(String name, int age)
  36.         {
  37.                 this.name = name;
  38.                 this.age = age;
  39.         }

  40.         public int hashCode() {
  41.                 final int prime = 31;
  42.                 int result = 1;
  43.                 result = prime * result + age;
  44.                 result = prime * result + ((name == null) ? 0 : name.hashCode());
  45.                 return result;
  46.         }

  47.         public boolean equals(Object obj) {
  48.                 if (this == obj)
  49.                         return true;
  50.                 if (obj == null)
  51.                         return false;
  52.                 if (getClass() != obj.getClass())
  53.                         return false;
  54.                 Person5 other = (Person5) obj;
  55.                 if (age != other.age)
  56.                         return false;
  57.                 if (name == null) {
  58.                         if (other.name != null)
  59.                                 return false;
  60.                 } else if (!name.equals(other.name))
  61.                         return false;
  62.                 return true;
  63.         }
  64. }
复制代码


刚刚总结完了。看对你有帮助不嘛!!我是后悔没看反射,就教答案了。不然又可以多混点技术分了
作者: as_heima    时间: 2014-8-10 16:26
fantacyleo 发表于 2014-8-10 15:01
这段代码在IBM的技术文章库中出现过,但我认为它很难说是内存泄露。我猜作者的本意是想说:变量o通过new指 ...

谢谢。我发的那个代码有人说内存泄漏,可是我貌似没看出来泄漏,所以发帖求大神讲解一下。您发的这篇代码我也比较赞同里面的内存泄漏:lol
作者: as_heima    时间: 2014-8-10 16:27
masai158 发表于 2014-8-10 15:05
刚刚总结完了。看对你有帮助不嘛!!我是后悔没看反射,就教答案了。不然又可以多混点技术分了 ...

:lol 辛苦了,谢谢




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2