Вопрос

Я пытался реализовать своего рода общий кэш между двумя или более JVM путем сопоставления памяти определенного файла с использованием MappedByteBuffer.Из спецификаций я вижу, что когда мы используем MappedByteBuffer.load() он должен загрузить данные в прямой буфер.У меня есть пара вопросов по этому поводу.

Мой фрагмент кода::

RandomAccessFile file = new RandomAccessFile("file.txt","rw");
FileChannel fc = file.getChannel();
MappedByteBuffer buf5 = fc.map(MapMode.READ_WRITE, 0, fc.size());

//ByteBuffer buf6 = ByteBuffer.allocateDirect(100000000);

buf5.load();

try
{
    Class c = Class.forName("java.nio.Bits");
    Field f = c.getDeclaredField("reservedMemory");
    f.setAccessible(true);
    long reservedMemory = f.getLong(null);
    f = c.getDeclaredField("maxMemory");
    f.setAccessible(true);
    System.out.println(
            "Direct Memory Usage: "+ reservedMemory +"/"+ f.getLong(null)+"\n");
}
catch (Throwable t)
{
}
  1. Результат приведенного выше кода равен 0 байтам для прямого использования памяти (File.txt равен 1 ГБ).Но если я раскомментирую строку ..

    ByteBuffer buf6 = ByteBuffer.allocateDirect(100000000);
    

    Я получаю Прямое использование памяти в размере 100 МБ .Не в состоянии понять, почему это так, относительно того, почему я не получаю никакого прямого использования памяти в первую очередь (т. е.когда строка закомментирована )

  2. Хотя прямое использование памяти составляет 0 B для приведенного выше кода, я вижу, что резидентная память (использующая unix top ) процесса увеличивается на 1 ГБ.Но если я делаю "free -m" на коробке, я не вижу никакого увеличения использования памяти.

В обоих случаях я немного сбит с толку относительно того, где заканчивается память.

Спасибо!

Это было полезно?

Решение

Прямые байтебуферы (выделяемые с помощью ByteBuffer.allocateDirect) отличаются от отображаемых байтебуферов тем, что они представляют разные разделы памяти и распределяются по-разному.Прямые байт-буферы - это способ доступа к блоку памяти, выделенному вне JVM, обычно выделяемому с маллок вызовите (хотя большинство реализаций, вероятно, будут использовать эффективный распределитель плит).То есть.это просто указатель на блок памяти.

MappedByteBuffer представляет собой раздел памяти, выделенный с помощью mmap ( ммап ) вызов, который используется для выполнения ввода-вывода с привязкой к памяти.Поэтому MappedByteBuffers не будут регистрировать использование памяти таким же образом, как это делает Прямой ByteBuffer.

Таким образом, хотя оба являются "прямыми" в том смысле, что они представляют память вне JVM, их цели различны.

Кроме того, чтобы получить значение reservedMemory, вы рефлексивно вызываете внутренний метод JVM, реализация которого не подпадает под какую-либо спецификацию, поэтому нет никаких гарантий относительно того, что возвращает это значение.Прямые байтебуферы могут быть выделены из JNI с помощью NewDirectByteBuffer - новый буфер обмена вызов из C / C ++ (скорее всего, это используют MappedByteBuffers), и это, вероятно, не влияет на значение reservedMemory, которое может изменяться только при использовании Java ByteBuffer.allocateDirect.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top