Я написал класс парсера для конкретного двоичного формата (nfdump, если кому-то интересно), который использует java.nio's MappedByteBuffer для чтения файлов по несколько ГБ каждый. Бинарный формат - это всего лишь серия заголовков и в основном двоичных записей фиксированного размера, которые передаются вызываемому, вызывая nextRecord(), который нажимает на конечный автомат, возвращая null, когда это будет сделано. Он хорошо работает. Он работает на машине разработки.Ошибка Java-карты/nio/NFS, вызвавшая ошибку VM: «произошла ошибка в недавней небезопасной операции доступа к памяти в скомпилированном Java-коде»
На моем рабочем хосте он может работать несколько минут или часов, но всегда кажется, что он бросает «java.lang.InternalError: произошла ошибка в недавней небезопасной операции доступа к памяти в скомпилированном Java-коде», перебирая одну из методы Map.getInt, getShort, т.е. операция чтения на карте. (?)
непротиворечивым код, который устанавливает карту это:
/** 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);
}
, а затем я использую различные map.get * методы для чтения шорты, Интс, лонги и другие последовательности байтов, перед тем нажав на конец файла и закрыв карту.
Я никогда не видел исключения, брошенного на мой хост разработки. Но существенная разница между моим хостом и развитием заключается в том, что на первом я читаю последовательности этих файлов по NFS (вероятно, в конечном итоге, 6-8 ТБ, все еще растет). На моей машине dev у меня есть меньший выбор этих файлов локально (60 ГБ), но когда он взорвется на хосте, это обычно хорошо, прежде чем он доберется до 60 ГБ данных.
В обеих машинах работает java 1.6.0_20-b02, хотя на хост-хосте работает Debian/lenny, хост-узел - Ubuntu/karmic. Я не уверен, что это будет иметь значение. Обе машины имеют 16 ГБ оперативной памяти и работают с одинаковыми настройками кучи java.
Я предполагаю, что если в моем коде есть ошибка, в JVM достаточно ошибки, чтобы не выбрасывать мне правильное исключение! Но я думаю, что это просто конкретная ошибка реализации JVM из-за взаимодействия между NFS и mmap, возможно, повторение 6244515, которое официально фиксировано.
Я уже пробовал добавить «нагрузка», чтобы заставить MappedByteBuffer загружать его содержимое в ОЗУ - это, казалось, задерживало ошибку в одном тестовом прогоне, который я сделал, но не мешал ему. Или это могло быть совпадением, которое было самым длинным, что оно ушло прежде, чем рухнуть!
Если вы уже читали это и делали это с помощью java.nio раньше, каков был бы ваш инстинкт? Прямо сейчас мой должен переписать его без nio :)
Я предполагаю, что вы уже видели D8 (http://nfs.sourceforge.net/) – Justin
У меня не было, спасибо, но тогда я тоже не пишу эти файлы. –
Я вижу, что это происходит с файлами с отображением памяти в локальных файловых системах ext4 и tmpfs с Java 7u1. –