一、直接内存概述

  直接内存  

  1. 不是虚拟机运行时数据区的一部分,也不是《Java虚拟机规范》中定义的内存区域。

  2. 直接内存是在Java堆外的、直接向系统申请的内存区间。

  3. 来源于NIO,通过存在堆中的DirectByteBuffer操作Native内存

  4. 通常,访问直接内存的速度会优于Java堆。即读写性能高。

  5. 因此出于性能考虑,读写频繁的场合可能会考虑使用直接内存。

  6. 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的架构,在读写本地文件时,我们需要从用户态切换成内核态

    【JVM】直接内存(十二)

  • NIO 直接操作物理磁盘,省去了中间商赚差价

    【JVM】直接内存(十二)

  • 测试代码:分别使用 BIO 和 NIO 复制大文件,看看用时差别
      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 }
    View Code

相关文章: