В статье мы расскажем, что такое утечка памяти, как происходит и какие вызывает последствия для операционной системы Android. Также рассмотрим инструменты для обнаружения утечек памяти, типовые модели утечки памяти в Android, способы оценки степени критичности и методы предотвращения основных видов утечек.
Каждому приложению для нормальной работы нужна оперативная память. Для обеспечения необходимым количеством памяти всех приложений Android должен эффективно управлять выделением памяти под каждый процесс. Среда выполнения Android запускает сборку мусора (GC), когда оперативная память заканчивается.
Что такое сборщик мусора?
Java Memory Management со встроенным сборщиком мусора является одним из лучших достижений этого языка. Он позволяет разработчикам создавать новые объекты, не заботясь о распределении памяти и ее освобождении, поскольку сборщик мусора автоматически восстанавливает память для повторного ее использования. Это обеспечивает более быструю разработку с меньшим количеством кода, одновременно устраняя утечки памяти и другие проблемы, связанные с ней. По крайней мере, в теории.
По иронии судьбы сборщик мусора Java работает слишком хорошо, создавая и удаляя большое количество объектов. Большинство проблем управления памятью решаются, но часто за счет уменьшения производительности. Создание универсального сборщика мусора, применяемого ко всем возможным ситуациям, привело к сложностям с оптимизацией системы. Чтобы разобраться со сборщиком мусора, нужно сначала понять, как работает управление памятью на виртуальной машине Java (JVM).
Как работает сборщик мусора
Многие считают, что сборщик мусора собирает и удаляет из памяти неиспользуемые объекты. На самом деле сборщик мусора Java делает все наоборот. Живые объекты отмечаются как активные, а все остальное считается мусором. Как следствие, эта фундаментальная особенность может привести ко многим проблемам с производительностью.
Начнем с так называемой кучи (англ. «heap») — области памяти, используемой для динамического распределения ресурсов приложений. В большинстве конфигураций операционная система заранее отдает эту часть под управление JVM во время работы программы. Это приводит к последствиям:
- создание объекта происходит быстрее, потому что глобальная синхронизация с операционной системой не требуется для каждого отдельного объекта. В процессе выделения памяти под приложение JVM просто фиксирует за задачей определенный участок памяти и перемещает указатель смещения вперед (картинка ниже). Следующее распределение начинается с этого смещения и занимает следующий участок памяти;
- когда объект больше не используется, сборщик мусора восстанавливает базовое состояние этого участка памяти и повторно использует ее для размещения другого объекта. Это означает, что нет явного удаления и память все еще не будет очищена.
Новые объекты просто размещаются в конце кучи.
Все объекты размещены в куче, управляемой JVM. Каждый элемент, используемый разработчиком, обрабатывается таким образом, включая объекты класса, статические переменные и даже сам код. Пока объект ссылается на что-то, JVM считает его используемым. Когда объект больше не ссылается и, следовательно, недоступен по коду приложения, сборщик мусора удаляет его и восстанавливает неиспользуемую память. Все настолько просто, как и звучит, но возникает вопрос: какова первая ссылка в дереве объектов?
Корни сборщика мусора — начальная позиция всех иерархий (деревьев) объектов
Каждое дерево объектов должно иметь один или несколько корневых объектов. Пока приложение может достичь этих корней, все дерево доступно. Но когда эти корневые объекты считаются доступными? Специальные объекты, называемые корнями сборщика мусора (корни GC, рисунок ниже), всегда доступны, а также любой объект, чьим корнем является корень сборщика мусора.
В Java существуют следующие типы корней сборщика мусора:
- локальные переменные поддерживаются активными благодаря стеку потока. Это фиктивная виртуальная ссылка на объект и, следовательно, она не видна. Для всех целей и задач локальные переменные являются корнями сборщика мусора;
- активные потоки Java всегда считаются используемыми объектами и поэтому являются корнями сборщика мусора. Это особенно важно для локальных переменных потока;
- на статические переменные ссылаются их классы. Это делает их де-факто корнями сборщика мусора. Сами классы могут быть собраны сборщиком, что приведет к удалению всех статических переменных, на которые они ссылаются. Это имеет особо важно, когда мы используем серверы приложений, контейнеры OSGi или загрузчики классов в целом.
Корни сборщика мусора — это объекты, которые ссылаются на JVM и, таким образом, остаются в памяти устройства.
Поэтому простое Java-приложение имеет следующие корни сборщика мусора:
- локальные переменные в главном методе;
- основной поток;
- статические переменные главного класса.
Маркировка и сборка мусора
Чтобы определить, какие объекты больше не используются, JVM периодически запускает алгоритм маркировки и сборки мусора:
- Алгоритм «проходит» по всей иерархии объектов, начиная с корней сборщика мусора, и отмечает каждый найденный объект как активный.
- Вся участки памяти, не содержащие активных объектов (а точнее объектов, которые не были отмечены в предыдущем шаге), восстанавливаются. Они просто обозначаются как свободные.
Сборщик мусора предназначен для устранения причины утечки памяти — недостижимых, но не удаленных объектов в памяти. Однако это работает только для утечек памяти в классическом их понимании. Возможно, что неиспользуемые объекты по-прежнему доступны приложению, потому что разработчик просто забыл очистить ссылки на них. Такие объекты не могут быть собраны сборщиком. Хуже того, такая логическая утечка памяти не может быть обнаружена никаким программным обеспечением.
Когда объекты больше не ссылаются прямо или косвенно на корень сборщика мусора, они будут удалены. Как видно, с классическими утечками памяти хорошо справляется встроенный сборщик мусора. С другими видами утечек памяти поможет справиться другое программное обеспечение, которое будет рассмотрено далее.
Простыми словами, в памяти остаются только те объекты, которые используются пользователем.
Однако, когда код написан плохо, неиспользуемые объекты могут ссылаться на несуществующие объекты, и сборщик мусора отмечает их как активные и не может их удалить. Это и называется утечкой памяти.
Почему утечка памяти — это плохо?
Ни один объект не должен оставаться в памяти дольше, чем нужно. Ведь эти ресурсы могут пригодиться для задач, которые могут иметь реальную ценность для пользователя. В частности, для Android это вызывает следующие проблемы:
Во-первых, когда происходят утечки, доступной для использования памяти становится меньше, что вызывает более частые запуски сборщика мусора. Такие запуски останавливают рендеринг пользовательского интерфейса, а также вызывают остановку других компонентов, необходимых для нормальной работы системы. В таких случаях прорисовка кадра длиться дольше обычных 16 мс. Когда прорисовка опускается до отметки ниже 100 мс, пользователи начнут замечать замедления в работе приложений.
В Android отзывчивость приложений контролируется менеджером активности и менеджером окон. Система откроет диалог ANR (приложение не отвечает) для конкретного приложения, когда будет выполнено одно из следующих условий:
- приложение не отвечает на нажатие клавиш, или нажатия на экран на протяжении 5 секунд;
BroadcastReceiver
не завершился на протяжении 10 секунд;
Вряд ли пользователям понравится видеть это сообщение на экранах своего гаджета.
Во-вторых, приложение с утечкой памяти не сможет получить дополнительные ресурсы от неиспользуемых объектов. Оно сделает запрос на выделение дополнительной памяти, но всему есть свой предел. Android откажется выделять больше памяти для таких приложений. Когда это произойдет, приложение просто упадет. Это может вызвать негативные эмоции у пользователей, а они, в свою очередь, могут не только удалить приложение, но и оставить негативные отзывы о нем в магазине приложений.
Как определить утечку?
Чтобы определить утечку памяти, необходимо очень хорошо разбираться в работе сборщика мусора. Но Android также может предоставить несколько хороших инструментов, которые могут помочь определить возможные утечки или найти подозрительный кусок кода.
Приложение Leak Canary от Square — хороший инструмент для обнаружения утечек памяти в приложении. Оно создает ссылки на объекты вашего приложения и проверяет, удаляются ли эти ссылки сборщиком мусора. Если нет, тогда все данные записываются в файл .hprof
и проводится анализ на наличие утечек памяти. Если утечка все же будет обнаружена, приложение пришлет вам уведомление о том, как это происходит. Рекомендуется использовать это приложение до выпуска в продакшн.Android Studio также имеет удобный инструмент для обнаружения утечек памяти. Если есть подозрения, что часть кода в вашем приложении может вызывать утечку, тогда можно сделать следующее:
- Скомпилировать и запустить отладочную версию сборки на эмуляторе или устройстве подключенному к вашему компьютеру;
- Перейти к подозрительной операции, затем вернуться к предыдущему действию, которое выведет подозрительную операцию из стека задач;
- В Android Studio открыть Android Monitor window → Memory section и нажать на кнопку запуска сборщика мусора (Initiate GC). Затем нажать кнопку
Dump Java Heap
; - После нажатия кнопки
Dump Java Heap
Android Studio откроет файл.hprof
. Существует несколько способов проверки утечки памяти через этот файл. Вы можете использовать Analyzer Tasks в правом верхнем углу для автоматического обнаружения утечек. Или же можно переключиться в режимTree View
и найти действие, которое должно быть отключено. Проверяем данныеTotal Count
, и если нашли отличия в данных, значит, что где-то есть утечка памяти. - Как только была обнаружена утечка, нужно проверить дерево ссылок и узнать, какой объект ее вызывает.
Каковы общие схемы утечек?
Есть множество причин, по которым происходит утечка памяти в Android. Но все они могут быть отнесены к трем категориям.
- утечки памяти, инициируемые статической ссылкой;
- утечки памяти, инициируемые рабочим процессом;
- просто утечка.
Можно загрузить приложение SinsOfMemoryLeaks, которое поможет определить, где происходит утечка.
В ветке Leak будут видны причины утечки памяти. Это приложение можно также запустить на устройстве или эмуляторе и использовать вышеупомянутые инструменты для отслеживания утечек. В ветке FIXED
можно увидеть советы, как исправить утечки. После исправления процедуру можно повторить заново, чтобы окончательно убедиться в том, что утечки исправлены. Каждая из веток приложения имеет разные идентификаторы приложений, поэтому вы можете установить их на одном устройстве и проверять показания одновременно.
А теперь быстро пройдемся по всем видам утечек.
Утечки памяти, инициируемые статической ссылкой
Статическая ссылка сохраняется до тех пор, пока ваше приложение находится в памяти. У операций есть свои жизненные циклы, которые прекращаются и начинаются во время работы с приложением. Если вы обращаетесь к операции прямо или косвенно со статической ссылки, сборщик мусора не очистит занимаемую память после завершения операции. Память, занимаемая определенной операцией, может варьировать от нескольких килобайт до нескольких мегабайт в зависимости от того, в каком состоянии находится приложение. Если у него большая иерархия представлений или изображения с высоким разрешением, это может привести к утечке большого количества памяти.
Некоторые особенности утечек для этой категории:
- утечка для статического представления;
- утечка для статической переменной;
- утечка при использовании синглтона;
- утечка статического экземпляра внутреннего класса.
Утечки памяти, инициируемые рабочим процессом
Рабочий поток также может работать дольше, чем нужно. Если сделать ссылку на операции прямо или косвенно из рабочего потока, который живет дольше, чем сами операции, это вызовет утечку памяти. Некоторые особенности утечек для этой категории:
- утечка из потока;
- утечка из обработчика;
- утечка из AsyncTask.
Тот же принцип применяется к таким потокам, как thread pool
или ExecutorService
.
Просто утечка
Каждый раз при запуске рабочего потока из операции вы сами отвечаете за управление потоком. Поскольку рабочий поток может работать дольше самой операции, нужно остановить его, когда действие будет прекращено. Если этого не сделать, существует вероятность утечки памяти рабочего процесса. Как в этом репозитории.
Каково влияние конкретной утечки?
В идеале следует избегать написания кода, который может вызвать утечку памяти, и исправить все утечки, существующие в приложении. Но на самом деле, если нужно работать со старой базой кода и определить приоритеты задач, включая исправление утечек памяти, можно оценить степень серьезности в следующих аспектах.
Насколько велика утечка памяти?
Не все утечки памяти одинаковые. Некоторые утечки могут составлять несколько килобайт, а некоторые — несколько мегабайт. Это можно определить, используя инструменты представленные выше и решить, имеет ли размер просочившейся памяти критическое значение для пользовательских устройств.
Как долго длится утечка?
Некоторые утечки через рабочий поток живут до тех пор, пока работает этот поток. В таком случае нужно изучить насколько долго живет этот поток. В примере приложения выше созданы бесконечные циклы в рабочем потоке, поэтому они постоянно держат в памяти объект, порождающий утечку. Но на самом деле большинство рабочих потоков выполняет простые задачи, такие как доступ к файловой системе или выполнение сетевых вызовов, которые либо недолговечны, либо ограничены тайм-аутом.
Сколько объектов в утечке?
В некоторых случаях утечку порождает только один объект, например, один из примеров статических ссылок, показанный в приложении SinsOfMemoryLeaks. Как только будет создано новое действие, оно начнет ссылаться на новую операцию. Старая утечка будет очищена сборщиком мусора. Таким образом, максимальная утечка всегда равна размеру одного экземпляра операции. Однако другие утечки продолжают просачиваться в новые объекты по мере их создания. В примере Leaking Threads активность пропускает по одному потоку каждый раз при его создании. Поэтому, если вы поворачиваете устройство 20 раз, утечка составит 20 рабочих потоков. Это закончится весьма печально, так как приложение заполнит всю доступную память на устройстве.
Как исправить и предотвратить утечки
Посмотрите как происходит устранение типичных утечек памяти в этой ветке репозитория. Решения можно обобщить до следующих пунктов:
- Нужно быть очень осторожными, принимая решение установки статической переменной для рабочего процесса. Это действительно необходимо? Возможно, эта переменная ссылается на процесс напрямую или косвенно (ссылка на объект внутреннего класса, прикрепленный экран и т. д.)? Если да, возможно ли будет очистить отсылку к процессу, используя функцию
onDestroy
? - Если было решено передавать операцию как синглтон или
x-manager
, нужно понимать, что делает другой объект с экземпляром действия. Нужно очистить ссылку (установить в null), если необходимо, используя для этого процесса функциюonDestroy
. - При создании класса внутри процесса, по возможности старайтесь сделать его статическим. Внутренние классы и анонимные классы имеют неявную ссылку на родительский класс. Поэтому, если экземпляр внутреннего/анонимного класса живет дольше, чем родительский класс, могут возникнуть проблемы. Например, при создании анонимного класса
runnable
и передаче его в рабочий поток или класс анонимного обработчика и использования его для передачи задач в другой поток существует риск утечки содержащегося объекта класса. Чтобы избежать риска утечки, нужно использовать статический класс, а не внутренний/анонимный класс. - Если писать синглтон или
x-manager
класс, нужно сохранить ссылку на экземпляр слушателя (англ. «listener»). При этом вы не контролируете, что происходит со ссылкой (удалил ее пользователь класса или нет). В этом случае можно использоватьWeakReference
для создания ссылки на экземпляр слушателя.WeakReference
не мешает сборщику мусора производить свои действия. Хотя эта функция отлично подходит для предотвращения утечек памяти, она также может вызвать побочный эффект, потому что нет гарантии, что ссылочный объект является активным, когда это необходимо. Поэтому рекомендуется использовать его в качестве последнего средства для исправления утечек памяти. - Всегда нужно завершать рабочие потоки, инициированные функцией
onDestroy()
.
Не забудьте проверить примеры кода для типичных утечек памяти и способы их избежания в репозитории на Github.
Источники: «Memory Leak Patterns in Android», «How Garbage Collection Really Works»
Время на прочтение
14 мин
Количество просмотров 84K
В этой статье для начинающих android-разработчиков я постараюсь рассказать о том, что такое «утечки памяти» в android, почему о них стоит думать на современных устройствах, выделяющих по 192МБ на приложение, как быстро найти и устранить эти утечки в малознакомом приложении и на что нужно обращать особое внимание при разработке любого приложения.
Конечная цель этой статьи — ответ на простой вопрос:
Куда нажать, чтобы узнать, какую строчку в приложении поправить?
Что такое «утечка памяти»?
Начнем с того, что же называется «утечкой памяти». В строгом понимании объект можно назвать утечкой памяти, если он продолжает существовать в памяти даже после того, как на него потеряны все ссылки. С этим определением сразу же возникает проблема: память для всех объектов, которые вы создаете, выделяется при участии сборщика мусора, и все созданные объекты сборщик мусора помнит, независимо от того, есть у вас ссылка на объект, или нет.
На самом деле сборщик мусора устроен крайне примитивно (на самом деле нет — но принцип работы действительно простой): есть граф, в котором каждый существующий объект — это вершина, а ссылка от любого объекта на любой другой объект — ребро. Некоторые вершины на этом графе — особые. Это корни сборщика мусора (garbage collection roots) — те сущности, которые созданы системой и продолжают свое существование независимо от того, ссылаются на них другие объекты или нет. Если и только если на графе существует любой путь от данного объекта до любого корня, объект не будет уничтожен сборщиком мусора.
В этом и заключается проблема — если объект не уничтожен, значит существует цепочка ссылок от корня до данного объекта (либо, если такой цепочки не существует, объект будет уничтожен при следующей сборке мусора).А это значит, что ни один объект не может являться утечкой памяти в строгом понимании этого термина. Собственно даже того, что сам сборщик мусора хранит ссылку на каждый существующий объект в системе, уже достаточно.
Попытки получить в java «чистую» утечку памяти предпринимались неоднократно и, безусловно, продолжают предприниматься, однако ни один из способов не способен заставить сборщика мусора забыть ссылку на объект, не освободив память. Существуют утечки памяти, связанные с выделением памяти нативным кодом (JNI), однако в этой статье мы их не будем рассматривать.
Вывод: вы можете потерять все ссылки на интересующий вас объект, но сборщик мусора помнит.
Итак, определение «утечки памяти» в строгом смысле нам не подходит. Поэтому далее будем понимать утечку памяти как объект, который продолжает существовать после того, как он должен быть уничтожен.
Далее я покажу несколько наиболее распространенных случаев утечек памяти, покажу как их обнаруживать и как избегать. Если вы научитесь устранять эти типовые утечки памяти, то с вероятностью 99.9%, в вашем приложении не будет утечек памяти, о которых стоит волноваться.
Но, прежде чем перейти к описанию этих частых ошибок, нужно ответить на главный вопрос: а нужно ли вообще исправлять эти ошибки? Приложение-то работает…
Почему нужно тратить время на устранение утечек памяти?
Приложения уже давно не падают из-за того, что вы забыли пережать ресурсы в папку drawable-ldpi. Готовясь к написанию этой статьи, я провел простой эксперимент: я взял одно из работающих приложений, и добавил в него утечку памяти таким образом, что ни одно создаваемое activity никогда не выгружалось из памяти (стал добавлять их в статический список). Я открыл приложение и начал прокликивать экраны, ожидая, когда же приложение наконец упадет на моем Nexus 5. Наконец, через 5 минут и 55 экранов, приложение упало. Ирония в том, что, по данным Google Analytics, обычно пользователь за сессию посещает 3 экрана.
Так нужно ли волноваться по поводу утечек памяти, если пользователь может их просто не заметить? Да, и есть три причины почему.
Во-первых, если в вашем приложении работает что-то, что работать не должно, это может привести к очень серьёзным и трудно отлаживаемым проблемам.
Например, вы разработали приложение для социальной сети. В этом приложении можно обмениваться сообщениями между пользователями, где на экране обмена сообщениями есть таймер, который делает запрос на сервер каждые 10 секунд с целью получения новых сообщений, но вы забыли этот таймер выключить при выходе с экрана. К чему это приведет визуально? Да ни к чему. Вы не заметите, что приложение делает что-то не то. Но при этом приложение продолжит каждые 10 секунд посылать запрос на сервер. Даже после того, как вы выйдете из приложения. Даже после того, как вы выключите экран (поведение может варьироваться от телефона). Если пользователь зайдет на экраны общения с тремя разными друзьями, в течение часа вы получите 1000 лишних запросов на сервер и одного пользователя, очень рассерженного на ваше приложение, которое усиленно потребляет батарею. Именно такие результаты я получил с тестовым приложением на телефоне с выключенным экраном.
Вы можете возразить, что это не утечка памяти, а всего лишь не выключенный таймер и это совсем другая ошибка. Это неважно. Важно, что проверив свое приложение на наличие утечек памяти, вы найдете и другие ошибки. Когда мы проверяем приложение на наличие утечек памяти, мы хотим найти все объекты, которые существуют, но существовать не должны. Находя такие объекты, мы сразу понимаем, какие лишние операции продолжают выполняться.
Во-вторых, не все приложения потребляют мало памяти, и не все телефоны выделяют много памяти.
Помните про приложение, которое упало только после 5 минут и 55 не выгруженных экранов? Так вот для этого же приложения мне каждую неделю приходит 1-2 отчета о падении с OutOfMemoryException (в основном с устройств до 4.0; у приложения 50.000 установок). И это при том, что утечек памяти в приложении нет. Поэтому даже сейчас вы можете изрядно подпортить себе карму, выложив приложение с утечками памяти, особенно если ваше приложение потребляет много памяти. Как обычно в мире android, от блестящего будущего нас отделяет суровое настоящее.
В-третьих, мужик должен всё уметь! (я же обещал, что все 3 причины будут серьёзные)
Теперь, когда я, надеюсь, убедил вас в необходимости отлавливать утечки памяти, давайте рассмотрим основные причины их появления.
Никогда не сохраняйте ссылки на activity (view, fragment, service) в статических переменных
Один из первых вопросов, с которым сталкивается каждый начинающий разработчик, это как передать объект из одного activity в следующий. Самое простое и самое неправильное решение, которое мне периодически приходится видеть, это запись первого activity в статическую переменную и обращение к этой переменной из второго activity. Это крайне неудачный подход. Не только потому, что он моментально приводит к утечке памяти (статическая переменная продолжит существовать пока существует приложение, и activity, на который она ссылается, никогда не будет выгружен). Этот подход также может привести к ситуации, когда вы будете обмениваться информацией не с тем экраном, ведь экран, невидимый пользователю, может в любой момент быть уничтожен и пересоздан лишь когда пользователь к нему вернется.
Почему же утечка activity — такая большая проблема? Дело в том, что если сборщик мусора не соберет activity, то он не соберет и все view и fragment, а вместе с ними и все прочие объекты, расположенные на activity. В том числе не будут высвобождены картинки. Поэтому утечка любого activity — это, как правило, самая большая утечка памяти, которая может быть в вашем приложении.
Никогда не записывайте ссылки на activity в статические переменные. Используйте передачу объектов через Intent, либо вообще передавайте не объект, а id объекта (если у вас есть база данных, из которой этот id потом можно достать).
Этот пункт также относится к любым объектам, временем жизни которых напрямую или косвенно управляет android. Т.е. к view, fragment, service и т.д..
View и fragment объекты содержат ссылку на activity, в котором они расположены, поэтому, если утечет один единственный view, утечет сразу всё — activity и все view в нём, а, вместе с ними, и все drawable и всё, на что у любого элемента из экрана есть ссылка!
Будьте аккуратны при передаче ссылки на activity (view, fragment, service) в другие объекты
Рассмотрим простой пример: ваше приложение для социальной сети отображает фамилию, имя и рейтинг текущего пользователя на каждом экране приложения. Объект с профилем текущего пользователя существует с момента входа в аккаунт до момента выхода из него, и все экраны вашего приложения обращаются за информацией к одному и тому же объекту. Этот объект также периодически обновляет данные с сервера, так как рейтинг может часто меняться. Необходимо, чтобы объект с профилем уведомлял текущее activity об обновлении рейтинга. Как этого добиться? Очень просто:
@Override
protected void onResume() {
super.onResume();
currentUser.addOnUserUpdateListener(this);
}
Как добиться в этой ситуации утечки памяти? Тоже очень несложно! Просто забудьте отписаться от уведомлений в методе onPause:
@Override
protected void onPause() {
super.onPause();
/* Забудьте про следующую строчку и вы получите серьёзную утечку памяти */
currentUser.removeOnUserUpdateListener(this);
}
Из-за такой утечки памяти activity будет продолжать обновлять интерфейс каждый раз, когда профиль будет обновляться даже после того, как экран перестанет быть видим пользователю. Хуже того, таким образом экран может подписать 2, 3 или больше раза на одно и то же уведомление. Это может привести к видимым тормозам интерфейса в момент обновления профиля — и не только на этом экране.
Что делать, чтобы избежать этой ошибки?
Во-первых, конечно нужно всегда внимательно следить за тем, что вы отписались от всех уведомлений в момент ухода activity в фон.
Во-вторых, вы должны периодически проверять своё приложение на наличие утечек памяти.
В-третьих, есть и альтернативный подход к проблеме: вы можете сохранять не ссылки на объекты, а слабые ссылки. Это особенно полезно для наследников класса View — ведь у них нет метода onPause и не совсем понятно, в какой момент они должны отписываться от уведомления. Слабые ссылки не считаются сборщиком мусора как связи между объектами, поэтому объект, на который существуют только слабые ссылки, будет уничтожен, а ссылка перестанет ссылаться на объект и примет значение null. Чтобы не возиться каждый раз с не очень удобными в использовании слабыми ссылками, вы можете воспользоваться примерно следующим шаблонным классом:
public class Observer<I> {
private ArrayList<I> strongListeners = new ArrayList<I>();
private ArrayList<WeakReference<I>> weakListeners = new ArrayList<WeakReference<I>>();
public void addStrongListener(I listener) {
strongListeners.add(listener);
}
public void addWeakListener(I listener) {
weakListeners.add(new WeakReference<I>(listener));
}
public void removeListener(I listener) {
strongListeners.remove(listener);
for (int i = 0; i < weakListeners.size(); ++i) {
WeakReference<I> ref = weakListeners.get(i);
if (ref.get() == null || ref.get() == listener) {
weakListeners.remove(i--);
}
}
}
public List<I> getListeners() {
ArrayList<I> activeListeners = new ArrayList<I>();
activeListeners.addAll(strongListeners);
for (int i = 0; i < weakListeners.size(); ++i) {
WeakReference<I> ref = weakListeners.get(i);
I listener = ref.get();
if (listener == null) {
weakListeners.remove(i--);
continue;
}
activeListeners.add(listener);
}
return activeListeners;
}
}
Который будет работать примерно вот так:
public class User {
...
public interface OnUserUpdateListener {
public void onUserUpdate();
}
private Observer<OnUserUpdateListener> updateObserver = new Observer<OnUserUpdateListener>();
public Observer<OnUserUpdateListener> getUpdateObserver() {
return updateObserver;
}
}
...
@Override
protected void onFinishInflate() {
super.onFinishInflate();
/* Мы подписываемся на уведомления при создании объекта */
currentUser.getUpdateObserver().addWeakListener(this);
}
/* ... и никогда от этих уведомлений не отписываемся */
...
Да, вы можете получить лишние обновления этого view. Но часто это — меньшее из зол. И, при любом раскладе, утечку памяти вы уже не получите.
Есть только одна тонкость при использовании метода addWeakListener: на объект, который вы добавляете, должен кто-то ссылаться. Иначе сборщик мусора уничтожит этот объект до того, как он получит свое первое уведомление:
/* Не делайте так! */
currentUser.getUpdateObserver().addWeakListener(new OnUserUpdateListener() {
@Override
public void onUserUpdate() {
/* Этот код не будет вызван */
}
});
Таймеры и потоки, которые не отменяются при выходе с экрана
Про эту проблему я уже рассказывал выше: итак, вы разработали приложение для социальной сети. В этом приложении можно обмениваться сообщениями между пользователями, и вы добавляете на экран обмена сообщениями таймер, который делает запрос на сервер каждые 10 секунд с целью получения новых сообщений, но вы забыли этот таймер выключить при выходе с экрана:
public class HandlerActivity extends Activity {
private Handler mainLoopHandler = new Handler(Looper.getMainLooper());
private Runnable queryServerRunnable = new Runnable() {
@Override
public void run() {
new QueryServerTask().execute();
mainLoopHandler.postDelayed(queryServerRunnable, 10000);
}
};
@Override
protected void onResume() {
super.onResume();
mainLoopHandler.post(queryServerRunnable);
}
@Override
protected void onPause() {
super.onPause();
/* Вы забыли написать строчку ниже и в вашем приложении появилась утечка памяти */
/* mainLoopHandler.removeCallbacks(queryServerRunnable); */
}
...
}
К сожалению, эту проблему сложно избежать. Единственные два совета, которые можно дать, будут такими же, как и в предыдущем пункте: будьте внимательны и периодически проверяйте приложение на утечки памяти. Вы также можете использовать аналогичный предыдущему пункту подход с использованием слабых ссылок.
Никогда не сохраняйте ссылки на fragment в activity или другом fragment
Я очень много раз видел эту ошибку. Activity хранит ссылки на 5-6 запущенных фрагментов даже не смотря на то, что на экране всегда виден только 1. Один фрагмент хранит ссылку на другой фрагмент. Фрагменты, видимые на экране в разное время, общаются друг с другом по прямым закешированным ссылкам. FragmentManager в таких приложениях выполняет чаще всего рудиментарную роль — в нужный момент он подменяет содержимое контейнера нужным фрагментом, а сами фрагменты в back stack не добавляются (добавление фрагмента, на который у вас есть прямая ссылка, в back stack рано или поздно приведет к тому, что фрагмент будет выгружен из памяти; после возврата к этому фрагменту будет создан новый, а ваша ссылка продолжит ссылаться на существующий, но невидимый пользователю фрагмент).
Это очень плохой подход по целому ряду причин.
Во-первых, если вы храните в activity прямые ссылки на 5-6 фрагментов, то это тоже самое, как если бы вы хранили ссылки на 5-6 activity. Весь интерфейс, все картинки и вся логика 5 неиспользуемых фрагментов не могут быть выгружены из памяти, пока запущено activity.
Во-вторых, эти фрагменты становится крайне сложно переиспользовать. Попробуйте перенести фрагмент в другое место программы при условии, что он должен быть обязательно запущен в одном activity с фрагментами, x, y и z, которые переносить не надо.
Относитесь к фрагментам как к activity. Делайте их максимально модульными, общайтесь между фрагментами только через activity и fragmentManager. Это может казаться излишне сложной системой: зачем так стараться, когда можно просто передать ссылку? Но, на самом деле, такой подход сделает вашу программу лучше и проще.
По этой теме есть отличная официальная статья от Google: «Communicating with Other Fragments». Перечитайте эту статью и никогда больше не сохраняйте указатели на фрагменты.
Обобщённое правило
После прочтения четырех предыдущих пунктов вы могли заметить, что они практически ничем не отличаются. Все это — частные случаи одного общего правила.
Все утечки памяти появляются тогда и только тогда, когда вы сохраняете ссылку на объект с коротким жизненным циклом (short-lived object) в объекте с длинным жизненным циклом (long-lived object).
Помните об этом и всегда внимательно относитесь к таким ситуациям.
У этого правила нет красивого короткого названия, такого как KISS, YAGNI или RTFM, но оно применимо ко всем языкам со сборщиком мусора и ко всем объектам, а не только к activity в android.
Теперь, когда я, надеюсь, показал основные источники утечек памяти, давайте наконец перейдём к их выявлению в рабочем приложении.
Куда нажать, чтобы узнать, какую строчку в приложении поправить?
Итак, вы знаете как избежать утечек памяти, но это не ограждает вас от опечаток, багов и проектов, которые вы написали до того, как узнали, как избежать утечек памяти.
Для того, чтобы определить наличие и источник утечек памяти в приложении вам потребуется немного времени и MAT. Если вы никогда раньше не пользовались MAT, установите его как plugin к eclipse, откройте DDMS perspective и найдите кнопку «Dump HPROF file». Нажатие на эту кнопку откроет дамп памяти выбранного приложения. Если вы используете Android Studio, то процесс будет немного сложнее, так как на данный момент MAT все ещё не существует как плагин к Android Studio. Поставьте MAT как отдельную программу и воспользуйтесь инструкцией со stackoverflow.
Выполните следующие шаги:
- Установите приложение на устройство, подключенное к компьютеру и попользуйтесь им таким образом, чтобы оказаться на каждом экране как минимум однажды. Если один экран может быть открыт с разными параметрами, постарайтесь открыть его со всеми возможными комбинациями параметров. Вообщем — пройдитесь по всему приложению, как если бы вы проверяли его перед релизом. После того как вы прошли все экраны, нажимайте кнопку «назад» до тех пор, пока не выйдите из приложения. Не нажимайте кнопку home — ваша задача завершить все запущенные activity, а не просто скрыть их.
- Нажмите на кнопку Cause GC несколько раз. Если вы этого не сделаете, в дампе будут видны объекты, которые подлежат уничтожению сборщиком мусора, но ещё не были уничтожены.
- Сделайте дамп памяти приложения нажав на кнопку «Dump HPROF file».
- В открывшемся окне сделайте OQL запрос: «SELECT * FROM instanceof android.app.Activity»
Список результатов должен быть пустым. Если в списке есть хотя бы один элемент, значит этот элемент — это и есть ваша утечка памяти. На скриншоте вы видите именно такой элемент — HandlerActivity: это и есть утечка памяти. Выполните пункты 8-10 для каждого элемента из списка.
- Выполните аналогичные запросы для наследников Fragment: «SELECT * FROM instanceof android.app.Fragment». Как и в предыдущем случае, все, что попало в список результатов — это утечки памяти. Выполните для каждой из них пункты 8-10.
- Откройте histogram. Результаты, отображаемые в histogram, отличаются от результатов, отображаемых в OQL тем, что в histogram отображаются классы, а не объекты. В поле фильтра введите используемый для ваших классов package name (на скриншоте это com.examples.typicalleaks) и отсортируйте результаты по колонке objects (сколько объектов данного класса сейчас существует в системе). Обратите внимание, что в результатах отображаются в том числе и классы, 0 экземпляров которых существовало на момент получения дампа. Эти классы нас не интересуют. Если объектов действительно много — выделите всю таблицу, нажмите правой кнопкой и выберите пункт Calculate Precise Retained Size. Отсортируйте таблицу по полю Retained Heap и рассматривайте только объекты с большими значениями Retained Heap, например больше 10000.
На этот раз далеко не все объекты классов, которые вы видите в списке, являются утечками памяти. Однако все эти классы — это классы вашего приложения, и вы должны примерно понимать, сколько объектов каждого из этих классов должно существовать в данный момент. Например, на скриншоте мы видим 6 объектов класса Example и один массив Example[]. Это нормально — класс Example это enum, его объекты были созданы при первом обращении и будут существовать пока существует приложение. А вот HandlerActivity и HandlerActivity$1 (первый анонимный класс, объявленный внутри файла HandlerActivity.java) — это уже знакомые нам утечки памяти. Нажимаем правой кнопкой на подозрительный класс, выбираем пункт list objects, выполняем пункты 8-10 для одного из объектов из полученного списка.
- Если к этому шагу у вас не набралось ни одного подозрительного объекта — поздравляю! В вашем приложении нет значимых утечек памяти.
- Нажмите правой кнопкой на подозрительный объект и выберите пункт Merge Shortest Paths to GC Roots — exclude all phantom/weak/soft etc. references.
- Раскройте дерево. У вас должна получится примерно следующая картина:
В самом низу вы должны увидеть ваш подозрительный объект. В самом верху — корень сборщика мусора. Все, что посередине — это объекты, соединяющие ваш подозрительный объект с корнем сборщика мусора. Именно эта цепочка и не позволяет сборщику мусора уничтожить подозрительный объект. Читать эту цепочку следует следующим образом: жирным написана переменная объекта выше по списку, в которой содержится ссылка на объект справа от названия переменной. Т.е. на скриншоте мы видим, что переменная mMessages объекта MessageQueue содержит ссылку на объект Message, который содержит переменную callback, ссылающуюся на объект HandlerActivity$1, который содержит ссылку на объект HandlerActivity в переменной this$0. Иными словами, наш подозрительный объект HandlerActivity удерживает первый Runnable, объявленный в файле HandlerActivity.java, так как он добавлен в Handler с помощью метода post или postDelayed. Найдите последний снизу списка класс, который являются частью вашего приложения, нажмите на него правой кнопкой и выберите пункт Open Source File.
- Исправьте код приложения таким образом, чтобы разрушить цепочку между подозрительным объектом и корнем сборщика мусора в тот момент, когда подозрительный объект перестанет быть нужен. В нашем примере нам достаточно вызвать метод Handler.removeCallbacks(Runnable r) в методе onPause HandlerActivity.
- После того, как вы разобрались со всеми подозрительными объектами, повторите алгоритм с шага 1, чтобы проверить, что теперь все работает нормально.
Заключение
Если вы прокликали все экраны в своем приложении и не нашли ни одного подозрительного объекта, то, с вероятностью 99.9%, в вашем приложении нет серьёзных утечек памяти.
Этих проверок действительно достаточно практически для любого приложения. Вас должны интересовать только утечки памяти, действительно способные повлиять на работу приложения. Утечка объекта, содержащего строковый uuid и пару коротких строк — это ошибка, на исправление которой просто не стоит тратить свое время.
Иногда возникает необходимость заряжать телефон в машине, для этого в центральной консоли раньше торчал порт зарядки USB тип А. Но консоль поменяна на раллиартовскую, да и китайский зарядник давно издох.
Внедрил я значит похожий зарядник в подлокотник, там он не мешает, да и задним пассажирам будет доступнее.
Но как обычно где-то я нарукожопил.
Простояла машина несколько дней в гараже и монитор АКБ сказал, что у меня аккумулятор разряжается.
Плохо. Ищем утечку тока.
Фига се, больше ампера! Начал искать что же так сильно потребляет ток и случайно заметил, что зарядка включена даже при вытащенном ключе! Как так-то?
Потом вспоминаем, что тащил туда постоянный плюс, ну и видимо по ошибке к нему и примотался
Жгут взрывать лень, поэтому просто врежем выключатель, такая конструкция то же имеет свои плюсы — при желании даже на выключенном автомобиле можно ткнуть кнопку — и поставить телефон на зарядку. Так и делаем.
Собираем все обратно, выключаем зарядник и проверяем утечку тока.
Другое дело, всего 0.08А. Сигналка и монитор АКБ запитаны постоянно, так что будем считать что это допустимо.
- 10 Ноя 2010
Хотелось бы узнать мнения коллег по данному вопросу. Например, имеем плату телефона после воздействия воды и т.д. Большие токи ищутся моментально — по нагреву. А вот потребление 20-40мА? Батарею высаживает от нескольких часов до 1 дня максимум (имеется в виду потребеление без включения телефона или во включенном состоянии к норм. потреблению добавляется и побочное). Первым делом проверяю все преобразователи напряжений, что запитаны на Vbat, а также стараюсь по одному снимать все подозрительные кондёры по этой же цепи. В последнюю очередь отключаю усилок PA. В большинстве случаев данные операции помогают найти утечку. Но встречаются экземпляры, кот. ни в какую не поддаются. А так же встречаются платы, которые не подвергались «замочке» и тоже имеют малое потребеление тока. Как в данном случае??? Тупо всё снимать по Vbat??
- 10 Ноя 2010
buffer, тема — боян…
Смачиваем ватку или кисточку быстро-испаряющейся жидкостью (эфир, дихлорэтан, смывка флюса из баллончика, ацетон, спирт и т.п.), подаем питание на плату, мажем элементы. Где быстрее испаряется (подсыхает), там и есть локальный нагрев/утечка.
Для совсем, относительно малых токов, берем кусок туалетной бумаги, размачиваем в быстро-испаряющемся растворе и прикладываем на искомый район платы, стараясь при этом примять мокрую бумагу к мелким элементам. Затем после подачи питания созерцаем. При повторе раза три процедуры, место даже малого нагрева локализуется.
- 10 Ноя 2010
Vad, При таких утечках ,как писал автор темы, твой метод не проканает.
Хорошо,если «подкарачивает» кондер — он будет заметно нагреваться.
А как быть с чипами,имеющими хороший теплоотвод?
Передатчик или КП ?
- 10 Ноя 2010
214837, Сегодня на Nokia E52 при помощи бумаги и Flux-off вычислил потребление в 9…10mA на микрухе зарядки (правда и небольшая она). Подмокла маленько через разъем, вот и поджирала ток по плюсу у выключенного.
Ну, передатчик скинуть то недолго. А на больших, можно и при помощи принудительного изменения температуры (то феном горячим, то дустером из балона — охлаждать), при этом плотненько отслеживать ток потребления тела.
- 10 Ноя 2010
Спасибо, попробую… Но всё же хотелось бы уточнить: при токе потребления в 10 — 20мА будет ли виновный элемент нагреваться настолько, чтобы создать испарение летучей жидкости быстрее, чем она испарится естественным путём??? Ведь даже маленький кондёр будет мгновенно охлаждаться платой… Ток то ведь маленький…
- 11 Ноя 2010
buffer, небольшой перепад по температуре как раз и будет заставлять испаряться летучую жидкость немножко поактивнее. Не с первого «прохода» можно заметить, ищется закономерность, статистика. С опытом научишься.
- 12 Окт 2011
У меня проблема с потреблением Samsung I400.
Тел подмочен и потреблял 120 ма в режиме покоя.Я применил следующую методу — прогрев феном (230 грд).На дефектных участках,это конденсаторы,потребление при нагреве резко увеличивалось.Удалось добится снижения потребления до 20 ма в режиме покоя.Дальше не получается.
Попробовал использовать бумагу+спирт покуда безуспешно.Что ещё можно пробовать?
- 13 Окт 2011
cliviy, Ну, раз подмочен… Есть варианты которые подходят для удаления грязи под микросхемами и иногда и под элементами. Для варианта, когда традиционные промывки не помогают и есть большая уверенность, что ноги и вывода не сгнили.
1 — Используем эффект быстрого испарения. Эдакую псевдо-кавитацию. Заливаем например, FLUX-OFF на очищаемый участок и либо при помощи фена с горячим воздухом через самую тонкую насадку или баллончика с Дустером, резко выдуваем быстроиспаряющуюся жидкость.
2 — Обильно заливаем проблемный участок качественным, безотмывочным флюсом (например FluxPlus), и при помощи нижнего подогрева и фена заставляем его «кипеть». Потом остатки обязательно смываем, желательно при помощи УЗВ. Не один КП N2200 так промыл в Nokia C7-00, а он там еще и в кожухе…
- 13 Окт 2011
А если тупо отсоединять потребителей тока и мерить? Все постоянные потребители часто соединены через дроссели и резисторы.
- 13 Окт 2011
Vad сказал(а):
cliviy, Ну, раз подмочен… Есть варианты которые подходят для удаления грязи под микросхемами и иногда и под элементами. Для варианта, когда традиционные промывки не помогают и есть большая уверенность, что ноги и вывода не сгнили.
1 — Используем эффект быстрого испарения. Эдакую псевдо-кавитацию. Заливаем например, FLUX-OFF на очищаемый участок и либо при помощи фена с горячим воздухом через самую тонкую насадку или баллончика с Дустером, резко выдуваем выдуваем быстроиспаряющуюся жидкость.
2 — Обильно заливаем проблемный участок качественным, безотмывочным флюсом (например FluxPlus), и при помощи нижнего подогрева и фена заставляем его «кипеть». Потом остатки обязательно смываем, желательно при помощи УЗВ. Не один КП N2200 так промыл в Nokia C7-00, а он там еще и в кожухе…
Спасибо за помощь!
Всё дело в том что потребление остаётся при переходе в спящий режим и к тому времени невозможно определить место нагрева при потреблении 20 ма.Это дело случая.Снимаю потихоньку конденсаторы.
- 15 Окт 2011
Есть одна метода
Так, по секрету…
Надо:
1 фен, с тонкой насадкой,
2 цешка
3 плата
Как:
1 цепляем цешку к клеммам питалова платы + и — в режиме измерения падения напряжения на диодах (режим прозвонки диодов)
2 смотрим на показания
3 дуем тонкой струёй горячего воздуха на микрухи и отслеживаем при нагреве какого места начинает резко падать напряжение перехода.
Вот, в принципе, и всё. локализация с точностью до размера сопла фена
PS естественно дуем на элементы не подряд, а поднося и отводя сопло фена, чтоб плата не нагревалась, а происходил только локальный нагрев.
- 15 Окт 2011
Mishael4444 сказал(а):
Есть одна метода
![]()
Так, по секрету…![]()
Надо:
1 фен, с тонкой насадкой,
2 цешка
3 плата
Как:
1 цепляем цешку к клеммам питалова платы + и — в режиме измерения падения напряжения на диодах (режим прозвонки диодов)
2 смотрим на показания
3 дуем тонкой струёй горячего воздуха на микрухи и отслеживаем при нагреве какого места начинает резко падать напряжение перехода.
Вот, в принципе, и всё.локализация с точностью до размера сопла фена
PS естественно дуем на элементы не подряд, а поднося и отводя сопло фена, чтоб плата не нагревалась, а происходил только локальный нагрев.
Напиши по-русски:что в твоём жаргоне означает «цешка»?
- 15 Окт 2011
cliviy сказал(а):
Напиши по-русски:что в твоём жаргоне означает «цешка»?
Кажется у всех ремонтников «цешка» — это «мультиметр сегодня».
Добавлено 15.10.2011 20:28
- 15 Окт 2011
214837 сказал(а):
Напиши по-русски:что в твоём жаргоне означает «цешка»?
Кажется у всех ремонтников «цешка» — это «мультиметр сегодня».
Добавлено 15.10.2011 20:28
«Железная» логика.Не один десяток лет работаю но услышал первый раз.Очень созвучно с…даже в голову не приходит с чем.
Были когда то авометры с буквой Ц .
Офтоп.Извените.
- 15 Окт 2011
послушай уважаемый этот прибор так называют уже наверно лет пятьдесят, и любой мастер (тем более если он работает не один десяток лет) уж обязательно знаком с таким выражением
- 16 Окт 2011
cliviy сказал(а):
«Железная» логика.Не один десяток лет работаю но услышал первый раз
- 16 Окт 2011
cliviy сказал(а):
Не один десяток лет работаю но услышал первый раз.
Работаете КЕМ ?
ссылка скрыта от публикации
Все » Профессиональные » Электрика и электроника »
Цешка — портативный электроизмерительный прибор. Как правило, это мультиметр.
- 16 Окт 2011
хорош мастеор не правда ли ребят?
наверно он пользуется супер аппаратурой которая нам еще не известна
очень извиняюсь за оффтоп, но сдержаться не смог уж больно до смешного доходит!
если такие мастера будут на смену нам, то миру пи…..ец
- 17 Окт 2011
Да ладно цепляться, ну свежий мастер, не знает всех жаргонов.
Мне вот интересно узнать, кто-нибудь ещё из форумчан, кроме меня, догадался до такого способа? Или только я до него додумался? Типа ноухау?
Если кто додумался отпишитесь плиз, пожму руку
- 17 Окт 2011
когда ищу кондюки подтекающие, грею не феном а жалом паяла каждый кондюк и слежу за потреблением тока.
- 17 Окт 2011
Ну в принципе, что ток отребления отслеживать, что падение напряжения — почти всё одно, за исключением того что, при резком изменении напряжения падения на 10-20 мВ изменение тока потребления не отследишь. И кондер (керамику) при поданном питании коротнуть более опасно чем при подключенном тестере.
Так что, думаю, мой вариант безопасней и более чувствителен при малых изменениях показаний. Хотя они и очень схожи.
- 17 Окт 2011
Mishael4444, завтра попробую, есть подопытный
- 17 Окт 2011
vaso5 сказал(а):
Mishael4444, завтра попробую, есть подопытный
![]()
Красный щуп на «землю» аппарата, черный на Vbat и ффперёт!
При нагреве некоторых нормальных элементов показания тоже будут немного гулять (при нагреве всегда в минус).
Для полноты ощущений за отправную точку можно взять такой же, но полностью исправный девайс, понагревать, чтоб понять динамику изменений на исправном аппарате.
- 19 Окт 2011
Иногда в поиске — когда не помог вариант с испарением- применяю «термометр» от MY 62, но долго и муторно-но помогало несколько раз.
- 26 Янв 2012
Впечатлило ссылка скрыта от публикации
Развитие технологий заставляет владельцев гаджетов задумываться о самых разных вещах. Например, о передаче личных данных со смартфона. Специалисты и умельцы из сети предлагают самостоятельно узнать не только об утечке информации, но и о том, куда отправляются данные.
Содержание
- Кто может шпионить, и зачем это нужно
- Признаки похищения информации с телефона
- Самые популярные способы похищения личных данных с телефона или смартфона
- Как найти и деактивировать шпионские программы на смартфоне
Кто может шпионить, и зачем это нужно
Интернет предоставляет все возможности узнать личную информацию о любом человеке. В качестве шпионов могут быть:
- Родные люди или друзья. Они имеют доступ к телефону, а приложения позволяют без труда скачать или посмотреть личные фото, выявить координаты нахождения на местности, прослушать разговоры, увидеть переписку.
- Хакеры и мошенники. Для них важна информация о кодовых словах, пин-кодах карточек и пр.
- Сотрудники специальных служб. Этим организациям важна переписка, телефонные разговоры, фотографии и пр.
Современные мобильные устройства снабжены множеством датчиков, которые позволяют контролировать каждый шаг владельца. Опытный хакер без труда получит доступ к смартфону, отследит приложения, которые применяет пользователь, получит распечатку разговоров, СМС, переписки в мессенджерах.
Признаки похищения информации с телефона
Распознать утечку личных данных несложно. Если смартфон заражен приложением для передачи информации, он ведет себя определенным образом. Обнаружив один из перечисленных признаков, необходимо срочно принимать меры по защите информации:
- Зависание или «торможение» гаджета. Явное замедление телефона без видимых причин (поломки, перегрузки приложениями) – еще один признак заражения шпионским ПО.
- Увеличение суммы оплаты за интернет. Подгружая программу в гаджет, хакеры не беспокоятся об оплате – за все заплатит владелец смартфона.
- Наличие входящих/исходящих звонков, СМС на незнакомые номера.
- Активность в мессенджерах или социальных сетях без присутствия владельца.
- Быстрая разрядка батареи. Смартфон может разряжаться в состоянии покоя, когда владелец не запускает программы, приложения, не делает звонков.
Иногда телефон быстро разряжается из-за скопления мусорных файлов, вирусов. Чтобы убедиться, что дело не в шпионской программе, владельцу стоит почистить гаджет от лишних приложений и проверить уровень зарядки.
Самые популярные способы похищения личных данных с телефона или смартфона
Схемы передачи информации отработаны годами. Например, владельцу гаджета может прийти СМС с сообщением о выигрыше. Чтобы получить приз, предлагают перейти по активной ссылке. Так незаметно на телефон закачивают шпионскую программу. И еще несколько вариантов «добровольного» заражения гаджета:
- скачивание приложений с вирусом из неизвестного источника;
- всплывающие окна с предложением ввести личные данные, чтобы не потерять доступ в аккаунт и т.д.;
- предложение воспользоваться Bluetooth для инсталляции программы;
- передача информации через USB-кабель, подключенный к неизвестному источнику для зарядки батареи (ноутбук, планшет);
- утечка информации через подключенный Wi-Fi;
- наличие информации в облачном сервисе (хакеры легко взламывают пароли и получают доступ ко всем программам устройства).
В телефонах на платформе Android, выпущенных до февраля 2020 года может быть встроен баг, который используют хакеры. Достаточно включить на смартфоне Bluetooth, чтобы мошенник моментально скачал всю личную информацию. Чтобы не допустить утечки, необходимо обновить платформу.
Как найти и деактивировать шпионские программы на смартфоне
Далеко не каждое шпионское приложение создано с целью кражи финансов, многие нужны для установки места нахождения жертвы, слежки за активностью, перепиской и пр. Обнаружить на своем смартфоне ненужное приложение довольно легко:
- Просмотреть все приложения. Возможно, хозяина ждет неприятный сюрприз, и он найдет программу, которую не устанавливал.
- На телефоне есть программа для экономии заряда батареи или приложение для фонарика. Оба ПО идеально подходят для целей хакеров, смартфон придется почистить.
- Если телефон тормозит после инсталляции новой игры, возможно, она заражена вирусом для передачи информации.
Чтобы исключить риск заражения гаджета вредоносными программами, не стоит:
- переходить по ссылкам в СМС;
- подключаться к чужим сетям Wi-Fi;
- заряжать смартфон через USB кабель от неизвестных источников.
- необходимо контролировать список исходящих и входящих вызовов.
Для деактивации шпионской программы удаляют чужие приложения, блокируют неизвестные номера и обязательно устанавливают антивирус. Антивирусы для мобильников дополнены словом mobile. Эти программы намного легче, чем для ПК, планшетов и других гаджетов, но поддерживают полноценный функционал, обеспечивают качественную защиту мобильника от взлома, передачи личной информации.
Удаление программы может занять время, причем удалять нужно не только ярлык, но и наполнение ПО. Это удобнее делать в настройках смартфона, выбирая нужную программу и удаляя ее с телефона без остатка. Вторая проблема – обнаружение троянов. Этот вирус сложно увидеть простому антивируснику. Выход – прокачать все программы мобильника через стационарный ПК с мощным антивирусом и удалить вредоносное ПО. В некоторых случаях потребуется «откатка» гаджета на заводские настройки – это точно «убьет» всевозможные шпионские программы.
Крайне важно следить за чистотой всех скачиваемых приложений, не доверять свой телефон малознакомым людям и своевременно проверять его на вирусы, чистить от мусора.
Оцените качество статьи. Нам важно ваше мнение: