2009-12-22 2 views
29

У меня есть несколько вопросов относительно объектов и памяти Bitmap и их общей таксономии.Растровые изображения в Android

  1. Что такое встроенное растровое изображение в памяти?
  2. Как память битмапа отличается от памяти кучи?

ответ

33

Память, поддерживает объект Bitmap выделяется с использованием нативного кода (malloc()), а не Java new ключевого слова. Это означает, что память управляется непосредственно ОС, а не Dalvik.

Единственная реальная разница между кучей навалов и кучей Dalvik заключается в том, что куча Dalvik - это сбор мусора, а родной - нет.

Для этих целей, однако, здесь нет большой разницы. Когда ваш объект Bitmap получает сбор мусора, он деструктор будет перерабатывать связанную память в нативной куче.

Источник:

+0

Знаете ли вы, что эта ошибка была исправлена? В настоящее время я сталкиваюсь с той же проблемой на болте гром. Я перерабатываю растровые изображения, но они никогда не очищают какое-либо место на родной куче, вызывая ошибки oom. –

+5

Просто для ясности, приведенный выше ответ верен для версии Android 2.x и ниже. Начиная с Android 3, экземпляры растровых изображений возвращают счетчик в кучу. Это можно легко проверить: создание растрового изображения в android 2.x приведет к тому, что размер кучи Java будет довольно интуитивно, а его создание в Adnroid 3.x добавит много байтов в кучу Java. –

+0

Ах! так что вы говорите, что подсчет теперь намного интуитивно понятен? Это здорово - за исключением всех нас, кто написал хакерский код, чтобы суммировать кучу android с родной кучей ... –

32

Существует важная тонкость: хотя Растровые пикселей выделяются в родной куче, некоторые специальные приемы в Dalvik причины это должно быть учтено против кучи Java. Это делается по двум причинам:

(1) Для управления объемом памяти приложение распределяет это. Без учета приложение может выделять огромное количество памяти (так как сам объект Bitmap очень мал, но может удержаться на произвольно большой объем встроенной памяти), выходящий за пределы 16-мегабайтного или 24-мегабайтного кучи.

(2) Чтобы определить, когда в GC. Без учета вы могли бы выделять и выпускать ссылки на 100 объектов Bitmap; GC не будет работать, потому что эти объекты являются крошечными, но на самом деле они могут представлять собой большое количество мегабайт фактических распределений, которые теперь не GCed своевременно. Учет этих распределений против кучи Java, сборщик мусора будет работать, поскольку он считает, что память используется.

Обратите внимание, что во многих отношениях это деталь реализации; очень вероятно, что он может измениться в будущем, хотя это основное поведение останется в той или иной форме, поскольку они являются важными характеристиками для управления распределением битмапа.

+1

Даже на телефонах, которые подсчитывают растровые изображения в куче java, собственный malloc может выделить WAY более 16 MiB. –

+10

Первый комментарий неправильный, все номера телефонов подсчитывают растровые распределения против предела кучи Dalvik. Главное изменение, которое следует знать, это то, что с Android 3.0 распределения фактически выполняются в куче Dalvik, поэтому вам больше не придется иметь дело с ситуациями, когда GC не будет работать так агрессивно, как должно. – hackbod

+2

Вы правы в этот момент. Тем не менее, GC отстает, когда дело доходит до обработки переработанных растровых изображений. Я обнаружил непредсказуемое поведение, если я вручную не запускаю GC после повторного использования растрового изображения (включая тенденцию к следующей «нагрузке»), чтобы вернуть копию переработанного растрового изображения вместо фактической загрузки его с диска) –

12

От развертывания в дикой природе, я нашел следующие устройства:

  • устройств, которые ограничивают до 16 Мбайт Явы кучи (растровые изображения практически неограниченны).
  • Устройство, которые ограничивают до 16 Мбайт (Java из кучи + родное хранение растровых изображений)
  • Устройства, которые ограничивают до 24 Мбайт Явы кучи (растровые изображения практически без ограничений).
  • Устройство, которые ограничивают до 24 Мбайт (Java из кучи + родное хранение растровых изображений)

24 МиБ имеет тенденцию быть высоким разрешением устройств, и может быть обнаружено с Runtime.getRuntime() maxMemory.(). Также есть 32-мегабайтные устройства, а некоторые из корневых телефонов по умолчанию имеют 64MiB. Раньше я несколько раз путал себя, пытаясь понять, что происходит. Я думаю, что все устройства подсчитывают растровые изображения в пределе кучи. Но очень сложно сделать какие-либо широкие обобщения об андроидном флоте.

Это ОЧЕНЬ неприятная проблема на Android и очень запутанная. Этот предел и его поведение плохо документированы, сложны и крайне неинтуитивны. Они также различаются в разных устройствах и версиях ОС и имеют несколько известных ошибок. Частью проблемы является то, что пределы не точны - из-за фрагментации кучи, вы попадете в OOM задолго до фактического предела и должны консервативно оставить мега или два буфера. Хуже того, у меня есть несколько устройств, где есть собственный segfault (100% ошибка в самом Android), которая возникает до того, как вы получите исключение Java OOM, что делает его вдвойне важным никогда не достигать предела, поскольку вы даже не можете поймать родной аварии. За более подробной информацией о моих расследованиях обращайтесь к this post. В том же сообщении я объясняю, как измерить использование против лимита и избежать сбоев.

Размер кучи java - это Runtime.getRuntime(). TotalMemory().

Нет простого способа измерения размера собственного растрового хранилища. Общая нативная куча может быть измерена с помощью Debug.getNativeHeapAllocatedSize(), но только растровые изображения подсчитываются до предела (я думаю).

+0

Поскольку каждый может выпускать собственную версию Android, кажется вполне правдоподобным, что там могут быть версии, которые реализуют разные политики для ограничения памяти кучи, включая те, которые вы описали выше. Например, CyanogenMod позволяет пользователям самостоятельно устанавливать ограничение кучи, поэтому я не понимаю, почему не может быть выпущена ОС, которая реализует политики, касающиеся ограничений, которые вы описываете. Мне было бы интересно узнать, есть ли в этом отношении какие-либо официальные руководящие принципы. Если нет, то мы подчиняемся прихотям этих вариантов ОС. – Carl

+0

@ Карл.Из того, что я могу сказать, это чистый хаос. Хотя в целом моды и корневые телефоны имеют тенденцию увеличивать пределы кучи, обычно до 64M. Решение о столь жестком ограничении размера кучи Java было мертвым с мертвой точки и привело к ужасному опыту пользователя. –

+0

Это заставляет нас как разработчиков внимательно смотреть на наше использование памяти. В настоящее время я разрабатываю приложение с очень большим набором данных, которое * должно * полностью находиться в куче (из-за интенсивного процесса поиска), а моя первоначальная реализация на основе массива String занимает 15 МБ кучи только для этих данных (каждый String ref в массиве принимает 32 байта данных). После того, как мы достигли предела 24 МБ, который все еще налагает множество текущих устройств, я разработал настраиваемую структуру данных, которая занимает всего 3,5 МБ для хранения точно такой же информации. Теперь мое приложение будет работать даже на устройстве с пределом 16 МБ. – Carl

-1

Мы можем увеличить размер кучи, используя android:largeheap="true" в вашем файле манифеста. Это решит вашу проблему.

+0

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

Смежные вопросы