Карта Java / nio / проблема NFS, вызывающая отказ VM: “отказ произошел в недавней небезопасной операции доступа к памяти в скомпилированном коде Java”

Я записал класс синтаксического анализатора для конкретного двоичного формата (nfdump, если кому-либо интересно), который использует MappedByteBuffer java.nio для прочтения файлов некоторых ГБ каждый. Двоичный формат является просто рядом заголовков и двоичных записей главным образом фиксированного размера, которые питаются к названному путем вызова nextRecord (), который спешит конечный автомат, возвращая пустой указатель, когда он сделан. Это работает хорошо. Это работает над машиной разработки.

На моем производственном узле это может работать в течение нескольких минут или часов, но всегда, кажется, бросает "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* методы, чтобы считать короткие замыкания, ints, longs и другие последовательности байтов, прежде, чем поразить конец файла и закрыть карту.

Я никогда не видел исключение, выданное на моем узле разработки. Но важная точка расхождения между моим производственным узлом и разработкой - то, что на первом, я читаю последовательности этих файлов по NFS (вероятно, 6-8TB в конечном счете, все еще растя). На моей dev машине у меня есть меньший выбор этих файлов локально (60 ГБ), но когда она аварийно завершается на производственном узле, это обычно задолго до того, как это добирается до 60 ГБ данных.

Обе машины выполняют java 1.6.0_20-b02, хотя производственный узел выполняет Debian/lenny, хостом dev является Ubuntu / кармический. Я не убежден, что это будет иметь любое значение. Обе машины имеют 16 ГБ RAM и работают с теми же настройками "кучи" Java.

Я получаю представление что, если существует ошибка в моем коде, существует действительно ошибка в JVM для не броска меня надлежащее исключение! Но я думаю, что это - просто конкретная ошибка реализации JVM из-за взаимодействий между NFS и mmap, возможно повторение 6244515, который официально фиксируется.

Я уже попытался добавить в вызове "загрузки", чтобы вынудить MappedByteBuffer загрузить свое содержание в RAM - это, казалось, задержало ошибку в одном тестовом прогоне, который я сделал, но не предотвращаю его. Или это могло быть совпадение, которое было самым долгим, это пошло перед катастрофическим отказом!

Если бы Вы читали настолько далеко и сделали такого рода вещь с java.nio прежде, каков Ваш инстинкт был бы? Прямо сейчас мой должен переписать его без nio :)

9
задан Matthew Bloch 1 June 2010 в 00:36
поделиться

1 ответ

Я бы переписал его без использования отображенного NIO.Если вы имеете дело с более чем одним файлом, существует проблема, заключающаяся в том, что отображаемая память никогда не освобождается, поэтому у вас закончится виртуальная память: NB, это не обязательно просто OutOfMemoryError, который взаимодействует со сборщиком мусора, это будет неспособность выделить новый отображаемый буфер. Я бы использовал FileChannel.

При этом крупномасштабные операции с файлами NFS всегда чрезвычайно проблематичны. Было бы намного лучше перепроектировать систему так, чтобы каждый файл читался его локальным процессором. Таким образом, вы также получите огромное улучшение скорости, намного больше, чем 20%, которые вы потеряете, не используя сопоставленные буферы.

4
ответ дан 3 November 2019 в 07:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: