Ответ 1
В момент, когда mmap()
завершается сбой, откройте /proc/self/maps
и скопируйте содержимое в файл temp, затем просмотрите файл в редакторе. Вы должны увидеть кучу записей вроде этого:
12e01000-42c00000 ---p 00201000 00:04 11639 /dev/ashmem/dalvik-main space (deleted)
55281000-5d500000 r--s 00000000 00:16 61 /storage/sdcard1/blah
5d500000-67e80000 rw-p 00000000 00:00 0 [anon:libc_malloc]
67ea4000-682cc000 r-xp 00000000 b3:17 114807 /system/vendor/lib/libsc-a3xx.so
682cc000-682f4000 r--p 00427000 b3:17 114807 /system/vendor/lib/libsc-a3xx.so
Числа слева представляют собой диапазоны виртуальных адресов (начало/конец) для процесса. Когда вы создаете новое сопоставление, оно должно соответствовать пробелу между отображениями.
В приведенном выше примере есть хороший большой промежуток между концом первой записи в 0x42c00000 и началом следующего в 0x55281000. Это около 294 МБ. Между двумя соседями нет места, и только после этого.
Если вы посмотрите на карту процессов и не найдете достаточно большого пробела для хранения вашего файла, у вас есть свой ответ. Область между 0x00000000 и 0xbfffffff обычно доступна для 32-разрядных приложений, но инфраструктура приложения использует ее много. (Верхняя 1 ГБ отображается на ядро.)
Я предполагаю, что некоторая комбинация ASLR и изменения в том, как виртуальная память распределена в Lollipop, привели к этой проблеме. На карте, прикрепленной к этому аналогичному вопросу, наибольший разрыв был около 300 МБ. Есть два больших "далвика" региона, один 768 МБ (на 12e01000), один 1,2 ГБ (на 84d81000). (Так как вы используете Lollipop, это на самом деле связано с ART, а не с Dalvik, но, по-видимому, этот ярлык застрял.)
Одна из возможностей заключается в том, что у АРТ более высокие требования к виртуальной памяти, чем у Dalvik, и большие ассигнования затрудняют приложения для получения областей с крупными картами. Также возможно, что АРТ чрезмерно распределяется из-за ошибки. Вы можете протестировать на Marshmallow, чтобы убедиться, что что-то исправлено.
В любом случае вы не можете создать сопоставление, если область смежных областей виртуальной памяти не будет достаточно большой, чтобы ее удерживать. С использованием рамок приложения и огромными распределениями АРТ, рассмотренными в другом вопросе, сопоставление 768 МБ было бы невозможно, даже если виртуальное адресное пространство не было фрагментировано. Вам нужно будет отобразить меньшие разделы файла и, возможно, отобразить их, когда вы работаете, чтобы освободить место.
Возможно, стоит записать ошибку b.android.com. Прикрепите копию файла карты процесса и укажите версию Android и устройства.
Более подробно об интерпретации /proc/maps output см., например, этот ответ.