Есть ли утечка памяти в библиотеке Android ZXing?

Я написал приложение для Android, используя библиотеку ZXing, и получаю ошибку java.lang.OutOfMemoryError.

Во-первых, я был уверен, что ошибка на моей стороне, поэтому я использовал Eclipse Memory Analyzer (MAT) в соответствии с Патриком Дюброем Google I/O 2011: управление памятью для приложений Android и несколько других руководств по отслеживанию утечек памяти, например Утечки памяти Android ИЛИ различные способы утечки.

В MAT я обнаружил, что со временем сотни экземпляров com.google.zxing.common.BitMatrix заняли большую часть моей динамической памяти.

Удивительно, но я столкнулся с той же проблемой в оригинальной тестовой программе ZXing "CaptureActivity"!

После некоторого расследования я понял, что ссылка на активность в классе DecodeHandler может помешать сборщику мусора освободить класс BitMatrix. Но у меня слишком мало опыта, чтобы это проверить. Более того, я удивлен, обнаружив эту проблему в оригинальной библиотеке ZXing (версия 2.1).

Может ли кто-нибудь воспроизвести это явление или сталкивался с ним раньше?


person Thassilo    schedule 05.06.2013    source источник
comment
Я никогда не видел доказательств утечки памяти и не могу придумать место, где будет храниться ссылка. Откуда это показывает, что на них ссылаются?   -  person Sean Owen    schedule 05.06.2013
comment
Как это связано с этим вопросом?   -  person Sean Owen    schedule 05.06.2013


Ответы (2)


Я думаю, вы на правильном пути. Вам нужно продолжать просматривать профиль кучи MAT, чтобы определить, какая часть пользовательского кода содержит ссылки на DecodeHandler и транзитивно на BitMatrix. Старайтесь отслеживать входящие ссылки из BitMatric, вычислять деревья доминаторов и проверять подозреваемых в утечке.

Попробуйте профилировать приложение, чтобы увидеть, какая часть кода отвечает за выделение BitMatrix, попробуйте отследить это обратно в код приложения.

Тот факт, что в примере с CaptureActivity возникает та же проблема, может быть вызван неправильным использованием библиотеки, поэтому это не обязательно доказывает, что в библиотеке происходит утечка памяти. Например, библиотеку можно было обновить, а пример оставить прежним.

person Aleš    schedule 05.06.2013

Я обнаружил ту же проблему (в версии 2.3 ZXing), работающую на эмуляторе Android (версия Intel). Основная причина оказалась следующей: в методе selectBestPatterns класса FinderPatternFinder выдается NotFoundException, когда не найдено допустимого (QR) шаблона поиска. Это исключение перехватывается методом decodeInternal класса MultiFormatReader. Таким образом, это исключение пропускает нормальный возврат нескольких вызовов метода. Я обнаружил, что из-за этого "исключительного возврата" экземпляр FinderPatternFinder не освобождается, а этот экземпляр, в свою очередь, удерживает ссылку BitMatrix, которая использует довольно много памяти. Звучит безумно, и я не думаю, что это соответствует спецификации Java, поэтому я называю это ошибкой в ​​эмуляторе. Обходной путь заключается в том, чтобы не полагаться на исключение, сигнализирующее о том, что шаблон поиска не найден. Я сделал это, вернув несколько нулевых результатов при свертывании стека вызовов методов. Это полностью устранило утечку памяти.

person Peter    schedule 04.05.2014
comment
Что ж, если это правда, это действительно ошибка в реализации JVM. Поток управления полностью в порядке и не связан со сборкой мусора. Эти элементы удаляются из стека фреймов; как вы думаете, где они хранятся? если хоть что-то из этого верно, гораздо более вероятно, что эмулируемый JVM GC не может справиться с тем, как быстро обрабатываются кадры, и объявляет OOM только потому, что его поток занял слишком много времени. - person Sean Owen; 04.05.2014
comment
@SeanOwen: эмулированная JVM работает довольно быстро, поскольку она запускает код Intel в быстром виртуальном режиме. Я использовал MAT, чтобы найти, что удерживает элементы вне стека. Он показал элементы, но не то, что их держит. Вы можете видеть в LogCat, как используемая память продолжает расти, пока не будет достигнут предел. - person Peter; 05.05.2014