关于JDK8中最大堆外内存大小MaxDirectMemorySize

10,114 阅读2分钟

java中最大堆外内存大小MaxDirectMemorySize是个迷一样的,有说是64M,有说128M等等,那到底是怎么样的,我们通过官方文档和实际的代码测试一下。

首先可以在jdk文档中找到:docs.oracle.com/javase/8/do… 关于MaxDirectMemorySize内存的描述:

-XX:MaxDirectMemorySize=size
Sets the maximum total size (in bytes) of the New I/O (the java.nio package) direct-buffer allocations. Append the letter k or K to indicate kilobytes, m or M to indicate megabytes, g or G to indicate gigabytes. By default, the size is set to 0, meaning that the JVM chooses the size for NIO direct-buffer allocations automatically.

The following examples illustrate how to set the NIO size to 1024 KB in different units:

-XX:MaxDirectMemorySize=1m
-XX:MaxDirectMemorySize=1024k
-XX:MaxDirectMemorySize=1048576

就是说在默认情况下是0,JVM会自动申请内存的大小。但具体能够申请多大的内存没有描述清楚。

下面我们用代码测试一下,看到底能申请多大的内存。 主要的代码如下:

public class DirectMemoryTest {
    public static void main(String[] args) throws InterruptedException {
        int i = 0;
        List<ByteBuffer> buffers = new ArrayList<>();
        while (true) {
            ByteBuffer bb = ByteBuffer.allocateDirect(1024 * 1024 * 1);
            buffers.add(bb);
            Thread.sleep(1000); //为了便于观察,休眠1s
            System.out.println(i++);
        }
    }
}

先不设置任何参数,我们执行该代码,会发现一直执行下去 那接下来我们设置-XX:MaxDirectMemorySize=60M,运行代码:

0
...
58
59
Exception in thread "main" java.lang.OutOfMemoryError: Direct buffer memory
	at java.nio.Bits.reserveMemory(Bits.java:694)
	at java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:123)
	at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:311)
	at com.dada.app.config.util.MemoryTest.main(MemoryTest.java:14)

Process finished with exit code 1

发现在59的时候程序报了OutOfMemoryError的错误,可见MaxDirectMemorySize=60M是生效的。

继续回到不加参数时,那最大MaxDirectMemorySize究竟能申请多少,我们将最大堆内存设置为:-Xmx100M,然后继续运行看看。

94
95
Exception in thread "main" java.lang.OutOfMemoryError: Direct buffer memory
	at java.nio.Bits.reserveMemory(Bits.java:694)
	at java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:123)
	at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:311)
	at com.dada.app.config.util.MemoryTest.main(MemoryTest.java:14)

Process finished with exit code 1

结果在96M的时候就报错OutOfMemoryError,可见DirectMemorySize是受到-Xmx限制的。

那么最终结果就是在没有设置MaxDirectMemorySize大小时,默认是0,最大大小受限于-Xmx,如果设置了,那就是MaxDirectMemorySize的大小。

已经代码均在JDK8版本中测得,其他的版本还未进行过测试。