1. 程式人生 > >JVM記憶體模型之直接記憶體

JVM記憶體模型之直接記憶體

直接記憶體
又稱堆外記憶體,也就是說這不是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); } } }