I've been studying memory leaks and using memory analyser tool to check them. So, as a practice, I have following code which leaks an activity as the anonymous inner class holds a reference to the activity. Here's the code :
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
exampleOne();
}
private void exampleOne() {
new Thread() {
@Override
public void run() {
while (true) {
SystemClock.sleep(1000);
}
}
}.start();
}
}
I have the memory analyzer images for the above leaks here (6 rotations):
It's quite clear that there are 6 running threads holding an implicit reference to the outer activity, and thereby preventing it from being garbage collected.
Now, consider following code:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
exampleTwo();
}
private void exampleTwo() {
new MyThread().start();
}
private static class MyThread extends Thread {
@Override
public void run() {
while (true) {
SystemClock.sleep(1000);
}
}
}
}
Here, I've made the class static, so that there's no reference to the outer activity and GC can freely reclaim the Activity objects without being prevented by the thread class.
Here are the MAT screenshots for the same:
I have confusion regarding the second set of screenshots, where there are 5 finalizer references. I googled about it, and found out that JVM adds the objects to the reference queue once they are about to be GCed. I expected that though this would happen, those changes won't be available in MAT as I don't think GC would take much time to free up those references. Even if I use 13 rotations, the result is the same, with 12 finalizer references. I might be wrong but I thought that MAT would display only 1 Activity object as others must have been GCed. Any help regarding the finalization reference queue, and the process which goes on while garbage collection would be appreciated. Thanks.