概述
因为JDK8之后,方法区的落地实现(元空间)使用的是本地的直接内存,因此对直接内存要有所了解。
直接内存不是虚拟机运行时数据区的一部分,也不是《Java虚拟机规范》中定义的内存区域。
直接内存是在Java堆外的、直接向系统申请的内存区间。
- 所以在设置堆空间大小的时候,也要兼顾一下直接内存的大小,避免因直接内存而产生的OOM
来源于NIO
,通过存在堆中的DirectByteBuffer
操作Native
内存
通常,访问直接内存的速度会优于Java堆。即读写性能高。
- 因此出于性能考虑,读写频繁的场合可能会考虑使用直接内存。
- Java的NIO库允许Java程序使用直接内存,用于数据缓冲区
使用下列代码,直接分配本地内存空间
int BUFFER = 1024*1024*1024; // 1GB
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(BUFFER);
非直接缓存区和缓存区
原来采用BIO的架构,我们需要从用户态切换成内核态;
NIO的方式使用了缓存区的概念,少了数据的copy过程,效率更高
存在的问题
也可能导致OutOfMemoryError: Direct buffer memory
异常
由于直接内存在Java堆外,因此它的大小不会直接受限于-Xmx
指定的最大堆大小,但是系统内存是有限的,Java堆和直接内存的总和依然受限于操作系统能给出的最大内存(总不能电脑才8个G的内存,还给你9个G吧)。
缺点
- 分配回收成本较高
- 不受JVM内存回收管理
直接内存大小可以通过MaxDirectMemorySize
设置
- 如果不指定,默认与堆的最大值
-Xmx
参数值一致