直接内存
1. 为何使用直接内存
直接内存(Direct Memory)并不在《Java虚拟机规范》中存在,所以并不属于Java运行时的内存区域。在JDK 1.4中引入了NIO机制,使用了直接内存,主要为了解决以下两个问题:
- Java堆中的对象如果不再使用要回收,回收时会影响对象的创建和使用。
- IO操作比如读文件流程,由于借助操作系统的读写功能,需要先把文件读入直接内存(缓冲区)再把数据复制到Java堆中。
对于IO操作如果在JDK中直接使用直接内存,就减少了复制操作: 另外在JDK1.8中直接内存还用于保存元空间的数据。
2. 创建直接内存
要创建直接内存上的数据,可以使用ByteBuffer。
语法:ByteBuffer directBuffer = ByteBuffer.allocateDirect(size);
arthas的memory
命令可以查看直接内存大小,属性名direct。
使用完毕需要释放:
java
ByteBuffer buffer = ByteBuffer.allocateDirect(1024);
try {
// 使用buffer进行操作
} finally {
buffer.clear();
// 可以手动触发垃圾回收,但不保证立即生效
System.gc();
}
2.1 设置最大直接内存大小
java
public class Jvm08 {
static List<ByteBuffer> list = new ArrayList<>();
public static void main(String[] args) {
int count = 0;
while (true){
ByteBuffer buffer = ByteBuffer.allocateDirect(1024 * 1024 * 100);
list.add(buffer);
System.out.println(++count);
}
}
}
可以看到一直申请直接内存,最后会执行报错,说明并不是无休止的申请都是可以的,JVM里面明显是有申请的上限,但交给虚拟机来制定这个上限值是不合理的,因为我们想根据具体不同系统的情况来做定制化的设置,JVM提供直接内存的使用大小参数: 如果需要手动调整直接内存的大小,可以使用
-XX:MaxDirectMemorySize=大小
, 单位k或K表示千字节,m或M表示兆字节,g或G表示千兆字节。默认不设置该参数情况下,JVM自动选择最大分配的大小。