第十一章:直接内存(Direct Memory)

摘要:
“);14byteBuffer=null;15System.gc();16scanner.next();17}18}III.直接内存的OOM和大小设置1。它还可能导致outofMemoryError异常。2。因为直接内存存在于Java堆之外,所以其大小不会直接限制为-Xmx指定的最大堆大小,但系统内存是有限的。Java堆和直接内存的总和仍然限于操作系统给定的最大内存。
一、直接内存概述

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)

第十一章:直接内存(Direct Memory)第1张

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

  2、直接缓冲区(NIO)

第十一章:直接内存(Direct Memory)第2张

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

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

代码示例:

1 public classBufferTest {
2     private static final int BUFFER = 1024 * 1024 * 1024;//1GB
3 
4     public static voidmain(String[] args){
5         //直接分配本地内存空间
6         ByteBuffer byteBuffer =ByteBuffer.allocateDirect(BUFFER);
7         System.out.println("直接内存分配完毕,请求指示!");
8 
9         Scanner scanner = newScanner(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 classBufferTest2 {
3     private static final int BUFFER = 1024 * 1024 * 20;//20MB
4 
5     public static voidmain(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 }

第十一章:直接内存(Direct Memory)第3张

简单理解:

Java process memory = java heap + native memory

更多:

堆外内存

Direct Memory(堆外内存)

免责声明:文章转载自《第十一章:直接内存(Direct Memory)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇struct对象可能分配在托管堆上吗【SpringCloud】SpringCloud Alibaba Sentinel实现熔断与限流下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

【FFMPEG】关于硬解码和软解码

一、一些命令 1、显示所有可用的硬件加速器 [root@tranCodeing ~]# ffmpeg -hwaccels ffmpeg version 4.1 Copyright (c) 2000-2018 the FFmpeg developers built with gcc 4.8.5 (GCC) 20150623 (Red Hat 4.8.5-...

简单的ld链接脚本学习

一、 链接脚本的整体认识 什么是链接文件呢?作用是什么呢? 当编写了多个C文件时,我们将他们编译链接成一个可执行的文件,此时就需要用到链接脚本文件(ld)。ld脚本主要功能就是:将多个目标文件(.o)和库文件(.a)链接成一个可执行的文件。 链接脚本文件主要有什么内容呢? 为了规范,我们分为三个部分: 链接配置(可有可无) 如一些符号变量的定义、入口地...

stressapptest使用介绍【转】

转自:https://blog.csdn.net/vichie2008/article/details/50457566 stressapptest 其是:Stressful Application Test (stressapptest) 的简称 Stressful Application Test试图让来自处理器和I/O到内存的数据尽量随机化,以创...

Redis内存碎片

目录 一、什么是内存碎片 二、如何判断有内存碎片 三、内存碎片是怎么形成的 3.1 jemalloc分配机制导致 3.2 数据的修改删除操作导致 四、如何清理内存碎片 4.1 重启 4.2 redis内存碎片自动清理机制 五、和现实的类比 一、什么是内存碎片 redis数据删除后,所占用内存不会马上还给操作系统,而是交给内存分配管理器,...

缓冲器的学习

导语 缓冲器的设计的是新IO模型中最基础的一部分。因为新IO模型中要求所有的IO操作都需要进行缓冲。在新的IO模型中,不再向输出流写入数据和从数据流中读取数据了,而是要从缓冲区中读写数据。缓冲区可是是数组,也可以是与硬件或内存直接连接。 从编程的角度来看,流和通道之间的关键区别子在于流是基于字节的,而通道是基于块的。流设计为按顺序一字节接一字节地传输数据。...

Java NIO学习系列七:Path、Files、AsynchronousFileChannel

相对于标准Java IO中通过File来指向文件和目录,Java NIO中提供了更丰富的类来支持对文件和目录的操作,不仅仅支持更多操作,还支持诸如异步读写等特性,本文我们就来学习一些Java NIO提供的和文件相关的类: Java NIO Path Java NIO Files Java NIO AsynchronousFileChannel 总结 1....