Ich habe eine Parser-Klasse für ein bestimmtes Binärformat (nfdump, falls jemand interessiert ist) geschrieben verwendet java.nios MappedByteBuffer, um Dateien von 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.Java map/nio/NFS-Problem, das einen VM-Fehler verursacht: "Ein Fehler ist in einem kürzlich unsicheren Speicherzugriffsvorgang in kompiliertem Java-Code aufgetreten"
Auf meinem Produktions-Host kann es für ein paar Minuten oder Stunden laufen, aber immer scheint zu werfen "java.lang.InternalError: ein Fehler trat in einem kürzlich unsicheren Speicherzugriffsvorgang in kompiliertem Java-Code" Fingersatz einer der die Methoden Map.getInt, getShort, dh eine Leseoperation in der Map. (?)
Der unumstritten Code, der die Karte einrichtet, ist dies:
/** Set up the map from the given filename and position */
protected void open() throws IOException {
// Set up buffer, is this all the flexibility we'll need?
channel = new FileInputStream(file).getChannel();
MappedByteBuffer map1 = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
map1.load(); // we want the whole thing, plus seems to reduce frequency of crashes?
map = map1;
// assumes the host writing the files is little-endian (x86), ought to be configurable
map.order(java.nio.ByteOrder.LITTLE_ENDIAN);
map.position(position);
}
und dann benutze ich die verschiedenen map.get * Methoden Shorts, Ints, sehnt sich und andere Sequenzen von Bytes zu lesen, bevor Treffen Sie das Ende der Datei und schließen Sie die Karte.
Ich habe noch nie die Ausnahme auf meinem Entwicklungs-Host geworfen 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 an Daten erreicht.
Beide Maschinen laufen mit Java 1.6.0_20-b02, obwohl auf dem Produktionshost 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 es einen Fehler in meinem Code gibt, genug von einem Fehler in der JVM, um mich nicht eine richtige Ausnahme zu werfen! Aber ich denke, es ist nur ein bestimmter JVM-Implementierungsfehler aufgrund von Interaktionen zwischen NFS und mmap, möglicherweise eine Wiederholung von 6244515, die offiziell behoben ist.
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 verhindern. Oder es könnte Zufall sein, dass es das längste 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, um es ohne nio umzuschreiben :)
Ich vermute, Sie haben bereits D8 von gesehen (http://nfs.sourceforge.net/) – Justin
Ich hatte nicht, danke, aber dann schreibe ich auch nicht in diese Dateien. –
Ich sehe dies bei Speicherabbilddateien auf lokalen ext4 und tmpfs Dateisystemen mit Java 7u1 auftreten. –