I’ve got an app where a thread is trying to send lots of Location objects via a Handler to the UI thread, where they get analyzed and passed on to other threads. I’ve noticed the app has a memory leak, as it eventually crashes 2-3 hours after starting up. If I use DDMS to profile the heap, I notice a gradual increase in the number of “Data Objects” (about 1500 per minute). It appears those 1500 are approximately evenly split between 16-byte and 32-byte items.
After gradually disabling parts of my app, I found that the Location generating thread’s call to the Handler appears to cause the leak.
I have gradually narrowed down the required parts of my thread to this:
class UIActivity implements Handler.Callback
{
@Override
public void onCreate()
{
m_handler = new Handler(this);
}
@Override
public boolean handleMessage(Message m)
{
switch(m.what)
{
case FAKE_LOCATION:
m.obj = null; // desperate anti-leak measures
return true;
}
return false;
}
public static class FakeLocationGenerator extends Thread
{
private Handler m_callback;
public FakeLocationGenerator(Handler callback)
{
m_callback = callback;
start();
}
@Override
public void run()
{
while(true)
{
Thread.sleep(50); // makes for 20hz
Location l = new Location("fake");
Message m = new Message();
m.what = FAKE_LOCATION;
m.obj = l;
m_callback.SendMessage(m);
}
}
}
}
The Handler.Callback.handleMessage() implementation on the UI activity just returns true and does nothing with the message. If I comment out the m_callback.SendMessage call, then the memory leak disappears. I tried a giant hack of calling Handler.removeMessages(FAKE_LOCATION) after each FAKE_LOCATION message, but that did nothing.
Any ideas?
Firstly, you should be using Message.obtain() and Message.recycle().
Secondly, is it possible that maybe there is no leak and you are simply generating new messages faster than they are being processed…?