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会被释放
请教各位,我的想法错在哪里?
看到一篇内存泄露的文章:
文章中举了一个内存泄露的例子:
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通过内部的信息还能找到对象,对象不是垃圾。
在C++中,内存泄漏的范围更大一些。有些对象被分配了内存空间,然后却不可达,由于C++中没有GC,这些内存将永远收不回来。在Java中,这些不可达的对象都由GC负责回收,因此不需要考虑这部分的内存泄露。 注意事项: 1.最基本的建议是尽早释放无用对象的引用。如: …… A a = new A(); //应用a对象 a = null; //当使用对象a之后主动将其设置为空
这是我看的别的资料说的,自己也有点迷惑了,希望更多好好的讨论 …。
o=null,只是去掉了其中的一个引用。
Object o = new Object();
v.add(o);有向图里new出来的对象有两个通路和其关联o = null;
关闭了其中一条通路仍然可以通过v.get(0);访问该对象
就是说v这个引用指向的对象和new出来的Object对象依然有关联
要么v.remove(0);要么v=null;
o=null前,它的引用数为1.
o=null后,引用数为0,仍然不小于0,因而不释放。
如果加入,v.remove(i),引用数小于0,释放对象o在堆中的空间,此时内存得到回收。gc的管理模型采用树一样的结构,来保证所有的对象都是可达的。但是如果因为某些原因,还是会有一些对象不再使用,但一直被引用,此时gc不会回收这些对象,就出现了所谓的内存泄露。Java中存在内存泄露,17楼的说法是错误的!!
int *p = malloc(sizeof(int));
p = malloc(sizeof(int));
delete p;p之前申请那块内存就没有办法释放。delete p只是释放了p后来申请的那块内存。这叫做内存泄漏!而Java中不可能存在没有办法释放的内存,所以Java中不存在内存泄漏。反驳我的话,请你举反例。
OutOfMemoryError: PermGen space
“没有办法释放”不能作为指标,我也看多C和C++内存方面的东西,从来没见过这种提法!
另外C/C++中的提法不一样,他们在这方面比较严谨 malloc / free 必须成对使用,c++中
new / delete 必须成对使用这位兄弟笔误了一下 malloc 和 delete 配对了~呵呵
请看 http://en.wikipedia.org/wiki/Memory_leak,这应该是权威解释了吧?这里明明说到:...where the program is unable to release memory it has acquired.
Vector vector=new Vector();
Object object=new Object();
vector.add(object);
System.out.println("before \"object=null\" objcet==="+object);
object=null;
System.out.println("after \"object=null\" object==="+object);
System.out.println("vector.get(0)==="+vector.get(0));
}
火龙果 大哥,个人觉得 这个是典型的 内存泄露 例子,因为这里只 new 了99个Object ,不存在 内存不够问题
before "object=null" objcet===java.lang.Object@18a992f
after "object=null" object===null
vector.get(0)===java.lang.Object@18a992f明显的没有执行object=null之前object和vector.get(0)指向的是同一个对象
而object=null;这里只能理解为把object这个引用和java.lang.Object@18a992f地址指向的数据的联系给断开了而已,并不是将java.lang.Object@18a992f指向的内存的数据都当做垃圾回收
想起来了,是thinking in java里面的
for (int i = 1; i<100; i++)
{Object o = new Object();//o 是一个引用在这个是这这个应用存放的是刚刚new出来的object的地址
v.add(o);// 在v中添加了指向object的地址
o = nul…… //所以在这个时候改变o的引用是对v不起作用的,v中存放的并不是o的值,而是当时o的指向的object的引用地址
Vector v = new Vector(10);
for (int i = 1; i<100; i++)
{Object o = new Object();
v.add(o);
o = null;
}
//balababala........................这里使用v
//但是下面的程序不会再使用v了,这里如果不将v=null的话,就会一直占用堆空间。在另一个角度来说,貌似内存不见了一部分,“变小”了,如果有N个类似这样的v,就会导致内存溢出问题。