Сбой фрагментации памяти Android GC. Обходной путь?

Я тестирую на Android 3.1, большой размер кучи, доступно около 250 МБ памяти.

Я установил следующий код, который будет запускаться всякий раз, когда я нажимаю кнопку «Тест» в настройках моего приложения:

float [][][]foo = new float[3][2048][2048];
Bitmap bm = Bitmap.createBitmap(2048, 2048, Bitmap.Config.ARGB_8888);
bm.recycle();
bm  = null;
foo = null;

У меня достаточно памяти для этого --Я могу нажать кнопку несколько раз без проблем.

Но если я продолжаю нажимать кнопку, в конце концов (менее 20 нажатий )она умирает с OutOfMemory. [Обычно в android.graphics.Bitmap.nativeCreate (Собственный метод )]

Больше ничего не происходит --Мне никогда не приходится выходить из PreferencesActivity. Когда я нажимаю кнопку, также отображается небольшой Toast, поэтому происходит небольшое количество других действий пользовательского интерфейса.

Это связано с фрагментацией или просто ужасной ошибкой в ​​​​коде растрового изображения Android и / или GC? Или я просто делаю что-то глупое? (Пожалуйста, пусть это будет что-нибудь глупое...)

У кого-нибудь есть обходной путь? Потому что приведенное выше довольно точно отражает то, что мой код должен делать каждый раз, когда пользователь вызывает его, и прямо сейчас, несмотря на тщательную очистку переменных, он умирает после нескольких использований. (И это уже давно меня бесит! )

[Обновление]

Я подтвердил, что это проблема фрагментации или ошибка gc, поскольку дамп кучи показывает, что я использую только 5,6 МБ в режиме ожидания (без утечек ), достигая пика около 26 МБ во время обработки. (Кроме того, собственная куча остается меньше 4M. )В то время как куча java тем временем увеличивается в размере до предела 280M на моем тестовом устройстве, после чего я начинаю получать исключения OutOfMemory. Таким образом, я использую только 10% моей доступной кучи на пике, но получаю OutOfMemory.

[Добавление вызова в System.gc (), к сожалению, исправляет простой тестовый пример, который я привел выше. Я говорю неудачный, потому что (A )это не должно иметь значения, и (B ), потому что я уже регулярно вызываю его в своем реальном коде, поэтому это означает, что мой простой тестовый пример выше слишком прост.]

Кто-нибудь еще столкнулся с этим? Любые обходные пути? Есть ли изящный способ перезапустить мое приложение?

[Обновление]

Следующая версия надежно вызывает OutOfMemory за 3-4 вызова (нажатия кнопки):

float [][][]foo = new float[3][2048][2048];
Bitmap bm = Bitmap.createBitmap(2048, 2048, Bitmap.Config.ARGB_8888);
int []bar = new int[3*2048*2048];
bm.recycle();
bm = null;
System.gc();
foo = null;
System.gc();
bar = null;
System.gc();

Трассировка памяти показывает, что куча неуклонно растет при каждом вызове, пока не достигнет предела и не умрет. Если я уберу любое из трех распределений, оно достигнет равновесия и будет существовать бесконечно долго. Удаление всего, кроме последнего gc (), приведет к тому, что он умрет немного раньше.

Я бы сказал, что это проблема фрагментации, а не ошибка gc как таковая. Если кто-нибудь знает, как это исправить, дайте мне знать. Распределение int[] предназначено для записи растрового изображения, поэтому у меня нет возможности выделить его как ограничение 2d-массива (библиотеки растровых изображений Android ).

19
задан Brandyn 23 May 2012 в 22:48
поделиться