Я изучал утечки памяти и проверял их с помощью анализатора памяти. Итак, на практике у меня есть следующий код, который пропускает активность, поскольку анонимный внутренний класс содержит ссылку на активность. Вот код:
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();
}
}
У меня есть изображения анализатора памяти для вышеупомянутых утечек здесь (6 ротаций):
Совершенно очевидно, что есть 6 запущенных потоков, которые содержат неявную ссылку на внешнюю активность и тем самым предотвращают ее сборку мусора.
Теперь рассмотрим следующий код:
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);
}
}
}
}
Здесь я сделал класс статическим, чтобы не было ссылки на внешнюю активность, и сборщик мусора мог свободно возвращать объекты Activity, не мешая классу потока.
Вот скриншоты MAT для того же:
У меня есть замешательство относительно второго набора скриншотов, где есть 5 ссылок на финализатор. Я погуглил об этом и обнаружил, что JVM добавляет объекты в очередь ссылок, как только они собираются пройти GCed. Я ожидал, что хотя это и произойдет, эти изменения не будут доступны в MAT, так как я не думаю, что GC займет много времени, чтобы освободить эти ссылки. Даже если я использую 13 вращений, результат тот же, с 12 ссылками на финализатор. Я могу ошибаться, но я думал, что MAT отобразит только 1 объект Activity, так как другие, должно быть, прошли GCed. Мы будем признательны за любую помощь в отношении эталонной очереди финализации и процесса, который происходит во время сборки мусора. Спасибо.