Политика конфиденциальностиКонтактыО сайтеОтзывыGitHubDonate
© EVILEG 2015-2018
Рекомендует хостинг
TIMEWEB

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

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 хостинг.

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь
N
23 марта 2019 г. 7:52
Nico03

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

  • Результат:80баллов,
  • Очки рейтинга4
Y
22 марта 2019 г. 9:39
Yavlados

Qt - Тест 001. Сигналы и слоты

  • Результат:21баллов,
  • Очки рейтинга-10
ЭА
22 марта 2019 г. 5:02
Эвелина Алексеева

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

  • Результат:53баллов,
  • Очки рейтинга-4
Последние комментарии
22 марта 2019 г. 12:32
Евгений Легоцкой

Ну может бибилотеки не те положили? У вас сборка для MinGW, а либы для MSVC.
ВН
22 марта 2019 г. 11:08
Волчонок Над-Пропастью

Из кьюта приложение не хочет запускаться, аварийно завершается, но каких-либо ошибок не выдаёт. Оно открывается, после нажатия "старт" зависает и завершается. Если не из кьюта запускать дебаг ...
21 марта 2019 г. 15:49
Евгений Легоцкой

серьезно? Эта ошибка 404 уже даже не относится к данному вопросу. В каких-то urls в вашем проекте. Вопросы, которые не относятся непосредственно к статье, задавайте, пожалуйста на...
АБ
21 марта 2019 г. 15:00
Артем Бел

а это где? сейчас ошибка в debag такая: Page not found (404)Request Method: GETRequest URL: http://amadowshop.site/accounts/profile/
21 марта 2019 г. 12:47
Евгений Легоцкой

не вижу здесь проблемы, поменяйте url для callback в приложения oauth в социальных сетях https://amadowshop.site/auth/verify/complete/facebook/
Сейчас обсуждают на форуме
m
22 марта 2019 г. 19:40
monevich

int main(int argc, char *argv[]){ QApplication a(argc, argv); MainWindow w; w.show(); if (argc==2) { w.openFile(argv[1]); } return a.exec();} Допустим...
22 марта 2019 г. 12:29
Дмитрий

Да, мьютекс добавил, но в том потоке, где сигнал вызывается.
ВН
22 марта 2019 г. 9:04
Волчонок Над-Пропастью

Да, на эту проблему! Зато у меня теперь новая, ругается на подключение QMediaPlayer, пишет, что не находит подобного файла или библиотеки. Пока не нашла как исправить, только вариант с переуст...
22 марта 2019 г. 8:58
Михаиллл

4) это , похоже, для создания видоизмененных страниц, для анимации. 3,5) добавить фвйл/qt/ui.qml
22 марта 2019 г. 8:04
Евгений Легоцкой

Привет. Если там std::vector , то наверное можно заранее подготовить вектор с необходимым количеством элементов и просто устанавливать значение по индексу элемента. Но в данном слу...
Присоединяйтесь к нам в социальных сетях

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