NIO的DirectByteBuffer

本文深入探讨Java NIO的DirectByteBuffer如何实现零拷贝技术,通过对比HeapByteBuffer,解释DirectByteBuffer如何节省数据拷贝过程,提升I/O操作效率,并详细解析其内部机制和垃圾回收方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

package com.crystal.cim.mycim.nio;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class NioTest5 {

    public static void main(String[] args) throws Exception {


        FileInputStream inputStream = new FileInputStream("input2.txt");
        FileOutputStream outputStream = new FileOutputStream("output2.txt");

        FileChannel inputChannel = inputStream.getChannel();
        FileChannel outputChannel = outputStream.getChannel();
        /**
         * DirectByteBuffer(int cap) {                   // package-private
         *
         *         // 这一段代码会进入到父类MapedBuffer,然后再调用父类ByteBuffer的构造方法,实际上生成的JVM里hb[]是个null
         *         // 但是pos、lim、cap、mark依旧还是赋予的值
         *         // 维护的byte数组hb[]实际用底层内存生成的一个byte[]了
         *         super(-1, 0, cap, cap);
         *         ...
         *
         *         try {
         *             // 就是这个地方生成了一个heap之外的内存byte[]
         *             base = unsafe.allocateMemory(size);
         *         } catch (OutOfMemoryError x) {
         *             Bits.unreserveMemory(size, cap);
         *             throw x;
         *         }
         *         ...
         *  }
         *
         * 那这么做的目的是啥呢?
         * 普通HeapBytebuffer的channel.write(buffer):
         *  _______________________
         * |                       |
         * | JVM _______________   |                 __________
         * |    |heap           |  |                | 内存     |                    ______
         * |    |      ______   |  |   copy(快)     |  ______  |     write(io慢)   | 磁盘 |
         * |    |     | hb[]-|--|--|--------------->| | hb[] |-|---------------->  |_____|
         * |    |     |______|  |  |                | |______| |
         * |    |_______________|  |                |__________|
         * |_______________________|
         *
         * 1、用direct可以省略copy的过程加快速度(NIO零拷贝)
         * 2、操作系统处于内核态其实可以直接访问JVM的区域, 拷贝是为了防止JVM的垃圾回收机制, 导致hb[]的地址内容有所改变, 就会报错
         * 3、堆外内存的数据的回收由操作系统决定,一般使用完就回收,DirectByteBuffer里address指向了内存的hb[],当这个对象被回收,
         *    JNI就会找到address指向的hb[],让操作系统进行回收(避免内存泄露)
         */
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(4);

        String c = "hello world!";
        byte [] bc = c.getBytes();
        System.out.println(bc.length);
        byteBuffer.put(bc);
        /**
         * 那怎么去拿到heap外的byte数组内容呢?
         * 父类ByteBuffer定义了一个long address, 实际上这个address只有directBuffer才会用到
         * 放在父类里是为了加快拿到address的速度,(类的连接都是从父类再到子类)
         *
         * public byte get(int i) {
         *    return ((unsafe.getByte(ix(checkIndex(i)))));
         * }
         * private long ix(int i) {
         *   return address + ((long)i << 0);
         * }
         *
          */
        byteBuffer.flip();
        System.out.println((char) byteBuffer.get(1));

        while (true) {

            byteBuffer.clear();

            int readCententLength = inputChannel.read(byteBuffer);
            if (readCententLength == -1) {
                break;
            }
            byteBuffer.flip();
            outputChannel.write(byteBuffer);
        }
        inputStream.close();
        outputStream.close();

    }


}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值