zoukankan      html  css  js  c++  java
  • 第十一章:直接内存(Direct Memory)

    一、直接内存概述

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

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

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

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

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

        Java的NIO库允许Java程序使用直接内存,用于数据缓冲区。

    直接内存并不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域,它直接从操作系统中分配,因此不受Java堆大小的限制,但是会受到本机总内存的大小及处理器寻址空间的限制,因此它也可能导致OutOfMemoryError异常出现。在JDK1.4中新引入了NIO机制,它是一种基于通道与缓冲区的新I/O方式,可以直接从操作系统中分配直接内存,即在堆外分配内存,这样能在一些场景中提高性能,因为避免了在Java堆和Native堆中来回复制数据。

    二、访问直接内存的速度会优于 Java 堆

      1、非直接缓冲区(传统IO)

          

        读写文件,需要与磁盘交互,需要由用户态切换到内核态。在内核态时,需要内存如上图的操作。
        使用IO,见上图。这里需要两份内存存储重复数据,效率低。

      2、直接缓冲区(NIO)

        

        使用NIO时,如上图。操作系统划出的直接缓存区可以被 java 代码直接访问,只有一份。NIO适合对大文件的读写操作。

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

        代码示例:

     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 
    13         System.out.println("直接内存开始释放!");
    14         byteBuffer = null;
    15         System.gc();
    16         scanner.next();
    17     }
    18 }

    三、直接内存的OOM与大小设置

      1、也可能导致outofMemoryError异常(Direct buffer memory)

      2、由于直接内存在Java堆外,因此它的大小不会直接受限于-Xmx 指定的最大堆大小,但是系统内存是有限的,Java堆和直接内存的总和依然受限于操作系统能给出的最大内存。

      3、缺点
        ① 分配回收成本较高

        ② 不受 JVM 内存回收管理

      4、直接内存大小可以通过MaxDirectMemorysize设置

      5、如果不指定,默认与堆的最大值 -Xmx 参数值一致

      设置本地内存:

     1 本地内存的OOM:  OutOfMemoryError: Direct buffer memory
     2 public class BufferTest2 {
     3     private static final int BUFFER = 1024 * 1024 * 20;//20MB
     4 
     5     public static void main(String[] args) {
     6         ArrayList<ByteBuffer> list = new ArrayList<>();
     7 
     8         int count = 0;
     9         try {
    10             while(true){
    11                 ByteBuffer byteBuffer = ByteBuffer.allocateDirect(BUFFER);
    12                 list.add(byteBuffer);
    13                 count++;
    14                 try {
    15                     Thread.sleep(100);
    16                 } catch (InterruptedException e) {
    17                     e.printStackTrace();
    18                 }
    19             }
    20         } finally {
    21             System.out.println(count);
    22         }
    23 
    24 
    25     }
    26 }

         

       简单理解:

      Java process memory = java heap + native memory

    更多:

      堆外内存

      Direct Memory(堆外内存)

      

     

  • 相关阅读:
    Codeforces题目 java程序员
    5个能够有效帮助你快速创建超棒CSS3动画效果的类库 java程序员
    POJ3140:Contestants Division(DFS,树形DP) java程序员
    github的学习使用以及将自己开发的app传上去。
    考研还是就业
    五月道别
    写给一个陌生的朋友
    有办法忘了一个人吗?
    困惑啊,我倒底错在哪里?
    招聘广告文字撰写者时注意11项
  • 原文地址:https://www.cnblogs.com/niujifei/p/14664978.html
Copyright © 2011-2022 走看看