Почему это утечка памяти

Я столкнулся с библиотекой для обнаружения утечки памяти в Android (Java) под названием LeakCanary, но не могу понять пример утечки памяти. Может кто-нибудь объяснить, как и почему код, показанный в их примере, является утечкой памяти.

class Cat {
}
class Box {
  Cat hiddenCat;
}
class Docker {
  static Box container;
}

// ...

Box box = new Box();
Cat schrodingerCat = new Cat();
box.hiddenCat = schrodingerCat;
Docker.container = box;

а затем они наблюдают переменную schrodingerCat для утечек, которая дает утечку, показанную ниже (что я не знаю, как относиться к вышеуказанному коду).

* GC ROOT static Docker.container
* references Box.hiddenCat
* leaks Cat instance

Любая помощь с объяснением утечки и тем, как обнаружение относится к ней, было бы очень полезно. Также неплохие статьи для начинающих.

Спасибо!

Ответ 1

Во-первых, дайте понять, что такое утечка памяти:

Определение

Утечка памяти - это данные (растровые изображения, объекты, массивы и т.д.) в ОЗУ, которые сборщик мусора (GC) не может освободить, хотя программа больше не нужна.

Пример

Пользователь открывает представление, в котором отображается изображение. Мы загружаем растровое изображение в память. Теперь пользователь выходит из представления, и изображение больше не требуется, и ссылка на него отсутствует из кода. В этот момент GC вступает в действие и удаляет его из памяти. НО, если у нас все еще есть ссылка на него, GC не будет знать, что это нормально для удаления, и он остался бы в ОЗУ, снимая ненужное пространство - aka Утечка памяти.

Кошка в коробке

Скажем, у нас есть объект Cat в нашем приложении, и мы удерживаем его в объекте Box. Если мы удерживаем окно (ссылаемся на объект Box), а в поле находится Cat, GC не сможет очистить объект Cat от памяти.

Докер - это класс, который имеет статическую ссылку на наш ящик. Это означает, что, если мы не аннулируем его или не переустановим значение, Docker будет продолжать ссылаться на Box. Предотвращение использования Box (и внутреннего кота) из памяти GC.

Итак, нужен ли нам Кошка? это все еще актуально для приложения?

Это зависит от разработчика, чтобы решить, как долго нам нужен Cat. LeakCanary и другие диагностические инструменты предполагают возможный утечка памяти. Они думают, что объект (Cat) может быть не нужен больше, поэтому они предупреждают, что это утечка.

Резюме

В этом примере они дают общий сценарий утечки памяти. При использовании Статической ссылки мы не позволяем GC очистить объект. Вы должны прочитать следующее:

* GC ROOT static Docker.container
* references Box.hiddenCat
* leaks Cat instance

as:

  • Объект Cat может больше не использоваться, но GC не был удален из памяти.
  • Причина, по которой объект Cat не был удален, поскольку Box имеет ссылку на него.
  • Причина, по которой объект Box не был удален, заключается в том, что Docker имеет статическую ссылку на него.
  • Статическая ссылка Docker - это ROOT дерева, который вызывает возможную утечку.

Ответ 2

Похоже на экземпляр RefWatcher, используемый для "просмотра переменной schrodingerCat для утечек":

refWatcher.watch(schrodingerCat);

заставляет набор GC-проходов, и если эта ссылка не была собрана во время этих проходов GC, она считается утечкой.

Так как статический Docker.container.hiddenCat хранит привязанную к GC ссылку на объект, первоначально известный как schrodingerCat, он не может быть GC'ed, поэтому, когда вы попросите RefWatcher проверить его. Поэтому он позволяет вам знать, что объект не может быть собран.

Ответ 3

Я предлагаю вам прочитать этот ответ fooobar.com/info/374204/...

Вероятно, это поможет вам понять пример выше.

Вкратце, в вашем примере класс Docker сохраняет ссылку на ящик. Даже когда контейнерная коробка больше не нужна, класс Docker все еще содержит ссылку на нее, тем самым создавая утечку памяти.

Сообщите мне, если это поможет.