Я тестирую на 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 ).