Android: OutofMemoryError: размер растрового изображения превышает бюджет виртуальной машины без видимой причины - PullRequest
34 голосов
/ 14 июня 2010

У меня исключение OutOfMemory с галереей JPEG размером более 600x800 пикселей.


Среда

Я использую Gallery с изображениями JPG вокруг600x800 пикселей.

Поскольку мой контент может быть немного сложнее, чем просто изображения, я установил для каждого представления значение RelativeLayout, которое оборачивает ImageView с помощью JPG.

Для того, чтобы «ускорить»«Пользовательский опыт У меня есть простой кэш из 4 слотов, который предварительно выбирает (в цикле) около 1 изображения слева и 1 изображение справа от отображаемого изображения и сохраняет их в 4-слотовом HashMap.

Платформа

Я использую AVD с 256 RAM и 128 Heap Size, с экраном 600x800.Это также происходит с целью Entourage Edge, за исключением того, что на устройстве сложнее отлаживать.


Проблема

Я получаю исключение:

OutofMemoryError: bitmap size exceeds VM budget

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


Странная вещь: не должно быть проблемы с памятью

Чтобы убедиться, что лимит кучи очень далек от того, что мне нужно, я вначале определил фиктивный массив 8 МБ и оставил его без ссылок, чтобы он сразу же отправлялся.Он является членом потока операций и определяется следующим образом:

static { @SuppressWarnings("unused")
byte dummy[] = new byte[ 8*1024*1024 ]; }    

В результате размер кучи составляет почти 11 МБ, и все это бесплатно. Примечание Я добавил этот трюк после того, как он начал падать.Это делает OutOfMemory менее частым.

Теперь я использую DDMS.Непосредственно перед сбоем (не сильно меняется после сбоев), DDMS показывает:

ID  Heap Size   Allocated   Free       %Used    #Objects
1   11.195 MB   2.428 MB    8.767 MB   21.69%   47,156  

А в таблице с подробными данными:

Type  Count  Total Size   Smallest   Largest   Median    Average
free  1,536  8.739MB      16B        7.750MB   24B       5.825KB

Самый большой блок составляет 7,7 МБ.И все же LogCat говорит:

ERROR/dalvikvm-heap(1923): 925200-byte external allocation too large for this process.

Если вы не возражаете против отношения медианы и среднего, можно предположить, что большинство доступных блоков очень маленькие.Однако есть блок, достаточно большой для растрового изображения, это 7,7M.Почему это все еще не достаточно?

Примечание: я записал след кучи.Если посмотреть на объем выделенных данных, то кажется, что выделено не более 2М.Он совпадает с отчетом о свободной памяти от DDMS.


  • Может быть, у меня возникла какая-то проблема, такая как фрагментация кучи?
  • Как мне решить / обойти проблему?
  • Разделяется ли куча всем потокам?
  • Может ли быть так, что я неправильно интерпретирую показания DDMS, и на самом деле нет блока 900K, который можно было бы выделить?Если да, кто-нибудь может сказать, где я могу это увидеть?

Большое спасибо

Мейман

Ответы [ 5 ]

12 голосов
/ 06 июля 2010

Я думаю, что нет ничего особенного в вашем случае.Просто не хватает памяти.Вы не можете иметь несколько 600x800 битовых карт в памяти, они занимают слишком много памяти.Вы должны сохранить их на SD и загрузить в память по требованию.Я думаю, это именно то, что вы делаете.

Одна вещь, которую вы должны знать: DDMS отображает потребление памяти кучи Java.Но есть и собственная память, которая не отображается в DDMS.И растровые изображения, насколько я понимаю, создаются в родной памяти.Так что DDMS - просто плохой инструмент для отслеживания этих проблем с памятью.Вам просто нужно быть уверенным, что вы освобождаете свою память, чтобы изображения собирались сборщиком мусора после того, как они вам больше не нужны.

Сборщик мусора работает по собственному расписанию.Вот почему вы должны вызывать метод Bitmap.recycle () для растровых изображений, которые вам больше не нужны.Этот метод освобождает именно ту нативную память, в которой у вас заканчивается.Таким образом, вы не зависите от GC и можете освободить большой объем памяти как можно скорее.

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

Вотхороший пост о распределении памяти, он может помочь вам копать глубже

5 голосов
/ 01 июля 2010

Не уверен, что это вариант для вас, но вы пробовали суперсэмплинг изображений Странно нехватка памяти при загрузке изображения в растровый объект ?

0 голосов
/ 16 мая 2015

Вопрос был задан в 2010 году, когда Фройо был свежим. С тех пор произошло много всего. До версии 3.0 растровые изображения размещались в JNI. Память не показывается в статистике Dalvik. Это больше не должно быть монолитным. До 2.3 статистика памяти для JNI не была доступна (вызов JNI для растрового декодирования) в logcat. 4,4 эвакуированы больше места. 5.0 большой взрыв ст. Еще в 2010 году Nexus One был high end с объемом менее 300 МБ. Бюджет для приложения был около 16 МБ. В наши дни эта память примерно в 8 раз больше.

0 голосов
/ 13 июня 2014

С тех пор, как я спросил об этом, прошло много времени.

Ответ должен быть разделен на 2 части: Pre-Gingerbread: вы просто используете маленькие картинки, используете субсэмплинг, возможно, одну фотографию размера экрана и надеетесь на хорошее Постарайтесь убедиться, что вы не выделяете крошечные элементы, которые не можете освободить, прежде чем получить растровое изображение. До Ginger память для bmps должна была быть непрерывной, и она не учитывалась в памяти виртуальной машины. Всегда смотрите на logcat. Смотрите лекцию о памяти от Google IO 2011. Поместить имбирь это проще. Начиная с Honeycomb, растровые изображения даже учитываются в вашей области Java. Там нет JNI области. Всегда используйте recycle для растровых изображений, которые вам не нужны. Не ждите GC.

0 голосов
/ 12 июня 2014

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...