-
1. Re: Memory leak in remoting objects
ron_sigal May 12, 2008 6:53 PM (in response to harish43)Every time you create a JBossMessaging connection, you're creating a Remoting bisocket connection, including a new BisocketClientInvoker.$PingTimerTask. When you close the JBM connection, the PingTimerTask should cancel itself.
You're sure that you're closing the JBM connection?
Now, the Timer that the PingTimerTasks are registered with is a static object, so I guess it's possible that the Timer is holding references to old PingTimerTasks. I don't know how you're profiling your test, but I know that with JProfiler you can see what's pointing to the PingTimerTasks and preventing them from getting garbage collected.
Could you look into that?
Thanks,
Ron -
2. Re: Memory leak in remoting objects
trustin May 12, 2008 7:28 PM (in response to harish43)It's a kind of bug in java.util.Timer. Calling TimerTask.cancel() causes the registered task from being dereferenced in Timer's internal data structure. It is because the Timer developers assumed that the cancellation of tasks would not happen that often.
The solution is probably destroying the parent Timer class and create a new one. In Java 5, java.util.concurrent.ScheduledThreadPoolExecutor provides a method that purges the references to the cancelled tasks. It's so inconvenient anyway. -
3. Re: Memory leak in remoting objects
trustin May 12, 2008 7:30 PM (in response to harish43)"trustin" wrote:
Calling TimerTask.cancel() causes the registered task from being dereferenced in Timer's internal data structure.
This sentence should be:
Calling TimerTask.cancel() prevents the registered task from being dereferenced in Timer's internal data structure. -
4. Re: Memory leak in remoting objects
ron_sigal May 13, 2008 9:01 PM (in response to harish43)Hey Trustin,
I'm seeing something different. When I runfor (int i = 0; i < 1000; i++) { Client client = new Client(clientLocator, clientConfig); client.connect(); TestCallbackHandler callbackHandler = new TestCallbackHandler(); client.addListener(callbackHandler, null, null, true); // client.removeListener(callbackHandler); client.disconnect(); }
I get lots of BisocketClientInvokers and BisocketClientInvoker.PingTimerTasks hanging around. When I uncomment the client.removeListener() line, I see something different. In particular, I still see lots of BisocketClientInvokers hanging around, but the only reference to them is a java.lang.ref.Finalizer weak reference. For some reason, when I force a garbage collection in JProfiler, the garbage collector doesn't collect them. Maybe the program isn't running long enough to do a full garbage collection? When the program concludes (but stays alive in JProfiler) I can garbage collect all of the BisocketClientInvokers and PingTimerTasks.
What I just described happens in Windows with jdk 1.5. When I run the same program in linux, the garbage collector is willing to collect the old BisocketClientInvokers, even when the program is still running.
So it doesn't look like a real leak to me, as long as the program properly disposes of its connections. It looks more like an artifact of the garbage collector behavior.
-Ron