• jvm-直接内存笔记【详细】


    直接内存概述

    • 直接内存并不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域。但是这部分内存也被频繁使用,而且也可能导致OutOfMemoryError一场出现,
    • 在jdk1.4中新加入了NIO(New Input/Output)类,引入了一种基于信道(Channel)与缓冲区(Buffer)的I/O方式,它可以使用native函数库直接分配堆外内存,然后通过一个存储在Java堆中的DirectByteBuffer 对象作为这块内存的引用进行操作,这样能在一些场景中显著提高性能,因为避免了在Java堆和native堆中来回复制数据
    • 显然本机直接内存的分配不会受到Java堆大小的限制,但是,既然是内存,肯定还是会受到本机总内存(包括RAM以及SWAP区或者分页文件)大小及处理器寻址空间的限制,服务器管理员在配置虚拟机参数是,会根据实际内存设置-Xmx等参数信息,但经常忽略直接内存,使得各个内存区域总和大于物理内存限制(包括物理的和操作系统级的限制),从而导致动态扩展出现OutOfMemoryError异常

    直接 内存GC

    jvm中的直接内存,存在堆内存中其实就是DirectByteBuffer类,它本身很小,真的内存是在堆的外卖呢,这里是映射关系。

    每次申请直接内存,都先看看是否已经达到了限定最大的直接内存大小(可以用 -XX:MaxDirectMemorySize设定),如果超出了,就会执行System.gc(),在GC的时候触发Stop-The-World ,因为是直接内存回收,时间会比较长,如果没有回收成功直接内存,并且还是超过直接内存的限额,就会抛出OOM

    DirectByteBuffer熬过了几次young gc之后,会进入老年代。当老年代满了之后,会触发Full GC。

    因为本身很小,很难占满老年代,因此基本不会触发Full GC,带来的后果是大量堆外内存一直占着不放,无法进行内存回收。还有最后一个办法,就是依靠申请额度超限时触发的system.gc(),但是它会中断进程100ms,如果在这100ms的之间,系统未完成GC,仍会抛出OOM。

    直接内存和非直接内存差异

    直接 非直接内存的概念与NIO有非常大的关联;

    在NIO之前,java.io 的方式是:
    	 磁盘IO --> 直接内存[系统内核态] -->   非直接(堆)内存[用户态]  -->  直接内存[系统内核态] --> 磁盘IO
    
    而NIO中,对文件的读写不再跟堆内存关联
    	磁盘IO --> 系统直接内存 --> 磁盘IO
    
    • 1
    • 2
    • 3
    • 4
    • 5

    读写文件时可以直接申请堆外内存。
    请添加图片描述

  • 相关阅读:
    海智算法训练营第三十三天 | 第八章 贪心算法 part03 | ● 1005.K次取反后最大化的数组和 ● 134. 加油站● 135. 分发糖果
    K8S入门前奏之VMware虚拟机网络配置
    kubectl 命令行管理K8S(上)
    Redis数据库入门
    Linux:系统基本信息扫描(3)
    基于PHP+MySQL汽车租赁管理系统的设计与实现
    自定义mvc框架复习(crud)
    Go 语言内置类型全解析:从布尔到字符串的全维度探究
    电子学会C/C++编程等级考试2021年06月(一级)真题解析
    【原理篇】三、SpringBoot自动配置原理
  • 原文地址:https://blog.csdn.net/weixin_54046648/article/details/127465494