11_直接内存

Posted root_zhb

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了11_直接内存相关的知识,希望对你有一定的参考价值。

1、概述

  1. 不是虚拟机运行时数据区的一部分,也不是《Java虚拟机规范》中定义的内存区域
  2. 直接内存是Java堆外的、直接向系统申请的内存区间
  3. 来源于NIO,通过存在堆中的DirectByteBuffer操作Native内存
  4. 通常,访问直接内存的速度会优于Java堆。即读写性能高.
    • 因此出于性能考虑,读写频繁的场合可能会考虑使用直接内存。
    • Java的NIO库允许Java程序使用直接内存,用于数据缓冲区


2、代码

/**
 *  IO                  NIO (New IO / Non-Blocking IO)
 *  byte[] / char[]     Buffer
 *  Stream              Channel
 *
 * 查看直接内存的占用与释放
 */
public class BufferTest {
    private static final int BUFFER = 1024 * 1024 * 1024;//1GB

    public static void main(String[] args){
        //直接分配本地内存空间
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(BUFFER);
        System.out.println("直接内存分配完毕,请求指示!");

        Scanner scanner = new Scanner(System.in);
        scanner.next();

        System.out.println("直接内存开始释放!");
        byteBuffer = null;
        System.gc();
        scanner.next();
    }
}

3、OOM与内存大小设置

  1. 直接内存大小可以通过 -XX:MaxDirectMemorySize=10m 设置,如果不指定,默认与堆的最大值 -Xmx参数值一致
  2. 直接内存OOM错误
  3. 简单理解: java process memory = java heap + native memory (栈和程序计数器等可忽略)

4、优缺点

  1. 优点
    ①. 减少了垃圾回收
    堆外内存是直接受操作系统管理(不是JVM)。这样做能保持一个较小的堆内内存,以减少垃圾收集对应用的影响。

    ②. 提升IO速度
    堆内内存由JVM管理,属于“用户态”;而堆外内存由OS管理,属于“内核态”。如果从堆内向磁盘写数据时,数据会被先复制到堆外内存,即内核缓冲区,然后再由OS写入磁盘,使用堆外内存避免了这个操作。

  2. 缺点
    缺点就是没有JVM协助管理内存,需要我们自己来管理堆外内存,防止内存溢出。为了避免一直没有FULL GC,最终导致物理内存被耗完。我们会指定直接内存的最大值,通过-XX:MaxDirectMemerySize来指定,当达到阈值的时候,调用system.gc来进行一次full gc,把那些没有被使用的直接内存回收掉。

以上是关于11_直接内存的主要内容,如果未能解决你的问题,请参考以下文章

我应该如何使用 Outlook 发送代码片段?

JVM--11---直接内存

C 中的共享内存代码片段

带有 UI 和内存泄漏的保留片段

如何使用模块化代码片段中的LeakCanary检测内存泄漏?

从内核分配用户空间内存