一、直接内存概述
直接内存
-
不是虚拟机运行时数据区的一部分,也不是《Java虚拟机规范》中定义的内存区域。
-
直接内存是在Java堆外的、直接向系统申请的内存区间。
-
来源于NIO,通过存在堆中的DirectByteBuffer操作Native内存
-
通常,访问直接内存的速度会优于Java堆。即读写性能高。
-
因此出于性能考虑,读写频繁的场合可能会考虑使用直接内存。
-
Java的NIO库允许Java程序使用直接内存,用于数据缓冲区
-
示例代码
1 public class BufferTest { 2 private static final int BUFFER = 1024 * 1024 * 1024;//1GB 3 4 public static void main(String[] args){ 5 //直接分配本地内存空间 6 ByteBuffer byteBuffer = ByteBuffer.allocateDirect(BUFFER); 7 System.out.println("直接内存分配完毕,请求指示!"); 8 9 Scanner scanner = new Scanner(System.in); 10 scanner.next(); 11 12 System.out.println("直接内存开始释放!"); 13 byteBuffer = null; 14 System.gc(); 15 scanner.next(); 16 } 17 }
-
直接占用了 1G 的本地内存
- 释放后,Java程序的内存占用明显减少,可以通过任务管理器查看内存变化
二、直接缓冲区(NIO)
关于NIO可以参考:【Java】Java NIO 概览(一)
- 原来采用BIO的架构,在读写本地文件时,我们需要从用户态切换成内核态
- NIO 直接操作物理磁盘,省去了中间商赚差价
- 测试代码:分别使用 BIO 和 NIO 复制大文件,看看用时差别
View Code
1 public class BufferTest1 { 2 3 private static final String TO = "F:\\test\\异界BD中字.mp4"; 4 private static final int _100Mb = 1024 * 1024 * 100; 5 6 public static void main(String[] args) { 7 long sum = 0; 8 String src = "F:\\test\\异界BD中字.mp4"; 9 for (int i = 0; i < 3; i++) { 10 String dest = "F:\\test\\异界BD中字_" + i + ".mp4"; 11 // sum += io(src,dest);//54606 12 sum += directBuffer(src, dest);//50244 13 } 14 15 System.out.println("总花费的时间为:" + sum); 16 } 17 18 private static long directBuffer(String src, String dest) { 19 long start = System.currentTimeMillis(); 20 21 FileChannel inChannel = null; 22 FileChannel outChannel = null; 23 try { 24 inChannel = new FileInputStream(src).getChannel(); 25 outChannel = new FileOutputStream(dest).getChannel(); 26 27 ByteBuffer byteBuffer = ByteBuffer.allocateDirect(_100Mb); 28 while (inChannel.read(byteBuffer) != -1) { 29 byteBuffer.flip();//修改为读数据模式 30 outChannel.write(byteBuffer); 31 byteBuffer.clear();//清空 32 } 33 } catch (IOException e) { 34 e.printStackTrace(); 35 } finally { 36 if (inChannel != null) { 37 try { 38 inChannel.close(); 39 } catch (IOException e) { 40 e.printStackTrace(); 41 } 42 43 } 44 if (outChannel != null) { 45 try { 46 outChannel.close(); 47 } catch (IOException e) { 48 e.printStackTrace(); 49 } 50 51 } 52 } 53 54 long end = System.currentTimeMillis(); 55 return end - start; 56 57 } 58 59 private static long io(String src, String dest) { 60 long start = System.currentTimeMillis(); 61 62 FileInputStream fis = null; 63 FileOutputStream fos = null; 64 try { 65 fis = new FileInputStream(src); 66 fos = new FileOutputStream(dest); 67 byte[] buffer = new byte[_100Mb]; 68 while (true) { 69 int len = fis.read(buffer); 70 if (len == -1) { 71 break; 72 } 73 fos.write(buffer, 0, len); 74 } 75 } catch (IOException e) { 76 e.printStackTrace(); 77 } finally { 78 if (fis != null) { 79 try { 80 fis.close(); 81 } catch (IOException e) { 82 e.printStackTrace(); 83 } 84 85 } 86 if (fos != null) { 87 try { 88 fos.close(); 89 } catch (IOException e) { 90 e.printStackTrace(); 91 } 92 93 } 94 } 95 96 97 long end = System.currentTimeMillis(); 98 99 return end - start; 100 } 101 }