Java-Map / nio / NFS-Problem, das einen VM-Fehler verursacht: "Bei einem kürzlich durchgeführten unsicheren Speicherzugriffsvorgang in kompiliertem Java-Code ist ein Fehler aufgetreten"

9

Ich habe eine Parser-Klasse für ein bestimmtes Binärformat geschrieben ( nfdump wenn jemand interessiert ist), die java.nios MappedByteBuffer , um Dateien mit jeweils einigen GB zu lesen. Das binäre Format besteht nur aus einer Reihe von Headern und meist binären Sätzen mit fester Größe, die durch Aufruf von nextRecord () an den Aufrufer ausgegeben werden, der auf den Zustandsautomaten drückt und nach Beendigung NULL zurückgibt. Es funktioniert gut. Es funktioniert auf einer Entwicklungsmaschine.

Auf meinem Produktions-Host kann es einige Minuten oder Stunden lang laufen, aber es scheint immer "java.lang.InternalError: ein Fehler ist aufgetreten in einem kürzlich unsicheren Speicherzugriffsvorgang in kompiliertem Java-Code", Fingersatz eines der Map.getInt, getShort-Methoden, dh eine Leseoperation in der Map.

Der unumstrittene (?) Code, der die Karte einrichtet, ist dies:

%Vor%

und dann benutze ich die verschiedenen map.get * -Methoden, um Kurzschlüsse, Inte, Longs und andere Bytefolgen zu lesen, bevor Sie das Ende der Datei erreichen und die Map schließen.

Ich habe noch nie die Ausnahme auf meinem Entwicklungshost gesehen. Aber der wesentliche Unterschied zwischen meinem Produktions-Host und der Entwicklung besteht darin, dass ich auf der ersten Seite Sequenzen dieser Dateien über NFS lese (wahrscheinlich 6-8 TB, die schließlich noch wachsen). Auf meinem Dev-Rechner habe ich eine kleinere Auswahl dieser Dateien lokal (60 GB), aber wenn es auf dem Produktions-Host explodiert, ist es normalerweise gut, bevor es 60 GB Daten erreicht.

Beide Maschinen laufen mit Java 1.6.0_20-b02, obwohl auf dem Produktions-Host Debian / Lenny läuft, der Dev-Host ist Ubuntu / Karmic. Ich bin nicht überzeugt, dass das einen Unterschied machen wird. Beide Computer verfügen über 16 GB RAM und werden mit den gleichen Java-Heap-Einstellungen ausgeführt.

Ich bin der Ansicht, dass, wenn ein Fehler in meinem Code ist, genug Bug in der JVM vorhanden ist, um mir keine richtige Ausnahme zu geben! Aber ich denke, es ist nur ein bestimmter JVM-Implementierungsfehler aufgrund von Interaktionen zwischen NFS und mmap, möglicherweise eine Wiederholung von 6244515 das ist offiziell festgelegt.

Ich habe bereits versucht, einen "load" -Aufruf hinzuzufügen, um den MappedByteBuffer zu zwingen, seinen Inhalt in den RAM zu laden - dies schien den Fehler in dem einen Testlauf zu verzögern, den ich gemacht habe, aber nicht zu verhindern. Oder es könnte Zufall sein, dass es am längsten war, bevor es zusammenbrach!

Wenn Sie so weit gelesen haben und mit java.nio schon einmal so etwas gemacht haben, was wäre Ihr Instinkt? Gerade jetzt meins ist es ohne nio umzuschreiben:)

    
Matthew Bloch 01.06.2010, 11:36
quelle

1 Antwort

4

Ich würde es ohne Verwendung von zugeordnet NIO umschreiben. Wenn Sie mit mehr als einer Datei arbeiten, gibt es ein Problem, dass der zugeordnete Speicher niemals freigegeben wird, so dass Ihnen der virtuelle Speicher ausgehen wird: NB dies ist nicht notwendigerweise nur ein OutOfMemoryError, der mit dem Garbage Collector interagiert, es wäre ein Fehler beim Zuweisen des neuen zugeordneten Puffers. Ich würde einen FileChannel verwenden.

Allerdings sind großangelegte Operationen mit NFS-Dateien immer extrem problematisch. Es wäre viel besser, wenn Sie das System so umgestalten, dass jede Datei von der lokalen CPU gelesen wird. Sie werden auf diese Weise immense Geschwindigkeitsverbesserungen erhalten, weit mehr als die 20%, die Sie verlieren werden, wenn Sie keine zugeordneten Puffer verwenden.

    
EJP 02.06.2010 03:59
quelle

Tags und Links