JVM記憶體模型之直接記憶體
阿新 • • 發佈:2019-01-08
直接記憶體
又稱堆外記憶體,也就是說這不是jvm執行時資料區的一部分,也不是java虛擬機器規範中定義的記憶體區域,但這部分也會被頻繁的使用,而且也可能導致OOM。
堆外記憶體有什麼優點呢?
1 減少了垃圾回收的工作,因為垃圾回收會暫停其他的工作
2 可以提高效能,避免java堆和native堆(直接記憶體)來回複製資料。
使用場景
1.在JDK1.4之後加入了NIO,引入了一種基於通道與緩衝區的I/O方式,它可以使用Native庫函式直接分配堆外記憶體,然後通過DirectByteBuffer物件作為這塊記憶體的引用來進行操作,jvm會自動對這部分的堆外記憶體進行回收。
2.使用jdk內部未對外公開的unsafe來直接使用堆外記憶體,但不會被JVM回收
例子
/**
* Created by shengjk1 on 2017/8/8
* 會自動回收的
*/
//-verbose:gc -XX:+PrintGCDetails -XX:MaxDirectMemorySize=40M
public class TestDirectByteBuffer {
public static void main(String[] args) {
while (true){
ByteBuffer buffer=ByteBuffer.allocateDirect(10*1024*1024);
}
}
}
/**
* Created by shengjk1 on 2017/8/8
* 不會自動回收
*/
public class TestUnsafeMemo {
public static Unsafe getUnsafeInstance() throws Exception
{
// 通過反射獲取rt.jar下的Unsafe類
Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafeInstance.setAccessible(true );
// return (Unsafe) theUnsafeInstance.get(null);是等價的
return (Unsafe) theUnsafeInstance.get(Unsafe.class);
}
public static void main(String[] args) throws Exception {
Unsafe unsafe = getUnsafeInstance();
while (true){
long point=unsafe.allocateMemory(20*1024*1024);
System.out.println(unsafe.getByte(point+1));
// unsafe.freeMemory(point);
}
}
}