DirectBuffer

DircetBuffer

  • directBuffer是和Java堆相区分的,更合适的是HeapBuffer,理论上DirectBuffer大小由操作系统可以给用户进程的内存大小所决定(虚拟内存,操作系统位数)。JVM提供了虚拟机参数可以配置直接内存的大小,理论上可以配置很大,但是和操作系统紧密相关。

DirectBuffer优缺点

  • 堆外内存的申请与普通的Java对象是有巨大的差别的。在以后的课程里,大家会发现,Java对象在Java堆里申请内存的时候,实际上是比malloc要快的,所以DirectBuffer的创建效率往往是比Heap Buffer差的。

  • 但是,如果进行网络读写或者文件读写的时候,DirectBuffer就会比较快了,说起来好笑,这个快是因为JDK故意把非HeapBuffer的读写搞慢的,我们看一下JDK的源代码。

static int write(FileDescriptor fd, ByteBuffer src, long position,
                     NativeDispatcher nd) 
        throws IOException
    {   
        if (src instanceof DirectBuffer)
            return writeFromNativeBuffer(fd, src, position, nd);

        // Substitute a native buffer
        int pos = src.position();
        int lim = src.limit();
        assert (pos <= lim);
        int rem = (pos <= lim ? lim - pos : 0); 
        ByteBuffer bb = Util.getTemporaryDirectBuffer(rem);
        try {
            bb.put(src);
            bb.flip();

关键点在这个方法的第一行,如果src是DirectBuffer,就直接调用writeFromNativeBuffer,如果不是,则要先创建一个临时的DirectBuffer,把src拷进去,然后再调用真正的写操作。为什么要这么干呢?还是要从DirectBuffer不会被GC移动说起。

writeFromNativeBuffer的实现,最终会把Buffer的address传给操作系统,让操作系统把address开始的那一段内存发送到网络上。这就要求在操作系统进行发送的时候,这块内存是不能动的。而我们知道,GC是会乱搬Java堆里的东西的,所以无奈,我们必须得弄一块地址不会变化的内存,然后把这个地址发给操作系统。

DirectBuffer当然还有一个直观的优点,不被GC管理,所以发生GC的时候,整理内存的压力就会小。当然,我后面也会讲,它并不是完全不被GC管理,它还是能被回收的,但是在GC平常整理内存的时候确实是不会去管它的。

你可能感兴趣的:(DirectBuffer)