Domanda

sto usando ByteBuffers E FileChannels per scrivere dati binari in un file.Quando lo faccio per file di grandi dimensioni o successivamente per più file, ottengo un file OutOfMemoryError eccezione.Ho letto altrove che using Bytebuffers con NIO non funziona e dovrebbe essere evitato.Qualcuno di voi ha già affrontato questo tipo di problema e ha trovato una soluzione per salvare in modo efficiente grandi quantità di dati binari in un file in Java?

È l'opzione jvm -XX:MaxDirectMemorySize la strada da percorrere?

È stato utile?

Soluzione

Direi di non creare un enorme ByteBuffer che contenga TUTTI i dati contemporaneamente.Crea un ByteBuffer molto più piccolo, riempilo con i dati, quindi scrivi questi dati nel FileChannel.Quindi reimpostare ByteBuffer e continuare finché non vengono scritti tutti i dati.

Altri suggerimenti

Dai un'occhiata a Java Buffer di byte mappati, noti anche come "buffer diretti".Fondamentalmente, questo meccanismo utilizza il sistema di paging della memoria virtuale del sistema operativo per "mappare" il buffer direttamente sul disco.Il sistema operativo gestirà lo spostamento dei byte da/verso il disco e la memoria in modo automatico e magico, molto rapidamente e non dovrai preoccuparti di modificare le opzioni della tua macchina virtuale.Ciò ti consentirà anche di sfruttare le prestazioni migliorate di NIO rispetto al tradizionale i/o basato su flusso Java, senza strani hack.

Gli unici due problemi che mi vengono in mente sono:

  1. Su un sistema a 32 bit, sei limitato a poco meno di 4 GB totale per tutti i buffer di byte mappati.(Questo è in realtà un limite per la mia applicazione e ora utilizzo architetture a 64 bit.)
  2. L'implementazione è specifica della JVM e non è un requisito.Utilizzo la JVM di Sun e non ci sono problemi, ma YMMV.

Kirk Pepperdine (un guru delle prestazioni Java piuttosto famoso) è coinvolto in un sito Web, www.JavaPerformanceTuning.com, che contiene ulteriori dettagli MBB: Suggerimenti sulle prestazioni NIO

Se accedi ai file in a moda casuale (leggi qui, salta, scrivi lì, torna indietro) allora hai un problema ;-)

Ma se scrivi solo file di grandi dimensioni, dovresti sul serio considerare l'utilizzo dei flussi. java.io.FileOutputStream può essere utilizzato direttamente per scrivere file byte dopo byte o racchiuso in qualsiasi altro flusso (ad es. DataOutputStream, ObjectOutputStream) per comodità di scrivere float, int, stringhe o anche oggetti serializzabili.Esistono classi simili per leggere i file.

I flussi ti offrono la comodità di manipolare file arbitrariamente grandi in una memoria (quasi) arbitrariamente piccola.Sono il modo preferito per accedere al file system nella stragrande maggioranza dei casi.

Usando il trasferito da dovrebbe aiutare in questo, presupponendo che tu scriva sul canale in modo incrementale e non tutto in una volta, come sottolineano anche le risposte precedenti.

Ciò può dipendere dal fornitore e dalla versione JDK specifici.

È presente un bug in GC in alcune JVM Sun.La carenza di memoria diretta non attiverà un GC nell'heap principale, ma la memoria diretta è bloccata dai ByteBuffer diretti in spazzatura nell'heap principale.Se l'heap principale è quasi vuoto, molti non verranno raccolti per molto tempo.

Questo può bruciarti anche se non stai utilizzando i buffer diretti per conto tuo, perché la JVM potrebbe creare buffer diretti per tuo conto.Ad esempio, la scrittura di un ByteBuffer non diretto su un SocketChannel crea un buffer diretto nascosto da utilizzare per l'operazione I/O effettiva.

La soluzione alternativa consiste nell'utilizzare personalmente un numero limitato di buffer diretti e conservarli per il riutilizzo.

Le due risposte precedenti sembrano abbastanza ragionevoli.Per quanto riguarda il funzionamento dell'opzione della riga di comando, dipende dalla velocità con cui l'utilizzo della memoria raggiunge il limite.Se non disponi di RAM e memoria virtuale sufficienti per almeno triplicare la memoria disponibile, dovrai utilizzare uno dei suggerimenti alternativi forniti.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top