Pregunta

Estoy usando ByteBuffers y FileChannels escribir datos binarios en un archivo.Al hacer esto para archivos grandes o sucesivamente para varios archivos, obtengo un OutOfMemoryError excepción.He leído en otra parte que usar Bytebuffers con NIO está roto y debe evitarse.¿Alguno de ustedes ya se ha enfrentado a este tipo de problema y ha encontrado una solución para guardar de manera eficiente grandes cantidades de datos binarios en un archivo en Java?

es la opción jvm -XX:MaxDirectMemorySize ¿el camino a seguir?

¿Fue útil?

Solución

Yo diría que no cree un ByteBuffer enorme que contenga TODOS los datos a la vez.Cree un ByteBuffer mucho más pequeño, llénelo con datos y luego escriba estos datos en FileChannel.Luego reinicie ByteBuffer y continúe hasta que se escriban todos los datos.

Otros consejos

Echa un vistazo a Java Búfers de bytes asignados, también conocidos como "búferes directos".Básicamente, este mecanismo utiliza el sistema de paginación de memoria virtual del sistema operativo para "mapear" su búfer directamente al disco.El sistema operativo gestionará el movimiento de bytes hacia/desde el disco y la memoria de forma automática, muy rápida, y usted no tendrá que preocuparse por cambiar las opciones de su máquina virtual.Esto también le permitirá aprovechar el rendimiento mejorado de NIO sobre la E/S tradicional basada en flujos de Java, sin ningún truco extraño.

Los únicos dos inconvenientes que se me ocurren son:

  1. En un sistema de 32 bits, está limitado a poco menos de 4 GB total para todos los buffers de bytes asignados.(Ese es en realidad un límite para mi aplicación y ahora la ejecuto en arquitecturas de 64 bits).
  2. La implementación es específica de JVM y no es un requisito.Yo uso la JVM de Sun y no hay problemas, pero YMMV.

Kirk Pepperdine (un gurú del rendimiento de Java algo famoso) participa en un sitio web, www.JavaPerformanceTuning.com, que tiene más detalles de MBB: Consejos de rendimiento de NIO

Si accede a archivos en un moda aleatoria (lee aquí, salta, escribe allí, retrocede) entonces tienes un problema ;-)

Pero si sólo escribe archivos grandes, debería en serio Considere el uso de transmisiones. java.io.FileOutputStream se puede utilizar directamente para escribir un archivo byte tras byte o incluirlo en cualquier otro flujo (es decir, DataOutputStream, ObjectOutputStream) para facilitar la escritura de flotantes, ints, cadenas o incluso objetos serializables.Existen clases similares para leer archivos.

Streams le ofrece la comodidad de manipular archivos arbitrariamente grandes en memoria (casi) arbitrariamente pequeña.Son la forma preferida de acceder al sistema de archivos en la gran mayoría de los casos.

Utilizando el Transferido de El método debería ayudar con esto, suponiendo que escriba en el canal de forma incremental y no todo a la vez, como también señalan las respuestas anteriores.

Esto puede depender del proveedor y la versión de JDK en particular.

Hay un error en GC en algunas JVM de Sun.La escasez de memoria directa no desencadenará un GC en el montón principal, pero la memoria directa está fijada por ByteBuffers directos basura en el montón principal.Si el montón principal está casi vacío, es posible que no se recopilen durante mucho tiempo.

Esto puede quemarlo incluso si no está utilizando buffers directos por su cuenta, porque la JVM puede estar creando buffers directos en su nombre.Por ejemplo, escribir un ByteBuffer no directo en un SocketChannel crea un búfer directo oculto para utilizarlo en la operación de E/S real.

La solución alternativa es utilizar una pequeña cantidad de buffers directos usted mismo y conservarlos para su reutilización.

Las dos respuestas anteriores parecen bastante razonables.En cuanto a si el cambio de línea de comando funcionará, depende de qué tan rápido el uso de la memoria alcance el límite.Si no tiene suficiente RAM y memoria virtual disponible para al menos triplicar la memoria disponible, deberá utilizar una de las sugerencias alternativas que se ofrecen.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top