Java mmap falla en Android con "mmap failed: ENOMEM (Fuera de memoria)"

Mapeo de memoria de un archivo grande en Android en Java funciona bien. Pero cuando la asignación de más de ~ 1,5 GB en total, incluso con múltiples llamadas de asignación falla con:

mmap failed: ENOMEM (Out of memory) 

Ver la discusión completa aquí . Nota: No falla en un servidor Linux. El androide: largeHeap = "true" está habilitado para la aplicación.

El siguiente código Java se llama unos cientos de veces solicitando ~ 1 MB por llamada:

 ByteBuffer buf = raFile.getChannel().map(allowWrites ? FileChannel.MapMode.READ_WRITE : FileChannel.MapMode.READ_ONLY, offset, byteCount); 

Para evitar la solicitud de un gran trozo de memoria contiguo que a menudo es más difícil de encontrar. Vea el código completo aquí . Tenga en cuenta que duplicar el "tamaño de segmento" (es decir, el tamaño de una sola llamada de mapa) no tiene efecto, lo que significa que se detiene en la posición de memoria similar. También es importante tener en cuenta que 2 aplicaciones con ambos ligeramente por debajo del límite están ejecutando multa (sugiriendo a un límite por proceso).

Las preguntas relacionadas están aquí , aquí , aquí , aquí , aquí , aquí , aquí y aquí .

¿Utilizará varios archivos en lugar de un archivo con varias asignaciones?

He leído que esto podría ser un límite por proceso para el espacio de direcciones virtuales . ¿Dónde puedo encontrar más información sobre esto? ¿Puedo cambiar esta configuración con NDK, por ejemplo, cómo llamar a ulimit ? ¿Podría madvise ayudarme un poco aquí?

Actualizar

Ver mi respuesta aquí para una herramienta mmap utilizable en Java

Su problema es causado por el agotamiento del espacio de direcciones virtuales. Probablemente su problema se reproduce en los dispositivos Android de 32 bits, donde está disponible el espacio de direcciones del usuario físicamente limitado a 2 GB y no puede ser superado. (Aunque puede ser de 3 GB (improbable) y se configura durante el proceso de construcción del SO). Probablemente ~ 500 MB se utiliza para las bibliotecas del sistema, JVM y su montón. Y ~ 1.5 GB está disponible para usted.

La única manera en esta situación IMO – seguir siendo asignado sólo las secciones de archivos que se utilizan realmente ahora y unmap no utilizados tan pronto como sea posible. Puede utilizar algún tipo de ventana deslizante donde sólo una pequeña parte del archivo se asignará a la memoria, y cuando termine – unmap esa parte, avance su posición de la ventana y el mapa de esa ventana actualizada, etc.

También cuando usted mapea el archivo grande entero – su proceso se convierte en una víctima atractiva para el asesino del fuera-de-Memoria del sistema. Porque al leer este archivo mapeado, el consumo de memoria física aumenta y en algún momento el proceso se destruirá.

Como no podemos aumentar el límite de direcciones virtuales en Android a través de una API (que no necesita acceso root), tampoco he visto esto en el código fuente de Android. La única solución posible que veo es implementar un tipo de caché, que mapea segmentos en el acceso y libera segmentos más antiguos si un cierto número de segmentos ya está mapeado. Esto significa que estamos haciendo el trabajo que el sistema operativo normalmente hace para nosotros automáticamente, lo que es un poco feo.

Para hacerlo funcionar bajo Android uno puede usar esta respuesta / util-mmap . Esperemos que alguien pueda implementar una caché de mmap para Android en algún momento, tal vez incluso nosotros 🙂

Intenta agregar largeHeap en tu manifiesto. Puede que funcione

  • Obtenga día, mes y año por separado usando SimpleDateFormat
  • XmlPullParserException función no admitida
  • Pestañas en TabLayout no llenar toda ActionBar
  • No es capaz de crear un proyecto de aplicación android en eclipse.Error Message - Introduzca un nombre de aplicación (mostrado en el lanzador)
  • VideoView no reproduce video o audio en RecyclerView
  • Descargar limitador de velocidad para la interfaz Wifi en Android
  • Posible pérdida de memoria a través de FinalizerReference
  • Gestión de sesiones de Android
  • Creación de una imagen de fondo para la aplicación de Android - Java
  • Mensaje emergente de Android Eclipse con el botón
  • ¿Por qué el tipo primitivo corto es significativamente más lento que largo o int?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.