《剑指JVM》——第10章—— 直接内存概述及其与普通访问方式的对比、直接内存的异常

🌈hello,你好鸭,我是Ethan,西安电子科技大学大三在读,很高兴你能来阅读。

✔️目前博客主要更新Java系列、项目案例、计算机必学四件套等。
🏃人生之义,在于追求,不在成败,勤通大道。加油呀!

🔥个人主页:Ethan Yankang
🔥推荐:史上最强八股文||一分钟看完我的几百篇博客

🔥温馨提示:划到文末发现专栏彩蛋   点击这里直接传送

🔥本篇概览:详细讲解了直接内存概述及其与普通访问方式的对比、直接内存的异常🌈⭕🔥


【计算机领域一切迷惑的源头都是基本概念的模糊,算法除外】


🔥 《剑指JVM》序言-CSDN博客

🔥 《剑指JVM》全书-CSDN博客


🌈章节引出

前一篇章:《剑指JVM》——第9章—— 对象的实例化内存布局与访问定位-CSDN博客

Java中的内存从广义上可以划分为两个部分,一部分是我们之前章节讲解过的受JVM 管理的堆内存,另一部分则是不受JVM管理的堆外内存,也称为直接内存,直接内存由操作系统来管理,这部分内存的应用可以减少垃圾收集对应用程序的影响。本章将会重点讲解直接内存的优缺点、如何设置直接内存的大小,以及直接内存的内存溢出现象

🌈章节速览

本章讲解了直接内存的概念,直接内存来源于NIO,它是一块堆外内存,这些内存直接受操作系统管理。
通过读写影片的案例,展示了NIO 和普通IO读取数据的性能对比,从结果来看,NIO的数据传输效率要比IO高,说明直接内存的使用可以提高数据传输效率,如果在读写频繁的场合可以考虑使用直接内存。直接内存不受JVM管理,相对于堆内存来讲更加难以控制,使用直接内存就意味着失去了JVM 管理内存的可行性,需要由开发人员管理,所以在使用直接内存的时候要注意空间的释放。                                                                        


10.1直接内存概述


直接内存不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域。((直接内存是在Java堆外的、直接向操作系统申请的内存区间。

直接内存是在系统内存和Java堆内存之间有操作系统开辟出的一块共享区域供操作系统和Java代码访问。

直接 内存 来 源 于NIO(Non-Blocking IO),可以通过 ByteBuffer类操作。ByteBufer类调用allocateDirect()方法可以申请直接内存,方法内部创建了一个DirectByteBuffer对象DirectByteBuffer对象存储直接内存的起始地址和大小,据此就可以操作直接内存。直接内存和堆内存之间的关系如图 所示。


代码清单10-1展示了直接内存的占用和释放。

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();
    }
}

通常,访问直接内存的速度会优于Java堆,读写性能更高(NIO)。因此出于性能考虑,读写频繁的场合可能会考虑使用直接内存。Java的NIO库允许Java程序使用直接内存,用于数据缓冲区。通过前面的案例我们可以把Java进程占用的内存理解为两部分,分别是JVM内存和直接内存。前面我们讲解方法区的时候,不同版本JDK中方法区的实现是不一样的,JDK7使用永久代实现方法区,永久代中的数据还是使用JVM内存存储数据。JDK8使用元空间实现方法区,元空间中的数据放在了本地内存当中,直接内存和元空间一样都属手堆外内存,如图 10-4所示。

普通访问


文件读写必然涉及磁盘的读写,但是Java本身不具备磁盘读写的能力,因此借助操作系统提供的方法,在Java中表现出来的形式就是Java中的本地方法接口调用本地方法库。普通IO 读取一份物理磁盘的文件到内存中,需要下面两步——

(1)把磁盘文件中的数据读取到系统内存中。
(2)把系统内存中的数据读取到JVM堆内存中。


如图10-5所示,为了使得数据可以在系统内存和JVM堆内存之间相互复制,需要在系统内存和JVM 堆内存都复制一份磁盘文件。这样做不仅浪费空间,而且涉及到上下文的切换,传输效率低下。

直接内存访问

当使用NIO时,如图10-6所示。操作系统划出一块直接缓冲区可以被Java代码直接访问。这样当读取文件的时候步骤如下:

(1)物理磁盘读取文件到直接内存。

(2)JVM 通过 NIO库直接访问数据。

以上步骤便省略了系统内存和JVM内存直接互相复制的过程,不仅节省了内存空间,也提高了数据传输效率。可以这样理解:

直接内存是在系统内存和Java堆内存之间开辟出的一块共享区域供操作系统和Java代码访问。

10.2直接内存异常


直接内存也可能导致 OutOfMemoryError 异常。由于直接内存在 Java 堆外,因此它的大小不会直接受限于“-Xmx”指定的最大堆大小,但是系统内存也是有限的Java堆和直接内存的总和依然受限于操作系统能给出的最大内存。



💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖

热门专栏推荐

🌈🌈计算机科学入门系列                     关注走一波💕💕

🌈🌈CSAPP深入理解计算机原理        关注走一波💕💕

🌈🌈微服务项目之黑马头条                 关注走一波💕💕

🌈🌈redis深度项目之黑马点评            关注走一波💕💕

🌈🌈JAVA面试八股文系列专栏           关注走一波💕💕

🌈🌈JAVA基础试题集精讲                  关注走一波💕💕   

🌈🌈代码随想录精讲200题                  关注走一波💕💕


总栏

🌈🌈JAVA基础要夯牢                         关注走一波💕💕  

🌈🌈​​​​​​JAVA后端技术栈                          关注走一波💕💕  

🌈🌈JAVA面试八股文​​​​​​                          关注走一波💕💕  

🌈🌈JAVA项目(含源码深度剖析)    关注走一波💕💕  

🌈🌈计算机四件套                               关注走一波💕💕  

🌈🌈数据结构与算法                           ​关注走一波💕💕  

🌈🌈必知必会工具集                           关注走一波💕💕

🌈🌈书籍网课笔记汇总                       关注走一波💕💕         



📣非常感谢你阅读到这里,如果这篇文章对你有帮助,希望能留下你的点赞👍 关注❤收藏✅ 评论💬,大佬三连必回哦!thanks!!!
📚愿大家都能学有所得,功不唐捐!

  • 23
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值