Немного об утечках памяти и способах их избежать

Memory leaks, garbage collection, Java

Что такое Утечки памяти (Memory leaks) в Андроид разработке ?

Приложение создает объекты, они лежат в памяти и не могут оттуда отчиститься после завершения своей работы.

Почему так происходит ?

Java имеет собственные средства очистки памяти от неиспользуемых элементов. Это garbage collection .

Сборщик мусора помечает все объекты, которые можно удалить, если на них нет ссылок. Memory leak - это как раз потерявшаяся ссылка, которая показывает, что объект удалить нельзя.

Сложность этого бага заключается в том, что до определенного времени его не видно и он может не мешать.
Есть хорошая цитата Бенджамина Франклина “Маленькая течь топит большой корабль." Утечки памяти съедают оперативную память приложения. Количество неочищенной памяти будет расти и однажды может привести к тому, что ваше приложение начнет тормозить и крашиться . Что приведет к недовольству пользователей и, скорее всего, приложение будет удалено...

Одно из самых опасных , когда программе теряется ссылка на view . Казалось бы, что такого, view маленькая на экране. Однако, стоит помнить, что у view есть ссылка на Activity (Fragment). A если ссылка на view не удалилась, то и Activity(Frsgment) тоже жива. A у Activity(Fragment) есть ссылки на все view, что есть на экране.

Как понять, есть ли утечки памяти ?

Отыскать мемори лики можно разными способами. Но самый простой - воспользоваться профайлером Android studio.

Порядок действий:

  • Запускаете проект
  • В нижней панели нажимаете "Profiler"
  • Выбираете "Memory"
  • Нажимаете "Force Garbage Collection" (затем нужно немного подождать)
  • Нажимаете "Dump Java heap"
  • Фильтруете список по необходимым классам
  • Смотрите количество объектов

На картинке выше видно, что имеется четыре объекта Activity . Это произошло, потому что программист позволил программе потерять ссылки на view . А пользователи очень любят поворачивать экран телефона. С каждой сменой ориентации активити пересоздавалась, а старая оставалась валяться в глубинах памяти.

Если вы хотите способ отлова утечек памяти поинтереснее, тогда предлагаю вам ознакомиться с библиотекой LeakCanary .

Как избежать утечек памяти ?

Вот несколько советов:

1. Не создавать статические ссылки на view. У статических полей жизненный цикл такой же, как у вашего приложения.

2. Не передавать ссылки в сущности, которые живут дольше, чем объект, который вы передали. Например: не стоит передавать в класс Runnable ссылки на View , так как новый поток продолжить жить даже после пересоздания активити.

public class LeakingRunnable implements Runnable {

    private View view;

    LeakingRunnable(View view){       // не делай так!
        this.view = view;
    }
    @Override
    public void run() {
        // do some work
    }
}

А как передавать view в Runnable ?

Использовать другие типы ссылок. В Java, кроме обычных "жестких ссылок" существуют другие "мягкие ссылки" и "слабые" . Правильно их называть:

  • WeakReference
  • SoftReference
  • Phantom Reference

Наличие "мягких ссылок" уже не будет мешать garbage collection удалять Acrivity. Подробнее почитать о них вы можете по ссылке: отличия между слабыми, мягкими, фантомными и обычными ссылками в Java

Без утечек памяти код выше выглядел бы так:

public class NoLeakingRunnable implements Runnable {

    @NonNull
    private final WeakReference<View> viewRef;

    public NoLeakingRunnable(@NonNull View view){
        this.viewRef = new WeakReference<>(view);         //делай так!
    }
    @Override
    public void run() {
        View view = viewRef.get();
        // do some work
    }
}  

3. Нужно делать внутренние классы Activity статическими. У внутреннего класса активити про обращении к view (и любым другим объектам) создаются ссылки на этот объект. И если внутренний класс живет дольше, чем активити, то появляется Memory leak.

В данной статье была рассказана лишь небольшая часть информации о том, что же такое утечки памяти в Андроид разработке и самые простые способы их избежать. Существует еще множество сложных ситуаций. Некоторые их них будут разобраны в следующих статьях. Подписывайтесь на новые статьи.

Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь
SZ
24 июня 2019 г. 17:49
Serg Zhi

C++ - Тест 003. Условия и циклы

  • Результат:78баллов,
  • Очки рейтинга2
АС
24 июня 2019 г. 8:03
Александр Спиридонов

C++ - Тест 001. Первая программа и типы данных

  • Результат:53баллов,
  • Очки рейтинга-4
БА
23 июня 2019 г. 13:52
Борис Артамонов

C++ - Тест 003. Условия и циклы

  • Результат:35баллов,
  • Очки рейтинга-10
Последние комментарии
24 июня 2019 г. 10:23
Евгений Легоцкой

Хорошо, ну будут проблемы помимо того, что касается статей, то не стесняйтесь задавать вопросы на форуме.
МБ
24 июня 2019 г. 10:21
Михаил Булатов

Извиняюсь, все работает(из-за невнимательности).
24 июня 2019 г. 9:52
Евгений Легоцкой

Придётся делать ещё сигнал в дочернем qml и пробрасывать через коннекты и обработчики. А вообще нужно смотреть конкретный код и что вы пытаетесь сделать. Так что лучше будет, если вы зад...
21 июня 2019 г. 8:31
Ruslan Polupan

Вот моя строка по которой все отлично сработало %cqtdeployer% -bin c:/CentralMposKeys/CentalMposKeys.exe -qmake c:/Qt/5.12.2/mingw73_64/bin/qmake.exe
21 июня 2019 г. 8:24
Андрей Янкович

Возможно кому то пригодится сqtdeployer для windows работает точно так же как и для Linux разница лишь в команде запуска Linux: cqtdeployer Windows: %cqtdeployer...
Сейчас обсуждают на форуме
24 июня 2019 г. 14:36
Михаиллл

Нашел проект подключения к вебсокету.Но по моему адресу не могу подключиться.Нужно ли для этого использовать библиотеки?Вы не знаете адрес вебсокета, на котором можно проверить с...
24 июня 2019 г. 14:07
Евгений Легоцкой

Я пока даже не знаю, а какой код самого подключения? использовали ожидание на подключение? Так делали? socket->connectToServer("market");if (socket->waitForConnected(1000)) ...
24 июня 2019 г. 13:19
IscanderChe

// widget.cpp#include "widget.h"#include <QTableView>#include <QVBoxLayout>#include "checkboxdelegate.h"#include "comboboxdelegate.h"#include "mytableview.h"#include <QSqlD...
24 июня 2019 г. 11:16
BlinCT

Хорошо, с этим понятно. Вот есть такой набор каких то кнопок. Цифры отображают в каком порядке должен менятся фокус.1. Как правильнее сделать отображение активного обьекта...
e
24 июня 2019 г. 10:58
evgenm27

Спасибо за ответ, буду пробовать
Ищу работу?
10,000.00 руб. - 15,000.00 руб.
Нужен помощник для создания API.
Moscow, Moscow, Russia
25,000.00 руб. - 30,000.00 руб.
Разработчик Qt/C++
Barnaul, Altai Krai, Russia

Для зарегистрированных пользователей на сайте присутствует минимальное количество рекламы

EVILEG
О нас
Услуги
Присоединяйтесь к нам
© EVILEG 2015-2019
Рекомендует хостинг TIMEWEB