日期:2014-05-20  浏览次数:20650 次

java 为什么会内存泄露,这个典型的例子为什么会造成内存泄露?
http://www.cnblogs.com/dotnetdoor/archive/2008/06/09/1216125.html
看到一篇内存泄露的文章:
文章中举了一个内存泄露的例子:
Vector v = new Vector(10);
for (int i = 1; i<100; i++)
{Object o = new Object();
v.add(o);
o = null;
}//

文章中描述:
  在这个例子中,循环申请Object 对象,并将所申请的对象放入一个Vector 中,如果仅仅释放引用本身,那么Vector 仍然引用该对象,所以这个对象对GC 来说是不可回收的。因此,如果对象加入到Vector 后,还必须从Vector 中删除,最简单的方法就是将Vector对象设置为null。

在我看来 vector中的 o 已经都统统指向了 null 而 new 出来的Object 已经没有对象再应引用它了,没用被应用的对象就应当被回收啊,所以这些new Object会被释放
请教各位,我的想法错在哪里?

------解决方案--------------------
首先理解什么是引用,什么是对象。
java中我们是通过引用来操作对象的。
比如Object o = new Object();
这里的o是引用,根据o能找到新创建的对象,但是o并不是这个对象。
打个比方,o就是一个门牌号,通过门牌号能找到放对象的地方。
v.add(o);就是你把门牌号放到里面了,也就是说v通过内部的信息还能找到对象,对象不是垃圾。
------解决方案--------------------
在Java中,内存泄漏就是存在一些被分配的对象,这些对象有下面两个特点,首先,这些对象是可达的,即在有向图中,存在通路可以与其相连;其次,这些对象是无用的,即程序以后不会再使用这些对象。如果对象满足这两个条件,这些对象就可以判定为Java中的内存泄漏,这些对象不会被GC所回收,然而它却占用内存
在C++中,内存泄漏的范围更大一些。有些对象被分配了内存空间,然后却不可达,由于C++中没有GC,这些内存将永远收不回来。在Java中,这些不可达的对象都由GC负责回收,因此不需要考虑这部分的内存泄露。 

  注意事项: 

  1.最基本的建议是尽早释放无用对象的引用。如: 

  …… 

  A a = new A(); 

  //应用a对象 

  a = null; //当使用对象a之后主动将其设置为空 
这是我看的别的资料说的,自己也有点迷惑了,希望更多好好的讨论。。。

  …。 


------解决方案--------------------
一楼的意思是不是说,通过v还能访问到o,所以虽然o=null,但o指向的那个对象仍然能通过v访问到,所以GC不会回收的
------解决方案--------------------
v.add(o);

意味着对象o,增加了一个新的引用(如果v中没有指向o的引用,如何通过v来访问到o)
o=null,只是去掉了其中的一个引用。
------解决方案--------------------
其实Java中不可能存在内存泄漏,因为GC会在必要的时候回收内存。

这个例子没有体现内存泄漏,但是用来理解内存泄漏的潜在发生可能还是可以的。

不需要那么复杂,一个非常简单的例子就能说明问题:

Object o1 = new Object();

Object o2 = o1;

o1 = null; // 这时o1指向的那个对象回收了吗?没有,因为它还被o2引用着

o2 = null; // 这样才能回收

实际应用中,只要o2的作用域很小,不执行o2=null也是没有问题的,因为只要o2过了它的生存期,它指向的对象就能被回收。

结论是,作用域越大的变量,越要引起重视,因为它可能占用着某些对象引用而导致对象不能被回收。换句话说,尽可能地缩小变量的作用域——这也是你在Java中关于内存方面能做的唯一努力了。