来源:https://my.oschina.net/OutOfMemory/blog/3034514
前言
从字面意思理解就是数据不需要来回的拷贝,大大提升了系统的性能;这个词我们也经常在java nio,netty,kafka,RocketMQ等框架中听到,经常作为其提升性能的一大亮点;下面从I/O的几个概念开始,进而在分析零拷贝。
I/O概念
1.缓冲区
专属福利 👉点击领取:651页Java面试题库
public class MappedByteBufferTest {public static void main(String[] args) throws Exception {File file = new File("D://db.txt");long len = file.length();byte[] ds = new byte[(int) len];MappedByteBuffer mappedByteBuffer = new FileInputStream(file).getChannel().map(FileChannel.MapMode.READ_ONLY, 0,len);for (int offset = 0; offset < len; offset++) {byte b = mappedByteBuffer.get();ds[offset] = b;}Scanner scan = new Scanner(new ByteArrayInputStream(ds)).useDelimiter(" ");while (scan.hasNext()) {System.out.print(scan.next() + " ");}}}
public abstract MappedByteBuffer map(MapMode mode,long position, long size)throws IOException;
public MappedByteBuffer map(MapMode mode, long position, long size)throws IOException{...省略...int pagePosition = (int)(position % allocationGranularity);long mapPosition = position - pagePosition;long mapSize = size + pagePosition;try {// If no exception was thrown from map0, the address is validaddr = map0(imode, mapPosition, mapSize);} catch (OutOfMemoryError x) {// An OutOfMemoryError may indicate that we've exhausted memory// so force gc and re-attempt mapSystem.gc();try {Thread.sleep(100);} catch (InterruptedException y) {Thread.currentThread().interrupt();}try {addr = map0(imode, mapPosition, mapSize);} catch (OutOfMemoryError y) {// After a second OOME, failthrow new IOException("Map failed", y);}}// On Windows, and potentially other platforms, we need an open// file descriptor for some mapping operations.FileDescriptor mfd;try {mfd = nd.duplicateForMapping(fd);} catch (IOException ioe) {unmap0(addr, mapSize);throw ioe;}assert (IOStatus.checkAll(addr));assert (addr % allocationGranularity == 0);int isize = (int)size;Unmapper um = new Unmapper(addr, mapSize, isize, mfd);if ((!writable) || (imode == MAP_RO)) {return Util.newMappedByteBufferR(isize,addr + pagePosition,mfd,um);} else {return Util.newMappedByteBuffer(isize,addr + pagePosition,mfd,um);}}
ByteBuffer directByteBuffer = ByteBuffer.allocateDirect(100);public class ChannelTransfer {public static void main(String[] argv) throws Exception {String files[]=new String[1];files[0]="D://db.txt";catFiles(Channels.newChannel(System.out), files);}private static void catFiles(WritableByteChannel target, String[] files)throws Exception {for (int i = 0; i < files.length; i++) {FileInputStream fis = new FileInputStream(files[i]);FileChannel channel = fis.getChannel();channel.transferTo(0, channel.size(), target);channel.close();fis.close();}}}
public abstract long transferTo(long position, long count,WritableByteChannel target)throws IOException;
public class CompositeChannelBuffer extends AbstractChannelBuffer {private final ByteOrder order;private ChannelBuffer[] components;private int[] indices;private int lastAccessedComponentId;private final boolean gathering;public byte getByte(int index) {int componentId = componentId(index);return components[componentId].getByte(index - indices[componentId]);}...省略...