Java 内存之直接内存

一、概念和特征

  • 直接内存并非 JVMS 定义的标准 Java 运行时内存。
  • JDK1.4 加入了新的 NIO 机制,目的是防止 Java 堆 和 Native 堆之间往复的数据复制带来的性能损耗,此后 NIO 可以使用 Native 的方式直接在 Native 堆分配内存。
  • 直接内存区域是全局共享的内存区域。
  • 直接内存区域可以进行自动内存管理(GC),但机制并不完善。
  • 本机的 Native 堆(直接内存) 不受 JVM 堆内存大小限制。
  • 可能出现 OutOfMemoryError 异常。

二、异常演示

测试代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

public class TestNativeHeap {

/**
* VM Args: -XX:MaxDirectMemorySize=10M
*/

// 每次内存分配大小
private static int _1M =1024*1024;

public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException {
Field unsafeFiled = Unsafe.class.getFields()[0];
unsafeFiled.setAccessible(true);
Unsafe unsafe = (Unsafe) unsafeFiled.get(null);
while (true) {
unsafe.allocateMemory(_1M);
}
}
}

以上代码运行会出现 OutOfMemoryError 异常,原因是不断申请内存将超出 Native 堆限制。

直接内存导致的 OutOfMemoryError 异常,在异常信息中不会有明显的堆栈区错误提示;同时另一大特点就是内存转储文件(dump)出来会非常小,如果项目中出现这种情况,并且直接或者间接地使用了 NIO 技术,那么应该考虑是否为直接内存导致的内存溢出。


本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 国际许可协议进行许可,转载请注明出处。