Emmanuel,

When client close connection, session should be discarded and it is kind of so. 
The only thing, I think, is because that the "finalize" method on 
DefaultIoFilterChain. Because it has such method, JVM can't claim the memory 
back right away because inside of the finalize code, it is impossible the very 
same object could be resurrected (because we users provide the implementation), 
so GC has to treat them quite differently (possibly go over multiple GC cycles 
before fully discard it). That's why the chain is still referenced by the 
Finalizer and so the session.

In theory, those objects should be eventually recycled. But the timing is 
totally un-deterministic and they can stay there for unnecessarily long. This 
is even true to Session objects. They are long live objects and most likely 
stay in PermGen, where GC recycles much less frequently. 

You can do a simple test. Use a client/server example in MINA code, start the 
server, start one client and let the client do some work and then close the 
client. Wait for 10 minutes, check the memory map of the server. Chances are, 
you can still find that Session object. If you trace it to "GC rootset exclude 
weak references", you will find that the session is referenced by the chain, 
which is referenced by Finalizer.

Now remove the "finalize" method in the chain and do the same test, you will 
find a different result.

Regardless of whether that is the true source of my memory leak, hopefully you 
can recognize the "finalize" method is evil. In the case of the filter chain, I 
don't see any reason why it is adopted. Getting rid of that would be a very 
good idea.

Thanks,
Yong

Here is how my chain is initialized.
----------------------------------------------------------------------

DefaultIoFilterChainBuilder chain = acceptor.getFilterChain();
chain.addLast("codec", new ProtocolCodecFilter(new            
ScMessageProtocolCodecFactory()));
        
chain.addLast("logger", new LoggingFilter());
chain.addLast("monitor", new ProtocolMonitorFilter());
        
ExecutorService threadPool = new OrderedThreadPoolExecutor(4);
chain.addLast("executor", new ExecutorFilter(threadPool));
acceptor.setHandler(new CentralDispatchHandler());


-----Original Message-----
From: Emmanuel Lecharny [mailto:[email protected]] On Behalf Of Emmanuel 
Lecharny
Sent: Friday, May 15, 2009 1:17 AM
To: [email protected]
Subject: Re: memory leak? -- help needed

Hi,

this is very strange... If the client close the connection before the 
message is sent to him, then the session should be discarded.

Could you provide the code which initialize the chain you are using ?

Also could you run your test with the latest version (ie, the trunk)? We 
have fixed some bad issues lately about the way messages are handled.

Thanks !


Yongxing Wang wrote:

> In sessionClosed() method in DefaultIoFilterChain, it will do:
>
> s.getWriteRequestQueue().dispose(session);
>
>
> There are only two classes that implements WriteRequestQueue, one is 
> CloseAwareWriteQueue and another is DefaultWriteRequestQueue. 
> CloseAwareWriteQueue is just a wrapper on top of DefaultWriteRequestQueue 
> where the dispose() method does nothing.
>  
>   public void dispose(IoSession session) {
>   }
>
>
> So I have a theory for the mem leak:
>
> 1: Client request something,
> 2: Server fetch the data and call session.write(), the data got queued in the 
> wirteRequestQueue.
> 3: Before the data got actually flushed, the client drops the connection
> 4: MINA fires sessionClosed() as expect, but the dispose method didn't 
> actually clear the queue.
> 5: Because of the session still got referenced by the Finalizer, the huge 
> amount of data just hang around.
>
>
> Am I right that the dispose() method should clear the queue?
>
> Thanks,
> Yong
>
>
>
>
> -----Original Message-----
> From: Yongxing Wang 
> Sent: Thursday, May 14, 2009 9:31 AM
> To: '[email protected]'
> Subject: RE: memory leak? -- help needed
>
> Yes, I will definitely run it against one of those tools (my Jprofile 
> evaluation expired, need to work it out). 
>
> I guess last night my brain was fried and I didn't provide enough 
> information. The dump analysis told me that there are still more than 7K 
> NioSocketSession (referenced by java.lang.Finalizer) hanging around three 
> hours after I the process out of LB. This probably related to one of my 
> earlier post:
>
> "Looking at the source code, it is caused by DefaultIoFilterChain (because it 
> has a finalize method)." -- the chain holds a reference to the session.
>
> I tried to trace the "DefaultWriteFuture" to the GC root. With 10G of dump 
> data, the query never returns.
>
> I will continue to do more analysis. At the mean time, is there a reason that 
> you have to use "finalize" method in the DefaultIoFilterChain? 
>
> Yong
>
>
> -----Original Message-----
> From: Emmanuel Lecharny [mailto:[email protected]] On Behalf Of Emmanuel 
> Lecharny
> Sent: Wednesday, May 13, 2009 11:47 PM
> To: [email protected]
> Subject: Re: memory leak? -- help needed
>
> Yongxing Wang wrote:
>   
>> Gurus,
>>   
>>     
> hi,
>
> you should use a tool to determine if the memory leak you are 
> experiencing is part of your own code. You have plenty of them out there 
> : JProfiler, OptimizeIt, YourKit, ...
>
> This will give you some insight about the part of the code where this 
> memory leak is likely to be created.
>
> There is not much we can do with the provided information atm...
>
>   


-- 
--
cordialement, regards,
Emmanuel Lécharny
www.iktek.com
directory.apache.org


Reply via email to