非直接缓冲区与直接缓冲区

Posted 编程老高

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了非直接缓冲区与直接缓冲区相关的知识,希望对你有一定的参考价值。

allocate(int capacity)

       作用:创建指定大小的非直接缓冲区对象,该缓冲区直接建立在JVM内存中;

       源码:

package java.nio;



...省略...



public abstract class ByteBuffer extends Buffer implements Comparable<ByteBuffer>{

   

    ...省略...

   

    public static ByteBuffer allocate(int capacity) {

        if (capacity < 0)

            throw createCapacityException(capacity);

        return new HeapByteBuffer(capacity, capacity, null);

    }

   

    ...省略...

}
package java.nio;

class HeapByteBuffer extends ByteBuffer {
    
	...省略...
	
    HeapByteBuffer(int cap, int lim, MemorySegmentProxy segment) {// package-private
        
        super(-1, 0, lim, cap, new byte[cap], 0, segment);//非直接缓冲区实质是一个数组
        /*
        hb = new byte[cap];
        offset = 0;
        */
        this.address = ARRAY_BASE_OFFSET;
    }
    
    ...省略...
}

       原理:

 

              说明:

                     1、读取:当Java应用程序读取文件时,磁盘文件数据先读取到操作系统内存,再拷贝到非直接缓冲区,然后才能被应用程序读取;

                     2、写入:当Java应用程序向文件写入时,首先将数据写入非直接缓冲区,再写入操作系统内存,然后才能写入到磁盘文件;

allocateDirect(int capacity)

       作用:创建指定大小的直接缓冲区对象,该缓冲区直接建立在物理内存中,即物理内存映射文件,应用程序直接操作物理内存映射文件,这样减少了中间copy过程,极大得提高了读写效率

       源码:

package java.nio;

...省略...

public abstract class ByteBuffer extends Buffer implements Comparable<ByteBuffer>{
    
	...省略...
	
    public static ByteBuffer allocateDirect(int capacity) {
        return new DirectByteBuffer(capacity);
    }
	
	...省略...
}
package java.nio;

...省略...

class DirectByteBuffer extends MappedByteBuffer implements DirectBuffer{
    
	...省略...
	
    DirectByteBuffer(int cap) {                   // package-private
        super(-1, 0, cap, cap, null);
        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);
        } 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));
        att = null;
    }
	
	...省略...
}

       原理:

              说明:

                     1、读取:当Java应用程序读取文件时,磁盘文件数据先读取到物理内存映射文件,然后应用程序直接从物理内存映射文件读取数据;

                     2、写入:当Java应用程序向文件写入时,首先将数据写入物理内存映射文件,然后操作系统直接将物理内存映射文件中数据写入到磁盘文件;

       缺点:

              1、非直接缓冲区由JVM分配,直接缓冲区由操作系统分配,直接缓冲区绕过了JVM堆栈,所以直接缓冲区创建和销毁比堆栈上的非直接缓冲区开销更大。

以上是关于非直接缓冲区与直接缓冲区的主要内容,如果未能解决你的问题,请参考以下文章

NIO之直接缓冲区与非直接缓冲区

Java-NIO:直接缓冲区与非直接缓冲区

非直接缓冲区与直接缓冲区

非直接缓冲区与直接缓冲区

深入浅出在NIO技术中,如何理解直接缓冲区要比非直接缓冲区效率高?

直接缓冲区和非直接缓冲区的区别 --NIO