Frage

Ich benutze ByteBuffers Und FileChannels um Binärdaten in eine Datei zu schreiben.Wenn ich das für große Dateien oder nacheinander für mehrere Dateien mache, erhalte ich eine OutOfMemoryError Ausnahme.Ich habe das an anderer Stelle gelesen Bytebuffers mit NIO ist kaputt und sollte vermieden werden.Hat jemand von Ihnen bereits ein solches Problem gehabt und eine Lösung gefunden, um große Mengen an Binärdaten effizient in einer Datei in Java zu speichern?

Ist die JVM-Option -XX:MaxDirectMemorySize der Weg, den man gehen sollte?

War es hilfreich?

Lösung

Ich würde sagen, erstellen Sie keinen riesigen ByteBuffer, der ALLE Daten auf einmal enthält.Erstellen Sie einen viel kleineren ByteBuffer, füllen Sie ihn mit Daten und schreiben Sie diese Daten dann in den FileChannel.Setzen Sie dann den ByteBuffer zurück und fahren Sie fort, bis alle Daten geschrieben sind.

Andere Tipps

Schauen Sie sich Java an Zugeordnete Bytepuffer, auch als „direkte Puffer“ bekannt.Grundsätzlich nutzt dieser Mechanismus das Paging-System des virtuellen Speichers des Betriebssystems, um Ihren Puffer direkt auf der Festplatte zu „abbilden“.Das Betriebssystem verwaltet das Verschieben der Bytes auf/von der Festplatte und dem Speicher automatisch und sehr schnell, und Sie müssen sich keine Gedanken über die Änderung der Optionen Ihrer virtuellen Maschine machen.Dadurch können Sie auch die verbesserte Leistung von NIO im Vergleich zu herkömmlicher Java-Stream-basierter E/A nutzen, ohne seltsame Hacks.

Die einzigen zwei Haken, die mir einfallen, sind:

  1. Auf einem 32-Bit-System sind Sie auf knapp 4 GB beschränkt Gesamtwert für alle zugeordneten Bytepuffer.(Das ist tatsächlich eine Grenze für meine Anwendung, und ich verwende jetzt 64-Bit-Architekturen.)
  2. Die Implementierung ist JVM-spezifisch und keine Voraussetzung.Ich verwende Suns JVM und es gibt keine Probleme, aber YMMV.

Kirk Pepperdine (ein einigermaßen berühmter Java-Performance-Guru) ist an der Website www.JavaPerformanceTuning.com beteiligt, die weitere MBB-Details enthält: NIO-Leistungstipps

Wenn Sie auf Dateien in a zugreifen zufällige Mode (hier lesen, überspringen, dort schreiben, zurückgehen) dann hast du ein Problem ;-)

Aber wenn Sie nur große Dateien schreiben, sollten Sie das tun ernsthaft Erwägen Sie die Verwendung von Streams. java.io.FileOutputStream kann direkt verwendet werden, um eine Datei Byte für Byte zu schreiben, oder in einen anderen Stream eingeschlossen werden (z. B. DataOutputStream, ObjectOutputStream), um das Schreiben von Floats, Ints, Strings oder sogar serialisierbaren Objekten zu erleichtern.Ähnliche Klassen gibt es zum Lesen von Dateien.

Streams bieten Ihnen eine bequeme Handhabung Beliebig große Dateien in (fast) beliebig kleinem Speicher.In den allermeisten Fällen sind sie die bevorzugte Methode für den Zugriff auf das Dateisystem.

Verwendung der Übertragen von Methode sollte dabei helfen, vorausgesetzt, Sie schreiben inkrementell in den Kanal und nicht alle auf einmal, wie in früheren Antworten ebenfalls hervorgehoben.

Dies kann vom jeweiligen JDK-Anbieter und der jeweiligen JDK-Version abhängen.

In einigen Sun-JVMs liegt ein Fehler im GC vor.Ein Mangel an direktem Speicher löst keinen GC im Haupt-Heap aus, aber der direkte Speicher wird durch Müll-Direkt-ByteBuffer im Haupt-Heap festgehalten.Wenn der Haupthaufen größtenteils leer ist, kann es sein, dass er lange Zeit nicht gesammelt wird.

Dies kann zu Problemen führen, selbst wenn Sie selbst keine direkten Puffer verwenden, da die JVM möglicherweise in Ihrem Namen direkte Puffer erstellt.Wenn Sie beispielsweise einen nicht direkten ByteBuffer in einen SocketChannel schreiben, wird unter der Decke ein direkter Puffer erstellt, der für den eigentlichen E/A-Vorgang verwendet wird.

Die Problemumgehung besteht darin, selbst eine kleine Anzahl direkter Puffer zu verwenden und diese zur Wiederverwendung aufzubewahren.

Die beiden vorherigen Antworten scheinen ziemlich vernünftig zu sein.Ob der Befehlszeilenschalter funktioniert, hängt davon ab, wie schnell Ihre Speichernutzung das Limit erreicht.Wenn Sie nicht über genügend RAM und virtuellen Speicher verfügen, um den verfügbaren Speicher mindestens zu verdreifachen, müssen Sie einen der angegebenen Alternativvorschläge verwenden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top