[Biojava-dev] memory leak

Rainer Pudimat rpudimat at informatik.uni-jena.de
Thu Jan 27 10:19:22 EST 2005


Hello Mark,

I have tried your suggested change in ChangeSuppot.removeChangeListener, 
but without positive effect on my heap.

The problem is that the condition
if( (listeners[i].get() == cl) && (types[i] == ct) )
is never fullfilled so your change is never executed.

But anyway, it seems the right place to look for.
Inspired by the method next to removeChangeListener
(reapGarbageListener) I tried to test what Objects
to which References listeners[i] points to, are actually
null:

if( ((listeners[i].get() == cl) && (types[i] == ct)) || 
listeners[i].get() == null )

This is true in many cases.

On the other hand, the method reapGarbageListener was never
executed, independent of the number of
System.gc() calls.

Rainer.

mark.schreiber at group.novartis.com schrieb:
> The problem seems to be in ChangeSupport.removeChangeListener()
> 
>   /**
>    * Remove a listener that was interested in a specific types of changes.
>    *
>    * @param cl  a ChangeListener to remove
>    * @param ct  the ChangeType that it was interested in
>    */
>   public void removeChangeListener(ChangeListener cl, ChangeType ct) {
>     synchronized(this) {
>       for(int i = 0; i < listenerCount; i++) {
>         if( (listeners[i].get() == cl) && (types[i] == ct) ) {
>           listenerCount--;
>           System.arraycopy(listeners, i+1, listeners, i, (listenerCount - 
> i));
>           System.arraycopy(types, i+1, types, i, (listenerCount - i));
>           return;
>         }
>       }
>     }
> 
> I think that somewhere there needs to be a nullification of the value at 
> listeners[i]. This is a classic memory leak problem outlined in Item 5 of 
> Joshua Bloch's Effective Java. I think that the loop should be:
> 
>  
>   public void removeChangeListener(ChangeListener cl, ChangeType ct) {
>     synchronized(this) {
>       for(int i = 0; i < listenerCount; i++) {
>         if( (listeners[i].get() == cl) && (types[i] == ct) ) {
> 
>           //prevent memory leak
>           listeners[i] = null;
> 
>           listenerCount--;
>           System.arraycopy(listeners, i+1, listeners, i, (listenerCount - 
> i));
>           System.arraycopy(types, i+1, types, i, (listenerCount - i));
>           return;
>         }
>       }
>     }
> 
> Does this look correct to everyone? I'm still a little concerned about 
> that HashMap though as I don't see it here. It also doesn't address the 
> question of what are all these ChangeListeners needed for (but then I'm no 
> expert on the Changeable API).
> 
> - Mark
> 
> 
> 
> 
> 
> Mark Schreiber/GP/Novartis at PH
> Sent by: biojava-dev-bounces at portal.open-bio.org
> 01/27/2005 01:25 PM
> 
>  
>         To:     Michael Heuer <heuermh at acm.org>
>         cc:     rpudimat at informatik.uni-jena.de, biojava-dev at biojava.org, Michael Heuer 
> <heuermh at shell3.shore.net>, (bcc: Mark Schreiber/GP/Novartis)
>         Subject:        Re: [Biojava-dev] memory leak
> 
> 
> 
>>   synchronized(this) {
>>     growIfNecessary();
>>     types[listenerCount] = ct;
>>     listeners[listenerCount] = new WeakReference(cl);
>>     listenerCount++;
>>   }
> 
> 
> 
> This may be the source of the problem. The thing the WeakReference points 
> to is released when memory runs low but a reference to the WeakReference 
> is being maintained (possibly in the listeners[]).
> 
> - Mark
> _______________________________________________
> biojava-dev mailing list
> biojava-dev at biojava.org
> http://biojava.org/mailman/listinfo/biojava-dev
> 
> 
> 


More information about the biojava-dev mailing list