>关于本机直接内存溢出的情况。
DirectMemory 容量可通过 -XX:MaxDirectMemorySize 指定,如果不指定,则默认与 Java 堆最大值(-Xmx 指定)一样,以下代码中越过了 DirectByteBuffer 类,直接通过反射获取 Unsafe 实例进行内存分配(Unsafe 类的 getUnsafe() 方法限制了只有引导类加载器才会返回实例,也就是设计者希望只有 rt.jar 中的类才能使用 Unsafe 的功能)。因为,虽然使用 DirectByteBuffer 分配内存也会抛出内存溢出异常,但它抛出异常时并没有真正向操作系统申请分配内存,而是通过计算得知内存无法分配,于是手动抛出异常,真正申请分配内存的方法是 unsafe.allocateMemory()。
代码如下:
>使用unsafe分配本机内存
```
/**
* -Xmx20M -XX:MaxDirectMemorySize=10M
*/
public class DirectMemoryOOM {
private static final int _1Mb = 1024*1024;
public static void main(String[] args) throws Exception{
Field unSafeField = Unsafe.class.getDeclaredFields()[0];
unSafeField.setAccessible(true);
Unsafe unsafe = (Unsafe)unSafeField.get(null);
while (true) {
unsafe.allocateMemory(_1Mb);
}
}
}
```
运行结果:

**由 DirectMemory 导致的内存溢出,一个明显的特征是在 Heap Dump 文件中不会看见明显的异常,如果在排查问题时发现 OOM 之后 Dump 文件很小,而程序中又直接或间接使用了NIO,那就可以考虑检查一下是不是这方面的原因。**
>书籍介绍:
>[《深入理解Java虚拟机:JVM高级特性与最佳实践》](https://book.douban.com/subject/6522893/)

实战:OutOfMemoryError 异常(四) -- 本机直接内存溢出