Меня смущает то, как JVM контролирует размер кучи, поэтому я хотел бы задать следующие вопросы, чтобы лучше понять это.
Когда люди используют Java Unsafe API для выделения памяти вне кучи в приложении Java, какой параметр jvm можно использовать для управления размером памяти, которая может быть выделена с помощью Unsafe? Это -XX:MaxDirectMemorySize? Есть ли какие-либо другие параметры, которые также можно использовать для управления размером?
В представлении макета памяти JVM есть область, называемая прямой памятью, тогда MaxDirectMemorySize используется для управления размером этой области? и Unsafe выделяется ли память из этой области?
Каков размер вне кучи по умолчанию, если -XX:MaxDirectMemorySize не установлен.
Если Unsafe попытаться выделить больше памяти, чем позволяет JVM (например, больше, чем MaxDirectMemorySize), OOM все равно произойдет?




-XX:MaxDirectMemorySize не имеет ничего общего с The Java Unsafe API. Он относится только к прямым байтовым буферам. Подробности можно увидеть в конструкторе DirectByteBuffer.
private static boolean tryReserveMemory(long size, int cap) {
// -XX:MaxDirectMemorySize limits the total capacity rather than the
// actual memory usage, which will differ when buffers are page
// aligned.
long totalCap;
while (cap <= maxMemory - (totalCap = totalCapacity.get())) {
if (totalCapacity.compareAndSet(totalCap, totalCap + cap)) {
reservedMemory.addAndGet(size);
count.incrementAndGet();
return true;
}
}
return false;
}
-XX:MaxDirectMemorySize ограничивает объем памяти, который можно выделить с помощью ByteBuffer.allocateDirect. Хотя allocateDirect использует Unsafe.allocateMemory под капотом, опция MaxDirectMemorySize не влияет на необработанные Unsafe вызовы.
Unsafe.allocateMemory сводится к функции malloc из стандартной библиотеки. HotSpot JVM не имеет возможности ограничить объем «небезопасной» памяти.
Строго говоря, «прямая память» — это абстракция. Типичная реализация JVM не имеет выделенной области для прямой памяти. Как упоминалось выше, Unsafe.allocateMemory получает память от системного malloc вызова. Кроме того, Direct Buffers подсчитывает выделенную память по лимиту MaxDirectMemorySize.
Если опция MaxDirectMemorySize не установлена, максимальный размер выделяемой прямой памяти ограничивается максимальным размером кучи, точнее, значением Runtime.getRuntime().maxMemory().
Нет, JVM не ограничивает Unsafe.allocateMemory. Операционная система должна контролировать эти выделения.
Да, спасибо @apangin, думаю, теперь я понял Unsafe, DirectMemory намного лучше, спасибо!