6.直接内存
6.1 定义
Direct Memory
-
不属于jvm,属于操作系统内存
-
常见与NIO操作时,用于数据缓冲
-
分配回收成本高,但读写性能高。
-
不受jvm内存回收管理 ,直接内存对象是通过Unsafe对象来管理的。
6.2案例
-
在使用传统FileInputStream 读文件,FileOutputStream 写文件。读取速度较慢。byte{}[]
-
-
使用FileChannel BteBuffer 直接内存
- Java不能直接操作系统内存,但是可以操作direct Memory(直接内存)
ByteBuffer源码
DirectByteBuffer(int cap) { // package-private
super(-1, 0, cap, cap);
boolean pa = VM.isDirectMemoryPageAligned();
int ps = Bits.pageSize();
long size = Math.max(1L, (long)cap + (pa ? ps : 0));
Bits.reserveMemory(size, cap);
long base = 0;
try {
base = unsafe.allocateMemory(size); //unsafe 分配内存
} catch (OutOfMemoryError x) {
Bits.unreserveMemory(size, cap);
throw x;
}
unsafe.setMemory(base, size, (byte) 0);
if (pa && (base % ps != 0)) {
// Round up to page boundary
address = base + ps - (base & (ps - 1));
} else {
address = base;
}
cleaner = Cleaner.create(this, new Deallocator(base, size, cap)); //直接内存释放必须主动调用unsafe对象
att = null; //Cleaner 虚引用对象,当关联对象被回收,就会触发虚引用的clean();
}
6.3 分配和回收原理
-
使用了 Unsafe 对象完成直接内存分配和回收,并且回收需要主动调用freeMemory方法
-
ByteBuffer的实现类内部,使用了Cleaner(虚引用) 来检测ByteBuffer 对象,一旦ByteBuffer对象被垃圾回收,那么就会由ReferenceHandler线程通过Cleaner的clean方法调用freeMemory来释放内存。
-
-XX:+DisableExplicitGC 禁用显示的GC (System.gc(); Full GC) 直接内存不会被释放,要等到真正GC的时候才会被释放,可以直接使用Unsafe对象释放。