[Biojava-dev] memory leak
Matthew Pocock
matthew.pocock at ncl.ac.uk
Fri Jan 28 04:48:11 EST 2005
Ah - do we have a parent-child inner/outer class hard/soft reference
problem? If you want the sublist to be managed independantly of the
parent, you should realy copy it. Is there a method in SymbolListTools
or SequenceTools that does this?
Matthew
mark.schreiber at group.novartis.com wrote:
>Looking at this further.
>
>The parent SymbolList adds ChangeListeners to all it's children that are
>created during subList() or subStr() operations. The children of these
>subXXX operations are views on the parent. Any Edit operations performed
>on them are notified to the parent and applied to the parent (who knew?
>how cool!). So that answers the question about what they are for and also
>why they are not cleaned up.
>
>Following your clue about the reapGarbageListeners() method your correct
>that it is never called. The only place it can be called is from
>ChangeSupport.firePreChangeEvent or ChangeSupport.firePostChangeEvent.
>Because nothing we are doing in the loop is actually causing anything to
>change there is no chance for reapListeners() to be called.
>
>To test this out I changed the loop to:
>
> while(true){
> SymbolList sl2 = sl.subList(1,12);
> Edit e = new Edit(4, DNATools.getDNA(), DNATools.g());
> sl2.edit(e);
> }
>
>This forces a changeEvent and results in garbageCollection of the
>WeakReferences and bingo, no more memory leak.
>
>So, there needs to be some mechanism by which reapGarbageListeners() can
>be called without the need for a changeEvent. I'm thinking that the
>finalize() method of SimpleSymbolList might call it but this is not
>currently possible as the reapListeners() method is protected and in a
>different package. Maybe the finalize() method could throw a dummy
>changeEvent as a bit of a hack and to signal to the world it is dying.
>
>Matthew or Thomas, Any ideas??
>
>- Mark
>
>
>
>
>
>
>Rainer Pudimat <rpudimat at informatik.uni-jena.de>
>01/27/2005 11:19 PM
>
>
> To: biojava-dev at biojava.org, Mark Schreiber/GP/Novartis at PH
> cc:
> Subject: Re: [Biojava-dev] memory leak
>
>
>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