to: buaaaladdin(阿拉丁的灯) 你好象还没明白我的意思啊? 第一个例子,数组里是保留着引用,但是,我是说,如果Stack生命结束后, GC是否会回收?如果会回收,我认为这就不算泄漏。第二个例子要比第一个严重,因为可能类EventListenerList死亡后,里面的 元素还没死,还被引用。 第二例中,作者就是跟你说的那样: public class EventListenerList { // // etc. // public void remove(EventListener listener) { int index = find(listener); if (index < 0) // error condition - do something about it for (int n = index; n < size - 1; ++n) listeners[n] = listeners[n + 1]; listeners[size - 1] = null; --size; } } 这当然没问题,但我还是不明白,为什么里面的元素在没有引用(?)时还不被回收, 我怀疑别的地方还有引用,如Listener注册到的界面元素是否对这个Listener有引用?
to allenhe(): 你的意思是要数组里的元素都是null,就组才会被回收?搞错了吧? 是先去掉上层(引用),下层(数组)没有被引用了,才被回收的,也就是先 回收上层,才回收下层的。
楼主太粗心大意,第一题编译报错如下: ^-^D:\>javac Stack.java Stack.java:8: cannot resolve symbol symbol : method ensureCapacity () location: class Stack ensureCapacity(); ^ Stack.java:13: cannot resolve symbol symbol : class EmptyStackException location: class Stack throw new EmptyStackException(); ^ 2 errors
你好象还没明白我的意思啊?
第一个例子,数组里是保留着引用,但是,我是说,如果Stack生命结束后,
GC是否会回收?如果会回收,我认为这就不算泄漏。第二个例子要比第一个严重,因为可能类EventListenerList死亡后,里面的
元素还没死,还被引用。
第二例中,作者就是跟你说的那样:
public class EventListenerList
{
//
// etc.
//
public void remove(EventListener listener)
{
int index = find(listener); if (index < 0)
// error condition - do something about it for (int n = index; n < size - 1; ++n)
listeners[n] = listeners[n + 1]; listeners[size - 1] = null;
--size;
}
}
这当然没问题,但我还是不明白,为什么里面的元素在没有引用(?)时还不被回收,
我怀疑别的地方还有引用,如Listener注册到的界面元素是否对这个Listener有引用?
另外Listener如果被addXXXListener,就被一个组件注册了,那么它的引用也会被该组件持有,而组件一般是按钮等可视构件,和应用程序生命期一样长,所以如果不被组件removeXXXListener,这些Listener对象也将一直存在下去。
第一个例子象是《Effective Java》中的。可参见http://courses.dce.harvard.edu/~cscie160/EffectiveJava.htm
第一例中,无非是一个很满的数组,有些不用的元素在那耗着浪费,这我
明白。我只是认为,如果Stack死亡后,GC会全部收回内存,就不算内存泄漏.(???)第二例,作者没有说明为什么Listener就会泄漏。只能“想象”它被注册组件引用。
这样,这信EventListenerList死亡后,这些Listener还在。如果没有谁有意见,这就是结论了?
第一个问题 ,pop时只是返回栈顶的元素,没有释放内存(没有把它置为null。其实置为null只是失去对元素的引用,等着gc来收集了,并没有真正释放内存),当然有内存泄漏;
第二个问题类似,只是不只是内存资源的浪费,问题更严重。
这是上面这位兄弟这么说。
那你怎么说呢,你不觉得上面的程序是“泄漏”?
虽然那不是好程序,但我也觉得不算泄漏。
在JNI中,有些内存是虚拟机控制不到的,即使你的java程序结束了,
有一些内存也不能回收,我觉得这才算是泄漏。
第一个问题:pop时,没有释放elements中的对象,只是返回了elements中一个的对象引用。也就是说这个队列实际上只能向里面加对象,而没有删除对象的方法。
就象你说的,如果你程序中使Stack生命期结束了,这些对象可能被释放,也可能不会释放。
想一下:当你pop了一个对象,实际上size指向顶层下一个对象,但顶层的还存在,此时如果push了,先将扩充一个集合,然后将size的位置指向新的对象,那原来的的那个对象还存在,但已经没有对象的引用指向它了,这里产生内存泄漏。如果你先pop了多个,在push,内存还要多泄漏。
产生的原因也是和第一个一样的。
listeners[n] = listeners[n + 1];实际上也没有释放原来的listeners[n]对象,而产生了一个没有被引用的对象,即这个对象不可能被回收。
下面的英文,大致也是这个意思,描述了产生泄漏的条件。还有:java里关于对象的概念和c里的指针有很大的不同,在初学的时候可以这样去快速理解,但写过一些程序后就会体会到他们的不同。
关于释放这些对象,也不是简单地赋为null就行了的。
虽然通常情况java不必我们关心内存。
但程序处理不好照样会有内存泄漏,就像楼主的题目。
另外
楼主:如果程序中想写数据结构,最好用java自己提供的集合来实现,它们一般都提供了分配和释放对象包含的方法。
第二个程序里。。
1,find()函数的第一个return 语句笔误了吧。是return n;
2,remove()函数里,如果是移除最后一个listener,
语句"listeners[n] = listeners[n + 1];"数组越界了吧不知小弟有没看错呢?
不过JVM会怎么处理Object数组里的东西,我还是不怎么明白,候教中如果JVM的垃圾回收决定要回收此对象数组,它是简单的置null,把数组占的内存收掉,还是会顺便把具体的元素(不在有其它对象对它的引用)也收走呢,,,?
1,find()函数的第一个return 语句笔误了吧。是return n;
2,remove()函数里,如果是移除最后一个listener,
语句"listeners[n] = listeners[n + 1];"数组越界了吧
---------------------
我是copy过来的。find的我看也是 return n;
不过,第二个问题,应该是没有越界。因为是 n<size-1的,就是
n最大才size-2。
所包含的意义就行了. "irrelevant memory holding"似乎合适一点. 关于这个一
点确实要注意,不要把GC想像的那么美妙,其实"它很傻", 如果在更合适的时候,发
出相比较更明确的指令驱动它,则是非常认真负责的做法(当然,就算你这么做了,
GC买不买你账还另当别论那,GC的实现是平台相关的). 正如有的兄弟谈到,在一些
要求比较高的situations(例如:长期运行的程序,频繁调用的方法,多线程并发处理
模块,内存容量苛刻的环境等),最好手动做些工作,就能或多或少地弥补GC比较傻这
一事实所带来的负面影响. 当然我说GC傻是个不太负责任的说法,GC的工作原理比较
复杂,要考虑的事情非常多,除非是sun的这方面的专家才有资格对它评头论足啊.我
只是凭普通人"看上去"的方式说的. 例如,GC提供了一种机制,让应用可以重新发现
已经走上"适合被收集"之路的对象,并做出有关处理. 虽然我还不知道这样的feature
有什么具体应用价值,但sun费劲地开发并提供了这样的功能,说不定就有啥用,呵呵.
可以说有JNI的地方,就存在内存泄漏,只是多少而已. 包括jvm内部的JNI,照样存在
内存泄漏,我看过这方面的研究文章,其中最厉害的两个方面是JNI实现的数据库操作
和平台相关的重量级图形控制. 我自己开发了CWJTray大量利用JNI实现,其中涉及
双向互传对象、jvm回调、JNI图形控制、线程同步,才感受到内存泄漏真的是个很
严重的问题,也是个非常难于控制的问题。好在不是什么大型软件。试想,象一般
的大些的软件,如Weblogic,Websperhe,JBuilder之类,开发者很不容易啊。怪
不得好值钱啦。
正确
1。泄漏
因为add过一个元素以后,这个元素永远不会被清除
换句话说,只要add过一次,那elements就永远有数据。
所以stack不会被回收
有数据就不会回收?
有引用才不会回收吧。
elements无法被回收,stack会被回收么?
你的意思是要数组里的元素都是null,就组才会被回收?搞错了吧?
是先去掉上层(引用),下层(数组)没有被引用了,才被回收的,也就是先
回收上层,才回收下层的。
Stack.java:8: cannot resolve symbol
symbol : method ensureCapacity ()
location: class Stack
ensureCapacity();
^
Stack.java:13: cannot resolve symbol
symbol : class EmptyStackException
location: class Stack
throw new EmptyStackException();
^
2 errors
bluesmile979(笑着) ( )
正确
1。泄漏
因为add过一个元素以后,这个元素永远不会被清除
换句话说,只要add过一次,那elements就永远有数据。
所以stack不会被回收
===================================================楼主的第一个例子有elements无add ,第二个例子有add无elements是不是看错了?
回复人: allenhe() ( ) 信誉:100 2004-04-26 18:29:00 得分:0
bluesmile979(笑着) ( )
正确
1。泄漏
因为add过一个元素以后,这个元素永远不会被清除
换句话说,只要add过一次,那elements就永远有数据。
所以stack不会被回收
===================================================楼主的第一个例子有elements无add ,第二个例子有add无elements是不是看错了?
=============================
add是增加数组的元素 还是第一个例子里的push方法
bluesmile979(笑着)说的add方法,或元素,也可以广义地看作push和其它类型元素。第一例是Effective java上的。
to game0ver12345(sfsfdsfdsdfsf) :我们且不谈具体细节。如编译错。这些不问题的实质。
bluesmile979(笑着)说的add方法,或元素,也可以广义地看作push和其它类型元素。第一例是Effective java上的。 ======================================================大家都想讨论问题的实质。但是这些错误或多或少的影响大家对问题实质的理解。讨论的时候严谨一些不是更好吗?而且作为一个程序员粗心大意是一个极之不好的习惯。