java NIO - DirectBuffer 和 HeapBuffer

problem:

  1. DirectBuffer belong to the external memory heap, it should still belong to the user memory, rather than the kernel memory?
  2. FileChannel the read (ByteBuffer dst) function, write (ByteBuffer src) function, if the incoming parameter is HeapBuffer type will apply for a temporary DirectBuffer, copy data, rather than directly for data transmission, which is what the reason ?

DirectBuffer

Java               |      native
                   |
 DirectByteBuffer  |     malloc'd
 [    address   ] -+-> [   data    ]
                   |

 DirectByteBuffer itself is a Java object heap in Java; and this object type field has a long address, recorded a call to malloc () apply to the native memory. DirectByteBuffer itself (Java), behind which the real data is carried in the buffer (Java) outer --native memory heap in the stack. This is malloc () memory dispensed, the user state. (Answer from the reference article R large)

DirectBuffer 和 HeapBuffer

 Both are Buffer, except that it is used outside the heap memory, when the latter is in the JVM heap memory. When using FileChannel read and write internal implementation is a bit different. The following are FileChannel use code

    public static void main(String[] args) throws Exception{
        RandomAccessFile aFile = new RandomAccessFile("data/nio-data.txt", "rw");
        FileChannel channel = aFile.getChannel();
        String newData = "New String to write to file..." + System.currentTimeMillis();

        // HeapByteBuffer
        ByteBuffer buf = ByteBuffer.allocate(48);
        // DirectByteBuffer
        ByteBuffer dirctBuf = ByteBuffer.allocateDirect(48);

        buf.clear();
        buf.put(newData.getBytes());

        buf.flip();

        while(buf.hasRemaining()) {
            channel.write(buf);
        }
    }
        //读取地址
        FileInputStream fis = new FileInputStream("C:\\CloudMusic\\Circadian Eyes - Ferris Wheel.mp3");
        //写出地址
        FileOutputStream fos = new FileOutputStream("D:\\etc\\cas\\logs\\cas_audit.log");
        FileChannel fc = fis.getChannel();
        MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
        //回刷回磁盘
        mbb.flip();
        fos.flush();
        fc.close();
        fis.close();

 If the above code channel.write incoming parameter is HeapBuffer type will DirectBuffer a provisional application, HeapBuffer data copied to the data memory outside the stack, and the rest is for IO operations performed DirectBuffer why copy directly HeapBuffer data into the kernel, then IO does it work? This is because if we want a reference in Java byte [] object passed to native code so that native code directly access the array of content, then it must ensure that native code for this [] object can not be moved byte in the time of the visit, that is, to be "pin" (nails) to live. The GC algorithm will move the target virtual machine, resulting address is changed, then the follow-up will generate an error. See detailed references R big answer. OpenJDK is sun.nio.ch.IOUtil.write (FileDescriptor fd, ByteBuffer src, long position, NativeDispatcher nd) implementation.

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();
            // Do not update src until we see how many bytes were written
            src.position(pos);

            int n = writeFromNativeBuffer(fd, bb, position, nd);
            if (n > 0) {
                // now update src
                src.position(pos + n);
            }
            return n;
        } finally {
            Util.offerFirstTemporaryDirectBuffer(bb);
        }
    }

MappedByteBuffer

 MappedByteBuffer is DirectBuffer parent class, which is higher than the read and write performance HeapByteBuffer (otherwise FileChannel internal implementation does not operate with DirectByteBuffer). MappedByteBuffer internal principles and major operating systems for virtual storage, a more direct link is relevant knowledge page table, read the following this article .

supplement

 About Heap memory and Native memory explanations from stackoverflow

  1. Heap memory: memory within the JVM process that is managed by the JVM to represent Java objects

  2. Native memory/Off-heap: is memory allocated within the processes address space that is not within the heap.

  3. Direct memory: is similar to native, but also implies that an underlying buffer within the hardware is being shared. For example buffer within the network adapter or graphics display. The goal here is to reduce the number of times the same bytes is being copied about in memory.

Finally, depending upon the OS then extra native allocations (assigning of the memory address space) can be carried out via Unsafe alloc and/or by memory mapping a file. Memory mapping a file is especially interesting as it can easily allocate more memory than the machine currently has as physical ram. Also note, that the total address space limit is restricted by the size of a pointer being used, a 32bit pointer cannot go outside of 4GB. Period.

Reference material

  • https://www.zhihu.com/question/57374068 (recommend a look)

Guess you like

Origin www.cnblogs.com/Benjious/p/11613147.html