Android - полностью очищает память, используемую jni
Я создаю приложение, которое обрабатывает очень большие изображения на стороне jni. И под очень большими изображениями я имею в виду, что почти все доступное ОЗУ устройств распределяется на несколько больших блоков. Проблема в том, что после выделения и освобождения всей этой памяти, тот же объем больше не доступен.
Теперь, ваша первая мысль, вероятно, о том, что здесь явно есть утечка памяти! Ну, похоже, нет. Я проанализировал использование памяти, используя
adb shell dumpsys meminfo (app package)
Вот мои результаты:
До обработки:
Pss Private Private Swapped Heap Heap Heap
Total Dirty Clean Dirty Size Alloc Free
------ ------ ------ ------ ------ ------ ------
Native Heap 19736 19712 12 1268 36864 26663 10200
Dalvik Heap 15201 15176 0 3308 32992 16694 16298
В течение:
Pss Private Private Swapped Heap Heap Heap
Total Dirty Clean Dirty Size Alloc Free
------ ------ ------ ------ ------ ------ ------
Native Heap 889826 889804 8 1252 929792 914480 15311
Dalvik Heap 16769 16744 0 3308 33678 18541 15137
После:
Pss Private Private Swapped Heap Heap Heap
Total Dirty Clean Dirty Size Alloc Free
------ ------ ------ ------ ------ ------ ------
Native Heap 22234 22212 8 1252 45056 28468 16587
Dalvik Heap 16461 16436 0 3308 33871 17573 16298
До и после не совсем то же самое, но я также переключался между действиями, так что есть шум.
Может также случиться так, что после однократной обработки данных больше не будет непрерывного блока памяти, но я все еще не знаю, как этого избежать.
Возможно, я мог бы использовать службу в отдельном процессе для выполнения jni и впоследствии убить процесс, но я не проверял это, поэтому он может не работать. Перезапуск приложения и воссоздание всего backstack, кажется, делают свое дело, хотя сделать его полностью стабильным может быть довольно сложно, это замедлит работу, и я действительно не хочу этого делать.
У кого-нибудь есть идеи получше?
0 ответов
Оказалось, что проблема заключалась в том, что освободившуюся память, по-видимому, нужно было собирать мусором.
Хотя использование вызова meminfo, казалось, означало, что вся память была освобождена, сам вызов запускал сборку мусора. После завершения обработки, но до вызова meminfo память была недоступна.
Мне удалось заставить все работать нормально, позвонив System.gc()
. Я знаю, что это не рекомендуется и, как говорят, это всего лишь предложение системе, но, похоже, это действительно решило проблему.