StackOverflowed
StackOverflowed

Reputation: 5975

Would anonymous Handler or Runnable create a memory leak?

new Handler().postDelayed(new Runnable(){

@Override
public void run() {
     // do stuff
}}, 100);

If I call this from an activity (onCreate or onResume or elsewhere) can this cause a memory leak? I've read that the new Runnable() should actually be a static instance, is that true?

Upvotes: 2

Views: 1883

Answers (2)

Sogger
Sogger

Reputation: 16132

Yes this is a leak. Because of the way Handlers work it is possible for them to stay alive for very long periods of time and prevent any resources they reference from being garbage collected. Here is a good explantion: http://www.androiddesignpatterns.com/2013/01/inner-class-handler-memory-leak.html

If your runnable may outlive the lifetime of your object, instead try the approach in the answer here: https://stackoverflow.com/a/27825703/579234

What you are doing is adding another level of object on top of the usual case that would trigger the existing Lint warning about non-static handler classes will trigger a Lint warning: Android lint checks:

HandlerLeak
-----------
Summary: Ensures that Handler classes do not hold on to a reference to an
outer class

Priority: 4 / 10
Severity: Warning
Category: Performance

In Android, Handler classes should be static or leaks might occur. Messages
enqueued on the application thread's MessageQueue also retain their target
Handler. If the Handler is an inner class, its outer class will be retained as
well. To avoid leaking the outer class, declare the Handler as a static nested
class with a WeakReference to its outer class.

Using an anonymous class is the same thing as stated in http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.9.5:

An anonymous class is always an inner class (§8.1.3); it is never static (§8.1.1, §8.5.1).

So, to explain explicitly, your runnable holds a reference to 'this' and the handler holds a reference to the runnable so 'this' won't be garbage collected until the handler is dead.

Upvotes: 3

MaciejGórski
MaciejGórski

Reputation: 22232

Yes. This code may cause a memory leak.

For as long as this anonymous class based on Runnable is in the queue (100 milliseconds in this example), it keeps a reference to outer Activity class.

Such a memory leak is not a problem by itself of course, but depending on what code inside run is executed, it may create bigger problems, like crashing the application when you e.g. try to show dialog after Activity is killed. In such situations you will see nice informational exceptions:

IllegalArgumentException: Can not perform this action after onSaveInstanceState

or

BadTokenException: Unable to add window - ... is your activity running?

Upvotes: 6

Related Questions