前言
直接内存大多时候也被称为堆外内存,自从 JDK 引入 NIO 后,直接内存的使用也越来越普遍。通过 native 方法可以分配堆外内存,通过 DirectByteBuffer 对象来操作。
直接内存不属于 Java 堆,所以它不受堆大小限制,但是它受物理内存大小的限制。
配置
可以通过 -XX:MaxDirectMemorySize 参数来设置最大可用直接内存,如果启动时未设置则默认为最大堆内存大小,即与 -Xmx 相同。即假如最大堆内存为1G,则默认直接内存也为1G,那么 JVM 最大需要的内存大小为2G多一些。当直接内存达到最大限制时就会触发GC,如果回收失败则会引起OutOfMemoryError。
分配内存耗时
环境为JDK9,两种内存分配的耗时如下,运行两遍让其预热。可以看到直接内存的分配比较耗时,而堆内存分配操作耗时少好几倍。
public static void directMemoryAllocate() {
long tsStart = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
ByteBuffer buffer = ByteBuffer.allocateDirect(400);
}
System.out.println("direct memory allocate: " + (System.currentTimeMillis() - tsStart) + " ms");
tsStart = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
ByteBuffer buffer = ByteBuffer.allocate(400);
}
System.out.println("heap memory allocate: " + (System.currentTimeMillis() - tsStart) + " ms");
}
direct memory allocate: 149 ms
heap memory allocate: 41 ms
direct memory allocate: 122 ms
heap memory allocate: 31 ms
读写操作耗时
环境为JDK9,两种内存的读写操作耗时如下,同样运行两遍让其预热,可以看到直接内存读写操作的速度相对快一些。
public static void memoryRW() {
ByteBuffer buffer = ByteBuffer.allocateDirect(400);
ByteBuffer buffer2 = ByteBuffer.allocate(400);
long tsStart = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
for (int j = 0; j < 100; j++) {
buffer.putInt(j);
}
buffer.flip();
for (byte j = 0; j < 100; j++) {
buffer.getInt();
}
buffer.clear();
}
System.out.println("direct memory rw: " + (System.currentTimeMillis() - tsStart) + " ms");
tsStart = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
for (int j = 0; j < 100; j++) {
buffer2.putInt(j);
}
buffer2.flip();
for (byte j = 0; j < 100; j++) {
buffer2.getInt();
}
buffer2.clear();
}
System.out.println("heap memory rw: " + (System.currentTimeMillis() - tsStart) + " ms");
}
direct memory rw: 39 ms
heap memory rw: 34 ms
direct memory rw: 23 ms
heap memory rw: 46 ms
总结
理论上直接内存的机制访问速度要快一些,但也不能武断地直接说直接内存快,另外,在内存分配操作上直接内存要慢一些。直接内存更适合在内存申请次数较少,但读写操作较频繁的场景。
-------------推荐阅读------------
跟我交流,向我提问:
公众号的菜单已分为“读书总结”、“分布式”、“机器学习”、“深度学习”、“NLP”、“Java深度”、“Java并发核心”、“JDK源码”、“Tomcat内核”等,可能有一款适合你的胃口。
欢迎关注: