ByteBuffer byteBuffer = ByteBuffer.allocateDirect(512); 直接内存:返回DirectByteBuffer对象,DirectByteBuffer的父类是MappedByteBuffer ,MappedByteBuffer 的父类是ByteBuffer , 在ByteBuffer的上边是Buffer,在 Buffer里边有一个address 他的声明和注释如下: // Used only by direct buffers // NOTE: hoisted here for speed in JNI GetDirectBufferAddress long address; address是专门为DirectByteBuffer使用的,存储是堆外内存的地址。在 DirectByteBuffer 的构造器里边,会对 address 进行赋值。 DirectByteBuffer使用的是直接的对外内存,去除了使用HeapByteBuffer方式的内存拷贝,因此有另外一个说法叫“零拷贝”,address对应的内存区域在os的内存空间,这块内存直接与io设备进行交互,当jvm对DirectByteBuffer内存垃圾回收的时候,会通过address调os,os将address对应的区域回收。
public class OldClient { public static void main(String[] args) throws Exception { Socket socket = new Socket("localhost",8899); InputStream inputStream = new FileInputStream("niofiles/spark-2.2.0-bin-hadoop2.7.tgz"); DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
int totalSend = 0; int readCount = 0; byte[] buff =new byte[4096]; long startTime = System.currentTimeMillis(); while((readCount=inputStream.read(buff))>=0){ totalSend+=readCount; dataOutputStream.write(buff); } System.out.println("send bytes :"+totalSend+",timecost:"+(System.currentTimeMillis()-startTime)); dataOutputStream.close(); socket.close(); inputStream.close(); } }
服务端代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
public class OldServer {
public static void main(String[] args) throws Exception{ ServerSocket serverSocket = new ServerSocket(8899); while(true){ Socket socket = serverSocket.accept(); DataInputStream dataInputStream = new DataInputStream(socket.getInputStream()); byte[] buff = new byte[4096];
while(true){ int readcount = dataInputStream.read(buff,0,buff.length);
public class NewClient { public static void main(String[] args) throws Exception{ SocketChannel socketChannel = SocketChannel.open(); socketChannel.connect(new InetSocketAddress("localhost",8899)); socketChannel.configureBlocking(true); String name = "niofiles/spark-2.2.0-bin-hadoop2.7.tgz"; FileChannel fileChannel = new FileInputStream(name).getChannel(); long start = System.currentTimeMillis(); //零拷贝关键代码 /** * This method is potentially much more efficient than a simple loop * that reads from this channel and writes to the target channel. Many * operating systems can transfer bytes directly from the filesystem cache * to the target channel without actually copying them. */ long transCount = fileChannel.transferTo(0,fileChannel.size(),socketChannel);