Я тестирую версию android 3.1, большой вариант heapsize, доступно около 250M памяти.
Я устанавливаю следующий код для запуска, когда я нажимаю кнопку "Тест" в своих приложениях:
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. Существует небольшой тост, который также отображается, когда я нажимаю кнопку, поэтому происходит небольшое количество других действий пользовательского интерфейса.
Это из-за фрагментации или просто ужасная ошибка в коде Bitmap android и/или GC? Или я просто делаю что-то глупое? (Пожалуйста, пусть это будет что-то глупое...)
Есть ли у кого-нибудь обход? Поскольку вышеприведенное является достаточно репрезентативным, что мой код должен делать каждый раз, когда пользователь вызывает его, и сейчас, несмотря на тщательную очистку переменных, он умирает после нескольких применений. (И это уже давно заводило меня орехами!)
[Обновление]
Я подтвердил, что это проблема фрагментации или ошибка gc, так как дамп кучи показывает, что я использую только 5.6M, когда простаивание (без утечек) достигает максимума около 26M во время обработки. (Кроме того, нативная куча остается ниже 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).