一、概念和特征
- 直接内存并非 JVMS 定义的标准 Java 运行时内存。
- JDK1.4 加入了新的 NIO 机制,目的是防止 Java 堆 和 Native 堆之间往复的数据复制带来的性能损耗,此后 NIO 可以使用 Native 的方式直接在 Native 堆分配内存。
- 直接内存区域是全局共享的内存区域。
- 直接内存区域可以进行自动内存管理(GC),但机制并不完善。
- 本机的 Native 堆(直接内存) 不受 JVM 堆内存大小限制。
- 可能出现 OutOfMemoryError 异常。
二、异常演示
测试代码:
1
2public class TestNativeHeap {
3
4 /**
5 * VM Args: -XX:MaxDirectMemorySize=10M
6 */
7
8 // 每次内存分配大小
9 private static int _1M =1024*1024;
10
11 public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException {
12 Field unsafeFiled = Unsafe.class.getFields()[0];
13 unsafeFiled.setAccessible(true);
14 Unsafe unsafe = (Unsafe) unsafeFiled.get(null);
15 while (true) {
16 unsafe.allocateMemory(_1M);
17 }
18 }
19}
以上代码运行会出现 OutOfMemoryError 异常,原因是不断申请内存将超出 Native 堆限制。
直接内存导致的 OutOfMemoryError 异常,在异常信息中不会有明显的堆栈区错误提示;同时另一大特点就是内存转储文件(dump)出来会非常小,如果项目中出现这种情况,并且直接或者间接地使用了 NIO 技术,那么应该考虑是否为直接内存导致的内存溢出。
评论