У меня есть требование использовать пространство в доступной ОЗУ, на которое GC не контролирует. Я прочитал несколько статей на том же, что дало мне введение по двум подходам. Они указаны в следующем коде.Буфер против небезопасного - вне JVM
package com.directmemory;
импорт java.lang.reflect.Field; import java.nio.ByteBuffer;
импорт sun.misc.Unsafe;
общественного класса DirectMemoryTest {
public static void main(String[] args) {
//Approach 1
ByteBuffer directByteBuffer = ByteBuffer.allocateDirect(8);
directByteBuffer.putDouble(1.0);
directByteBuffer.flip();
System.out.println(directByteBuffer.getDouble());
//Approach 2
Unsafe unsafe = getUnsafe();
long pointer = unsafe.allocateMemory(8);
unsafe.putDouble(pointer, 2.0);
unsafe.putDouble(pointer+8, 3.0);
System.out.println(unsafe.getDouble(pointer));
System.out.println(unsafe.getDouble(pointer+8));
System.out.println(unsafe.getDouble(pointer+16));
}
public static Unsafe getUnsafe() {
try {
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
return (Unsafe) f.get(null);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
У меня есть несколько вопросов
1) Почему я когда-либо обратить внимание на подход 1 упоминается в коде, потому что, согласно моему пониманию ByteBuffer.allocateDirect() не может вернуть мне буфер с объемом памяти более 2 ГБ? Поэтому, если мое требование состоит в том, чтобы хранить, скажем, 3 ГБ данных, я должен создать новый буфер и сохранить там данные, что означало бы, что помимо хранения данных у меня есть дополнительная ответственность за идентификацию соответствующего буфера (из списка 'n буферов), который поддерживает указатель на прямую память.
2) Не подходит подход 2 немного быстрее, чем подход 1, потому что мне не нужно сначала находить буфер, а затем данные, мне нужен механизм индексирования для поля объекта и использовать методы getDouble/getInt и передать абсолютный адрес?
3) Является ли выделение прямой памяти (правильно ли сказать кучную память?), Связанной с ПИД-кодом? Если на машине у меня есть два процесса java, вызовы allocateMemory в PID 1 и PID 2 дают мне никогда не пересекающиеся блоки памяти для использования?
4) Почему последний оператор sysout не приводит к 0,0? Идея состоит в том, что каждый двойной использует 8 байтов, поэтому я храню 1.0 по адресу, возвращенному allocateMemory, скажем, адрес = 1, 2.0 по адресу 1 + 8, который равен 9, а затем остановится. Значит, значение по умолчанию не должно быть 0.0?
Спасибо за все пункты. Первая точка, в которой я думаю, что ByteBuffer выигрывает над Unsafe, заключается в том, что ByteBuffer позволяет вам аккумулировать память контролируемым образом и имеет apis для доступа к позиции и ограничения, поэтому мы можем принять решение о создании нового буфера или нет, что я не уверен Небезопасным. Так что, если приложение требует выделения большего количества памяти с помощью небезопасных, не очень просто использовать метод reallocateMemory? Это имеет смысл или вы считаете, что перераспределение с использованием небезопасного является достаточно интуитивным? – 100pipers
Если вы писали код в 'C', вы использовали бы аналогичные функции (malloc/realloc/free), поэтому использование reallocateMemory имеет смысл –