2JAVA NIO HeapByteBuffer与DirectByteBuffer区别

JAVA NIO的相关方法以及使用

普通方法简介类型化的put 以及类型化的get 方法 他们的底层都是对字节数组的操作

**
 * 描述:
 * byte 方法的
 * 类型化put和类型化get
 *
 * @author HeGaoJian
 * @version 1.0
 * @create 2019-01-11 15:21
 */
public class NIOTest5 {

    public static void main(String[] args) {
        ByteBuffer byteBuffer = ByteBuffer.allocate(64);
        byteBuffer.putInt(15);
        byteBuffer.putLong(5000000000L);
        byteBuffer.putDouble(3.14159265357985);
        byteBuffer.putChar('款');
        byteBuffer.putShort((short) 2);
        byteBuffer.putChar('和');


        byteBuffer.flip();


        System.out.println(byteBuffer.getInt());
        System.out.println(byteBuffer.getLong());
        System.out.println(byteBuffer.getDouble());
        System.out.println(byteBuffer.getChar());
        System.out.println(byteBuffer.getShort());
        System.out.println(byteBuffer.getChar());
    }
}

sliceBuffer 的分片操作 Demo

概念: 对里面的数据任何一次修改都会到新的Buffer上面
SliceBuffer 与原有Buffer 共享数据 相同的底层数组
两个Buffer的值是独立的

	    ByteBuffer byteBuffer = ByteBuffer.allocate(10);
        for (int i = 0; i < byteBuffer.capacity(); i++) {
            byteBuffer.put((byte) i);
        }
        byteBuffer.position(2);
        byteBuffer.limit(5);

        ByteBuffer sliceBuffer = byteBuffer.slice();
        //操作sliceBuffer
        for (int i = 0; i < sliceBuffer.capacity(); i++) {
            //取出来里面的元素
            byte newbyte = sliceBuffer.get(i);
            //每一个元素乘以2
            newbyte *= 2;
            //添加到buffer
            sliceBuffer.put(i, newbyte);
        }
        //调出原有的buffer  并遍历原有的Buffer
        //是一个绝对的操作
        byteBuffer.position(0);
        byteBuffer.limit(byteBuffer.capacity());
        //原有的Buffer也同样更改
        while (byteBuffer.hasRemaining()) {
            System.out.println(byteBuffer.get());
        }
    }

只读的Buffer

/**
 * 描述:
 * 只读buffer 只能读buffer 的 随时将一个普通buffer调用asreadOnlybuffer
 * 但是不能将一个只读buffer转化为一个读写buffer
 *
 * @author HeGaoJian
 * @version 1.0
 * @create 2019-01-11 16:09
 */
public class ReadOnlyBuffer {
    public static void main(String[] args) {
        ByteBuffer buffer = ByteBuffer.allocate(10);
        System.out.println(buffer.getClass());
        for (int i = 0; i < buffer.capacity(); i++) {
            buffer.put((byte) i);
        }
        ByteBuffer readOnlyBuffer = buffer.asReadOnlyBuffer();
        //class java.nio.HeapByteBufferR
        System.out.println(readOnlyBuffer.getClass());

        readOnlyBuffer.position();
		//这个就是试着更改它结果报错了 要报错喽
//        readOnlyBuffer.put((byte) 2);
    }

HeapByteBuffer 与DirectByteBuffer

我们在初始化Buffer的时候看到是有两种方法的 :

	//追源码我们发现 allocate 构造出来的是DirectByteBuffer   对象
    ByteBuffer buffer = ByteBuffer.allocateDirect(512); 
    //追源码我们发现 allocate 构造出来的是HeapByteBuffer  对象
	ByteBuffer allocate = ByteBuffer.allocate(512);

那么它们的区别是什么呢?
DirectByteBuffer 用到的对象是sun包下面的也就是闭源的 里面也有native 本地的方法
也就是直接缓存 与 间接缓存

	DirectByteBuffer ,是存在于java堆里面的,new出来的对象是由在java领域下面的 JVm所掌控的 
	native 不在java内存中间, 也就是堆外内存 , 由c 或者c++ 来生成的 , 也就是walloc 方法   
	那么 DirectByteBuffer  里面一定有一个成员变量可以访问堆外内存的   那就是
	java.nio.Buffer 中的address  address表示就是在堆外内存的地址 
 // NOTE: hoisted here for speed in JNI GetDirectBufferAddress
    long address;  
HeapByteBuffer  是由操作系统将JVM 中的字节数组拷贝到java内存之外的内存也就是操作系统的内存
如果使用的是 DirectByteBuffer    的话是程序直接与堆外内存进行操作, (再把数据取出来在对比与操作等等) 也就是由JNI操作的 
 这种操作方式呢,我们就叫做0拷贝 是不是很这个词熟悉??
 but为什么要拷贝, IO操作的时候 通过JNI的方式访问 操作JVM内存 ,
 可能发生Gc算法等, (例如先标记在压缩的算法过程)如果Native的操作过程中发生了压缩那么数据就乱套了,所以不能进行GC操作 

所以我们要进行拷贝的操作与过程(拷贝过程不会发生GC)
这样我们就0拷贝到的方式进行了操作

源码分析

	   java.nio.DirectByteBuffer#DirectByteBuffer(int)  
		//内存分配 
	   base = unsafe.allocateMemory(size); 
	   java.nio.DirectByteBuffer.Deallocator#Deallocator 
	   //内存释放 
	   unsafe.freeMemory(address);
	   //Copy的方法 也就Native本地的方法
	   sun.misc.Unsafe#copyMemory(java.lang.Object, long, java.lang.Object, long, long) 
	      

总结

HeapByteBuffer 是直接内存模型 ,JAVA 堆上的操作 必须要经过一个Native 堆, 在由Native多进行了一个拷贝操作,直接操作内存
JAVA 堆外内存

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值