Растровые изображения в Android

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

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

4 ответа

Решение

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

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

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

Источник:

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

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

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

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

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

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

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

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

Размер кучи Java - Runtime.getRuntime(). TotalMemory().

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

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

Другие вопросы по тегам