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();
}
}
NIO的DirectByteBuffer
最新推荐文章于 2024-12-19 16:00:49 发布