• 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

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

  • 相关阅读:
    计算机竞赛 深度学习卫星遥感图像检测与识别 -opencv python 目标检测
    【算法刷题day29】Leetcode:491.递增子序列 46.全排列 47.全排列 II
    Linux 和 Window 软件包管理器
    5 Tensorflow图像识别(下)模型构建
    numpy的使用教程
    MyBatis:基础入门
    一、MFC介绍
    __main__文件学习测试如下
    drag 拖动元素让元素跟着鼠标移动,但是拖拽时的阴影咋隐藏不让他显示 ,
    ElasticSearch-head前端安装以及连接ES基本步骤(linux)
  • 原文地址:https://blog.csdn.net/weixin_54046648/article/details/127465494