Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/355.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java `ByteBuffer.allocateDirect`和Xmx_Java_Memory Management - Fatal编程技术网

Java `ByteBuffer.allocateDirect`和Xmx

Java `ByteBuffer.allocateDirect`和Xmx,java,memory-management,Java,Memory Management,根据(尽管JavaDoc中没有特别提到),ByteBuffer.allocateDirect从主JVM堆中分配内存。我可以确认,使用Java任务控制,调用ByteBuffer n=ByteBuffer.allocateDirect(Integer.MAX_VALUE)的程序不会占用太多Java堆内存: 但是,当限制JVM堆内存时,这种堆外内存分配将停止工作。例如,当我使用-Xmx1g选项运行JVM时,allocateDirect调用会导致以下异常:线程“main”java.lang.OutOf

根据(尽管JavaDoc中没有特别提到),
ByteBuffer.allocateDirect
从主JVM堆中分配内存。我可以确认,使用Java任务控制,调用
ByteBuffer n=ByteBuffer.allocateDirect(Integer.MAX_VALUE)
的程序不会占用太多Java堆内存:

但是,当限制JVM堆内存时,这种堆外内存分配将停止工作。例如,当我使用
-Xmx1g
选项运行JVM时,
allocateDirect
调用会导致以下异常:
线程“main”java.lang.OutOfMemoryError中的异常:直接缓冲内存
。我不完全理解这个JVM选项如何与堆外直接内存分配相关,因为根据
-Xmx
选项设置Java堆空间大小。如果我使用
getUnsafe().allocateMemory(Integer.MAX_值)分配内存内存已成功分配。我的JVM如下所示:

java版本“10”2018-03-20 java(TM)SE运行时环境18.3 (构建10+46)Java热点(TM)64位服务器VM 18.3(构建10+46, 混合模式)

Xmx
ByteBuffer.allocateDirect
之间是否会出现这种行为


编辑:JDK1.7中似乎存在一个与上述行为相同的(不可复制的)。这是一个bug吗?

好吧,这不是bug,让我告诉你为什么
allocateDirect
会导致
OOM
。 在JVM中,您已经知道设置最大JVM堆大小的
-Xmx
选项。但是你必须知道JVM内存(堆)也是你电脑内存的一部分。 简单来说,这意味着
您的PC内存
=
JVM
+
直接内存
。 因此,当您将JVM选项设置为“-Xmx1g”并获得
OOM
异常时,请检查并确保您有足够的内存(电脑的其余内存)来运行
allocateDirect


希望它能帮助你

我不得不去寻觅拾荒者来寻找原因,但你来了

首先,我查看了
ByteBuffer#allocateDirect
,发现如下内容:

public static ByteBuffer allocateDirect(int capacity) {
    return new DirectByteBuffer(capacity);
}
private static boolean tryReserveMemory(long size, int cap) {
    long totalCap;

    while (cap <= maxMemory - (totalCap = totalCapacity.get())) {
        if (totalCapacity.compareAndSet(totalCap, totalCap + cap)) {
            reservedMemory.addAndGet(size);
            count.incrementAndGet();
            return true;
        }
    }

    return false;
}
然后我导航到
DirectByteBuffer
的构造函数,并找到以下方法调用:

Bits.reserveMemory(size, cap);
通过这种方法,我们可以看到:

while (true) {
    if (tryReserveMemory(size, cap)) {
        return;
    }

    if (sleeps >= MAX_SLEEPS) {
        break;
    }

    try {
        if (!jlra.waitForReferenceProcessing()) {
            Thread.sleep(sleepTime);
            sleepTime <<= 1;
            sleeps++;
        }
    } catch (InterruptedException e) {
        interrupted = true;
    }
}

// no luck
throw new OutOfMemoryError("Direct buffer memory");
我对
maxMemory
字段很好奇,并查看它的声明位置:

private static volatile long maxMemory = VM.maxDirectMemory();
现在我必须查看
VM.java
中的
maxDirectMemory

public static long maxDirectMemory() {
    return directMemory;
}
最后,让我们看一下directMemory的声明:

// A user-settable upper limit on the maximum amount of allocatable direct
// buffer memory.  This value may be changed during VM initialization if
// "java" is launched with "-XX:MaxDirectMemorySize=<size>".
//
// The initial value of this field is arbitrary; during JRE initialization
// it will be reset to the value specified on the command line, if any,
// otherwise to Runtime.getRuntime().maxMemory().
//
private static long directMemory = 64 * 1024 * 1024;

这太棒了,谢谢
/**
 * Returns the maximum amount of memory that the Java virtual machine
 * will attempt to use.  If there is no inherent limit then the value
 * {@link java.lang.Long#MAX_VALUE} will be returned.
 *
 * @return  the maximum amount of memory that the virtual machine will
 *          attempt to use, measured in bytes
 * @since 1.4
 */
public native long maxMemory();