本文来说下堆外内存的回收机制分析

文章目录

  • 堆外内存
  • 堆外内存的申请和释放
  • 堆外内存的回收机制
  • 本文小结

堆外内存

JVM启动时分配的内存,称为堆内存,与之相对的,在代码中还可以使用堆外内存,比如Netty,广泛使用了堆外内存,但是这部分的内存并不归JVM管理,GC算法并不会对它们进行回收,所以在使用堆外内存时,要格外小心,防止内存一直得不到释放,造成线上故障。


堆外内存的申请和释放

JDK的ByteBuffer类提供了一个接口allocateDirect(int capacity)进行堆外内存的申请,底层通过unsafe.allocateMemory(size)实现,接下去看看在JVM层面是如何实现的。


可以发现,最底层是通过malloc方法申请的,但是这块内存需要进行手动释放,JVM并不会进行回收,幸好Unsafe提供了另一个接口freeMemory可以对申请的堆外内存进行释放。


堆外内存的回收机制

如果每次申请堆外内存,都需要在代码中显示的释放,对于Java这门语言的设计来说,显然不够合理,既然JVM不会管理这些堆外内存,它们是如何回收的呢?

DirectByteBuffer

JDK中使用DirectByteBuffer对象来表示堆外内存,每个DirectByteBuffer对象在初始化时,都会创建一个对用的Cleaner对象,这个Cleaner对象会在合适的时候执行unsafe.freeMemory(address),从而回收这块堆外内存。

当初始化一块堆外内存时,对象的引用关系如下:


其中first是Cleaner类的静态变量,Cleaner对象在初始化时会被添加到Clener链表中,和first形成引用关系,ReferenceQueue是用来保存需要回收的Cleaner对象。如果该DirectByteBuffer对象在一次GC中被回收了。


此时,只有Cleaner对象唯一保存了堆外内存的数据(开始地址、大小和容量),在下一次FGC时,把该Cleaner对象放入到ReferenceQueue中,并触发clean方法。

Cleaner对象的clean方法主要有两个作用:

  • 把自身从Clener链表删除,从而在下次GC时能够被回收
  • 释放堆外内存
public void run() {if (address == 0) {// Paranoiareturn;}unsafe.freeMemory(address);address = 0;Bits.unreserveMemory(size, capacity);
}

如果JVM一直没有执行FGC的话,无效的Cleaner对象就无法放入到ReferenceQueue中,从而堆外内存也一直得不到释放,内存岂不是会爆?其实在初始化DirectByteBuffer对象时,如果当前堆外内存的条件很苛刻时,会主动调用System.gc()强制执行FGC。


不过很多线上环境的JVM参数有-XX:+DisableExplicitGC,导致了System.gc()等于一个空函数,根本不会触发FGC,这一点在使用Netty框架时需要注意是否会出问题。


本文小结

本文介绍了JVM堆外内存的回收机制。

JVM堆外内存的回收机制分析相关推荐

  1. 一次完整的JVM堆外内存泄漏故障排查记录

    前言 记录一次线上JVM堆外内存泄漏问题的排查过程与思路,其中夹带一些JVM内存分配机制以及常用的JVM问题排查指令和工具分享,希望对大家有所帮助. 在整个排查过程中,我也走了不少弯路,但是在文章中我 ...

  2. jvm堆外内存--DirectByteBuffer

    jvm的堆外内存本来是高贵而神秘的东西,只在一些缓存方案实战级别才会出现.但自从用了Netty等高并发IO框架后,就变成了天天与堆外内存打交道,在mina,netty等nio框架中屡见不鲜.堆外内存的 ...

  3. jvm堆外内存排查详解

    文章目录 前言 一.堆外内存排查 1.背景 2.内存对比 3.堆外内存检查 4.排查堆外内存 5.glibc内存泄露 结尾 前言 内存泄漏想必大家并不陌生,对于jvm的内存泄漏,有很多排查手段和方便的 ...

  4. jvm 堆外内存_NIO效率高的原理之零拷贝与直接内存映射

    更多内容,欢迎关注微信公众号:全菜工程师小辉~ 前言 在笔者上一篇博客,详解了NIO,并总结NIO相比BIO的效率要高的三个原因,彻底搞懂NIO效率高的原理. 这篇博客将针对第三个原因,进行更详细的讲 ...

  5. jvm 堆外内存_jvm┃java内存区域,跳槽大厂必会知识点

    正文约: 2000字 预计阅读时间: 6分钟 文章首发于我的微信公众号:哪儿来的moon,欢迎大家关注 目录 目录 前言 正文 1.程序计数器 2.虚拟机栈 3.本地方法栈 4.堆 5.方法区 6.直 ...

  6. jvm 堆外内存_一图解千愁,jvm内存从来没有这么简单过!

    原创:小姐姐味道,欢迎分享,转载请保留出处. 看到这张图的同学,千万不要到处分享.我们仅限于小范围讨论,因为这张图威力很大,是我花了10年时间才画出来的! 了解了这张图,会让你对JVM内存的划分有更深 ...

  7. 一文探讨堆外内存的监控与回收

    引子 记得那是一个风和日丽的周末,太阳红彤彤,花儿五颜六色,96 年的普哥微信找到我,描述了一个诡异的线上问题:线上程序使用了 NIO FileChannel 的 堆内内存作为缓冲区,读写文件,逻辑可 ...

  8. java 查看堆外内存占用_如何监控和诊断JVM堆内和堆外内存使用?

    上一讲我介绍了 JVM 内存区域的划分,总结了相关的一些概念,今天我将结合 JVM 参数.工具等方面,进一步分析 JVM 内存结构,包括外部资料相对较少的堆外部分. 今天我要问你的问题是,如何监控和诊 ...

  9. Java堆外内存泄露分析

    查看堆内存占用正常,jvm垃圾回收也没有异常.而top出来显示java占用内存是几个G,那么可能想到了是堆外内存泄漏. 需要安装google-perftools工具进行分析 1.先安装g++ 不然编译 ...

最新文章

  1. 服务器温度3d显示,智能问答助手、3D可视化展示,腾讯医典“黑科技”助力科普更有温度...
  2. python 使用UUID库生成唯一ID
  3. 莫队(不带修改)模板
  4. Java IO篇:什么是 Proactor 网络模型?
  5. VTK:相互作用之SelectAVertex
  6. 方法性能分析器--装饰者模式应用
  7. 理论基础 —— 排序 —— 快速排序
  8. 每天一个小异常——ssh整合空指针异常
  9. 突发!Java首度“落泪”,愿永久祝福Python!网友:我也想哭!
  10. 写作的积累 —— 台词
  11. vue 项目安装 (入门)
  12. 开源商城小程序源码(小程序商城完整版源码)附搭建部署教程
  13. 基于JSP实现的影视创作论坛系统
  14. c++编写浪漫烟花 表白代码大全
  15. 公众号吸粉实操之qq群吸粉
  16. 《Flutter入门疑难杂症》imagepicker ImagePicker().getVideo()返回.jpg
  17. 【嵌入式04】用寄存器HAL库完成LED流水灯程序
  18. TTL接口笔记本液晶屏改液晶显示器
  19. wazuh-monitord agent连接监控
  20. 【数据】2000-2020Landscan Global Population Database(全球人口分布数据集-1km)下载教程

热门文章

  1. Vue动态传值与接收步骤
  2. 定义软件定义的存储市场
  3. Codeforces Round #281 (Div. 2) A. Vasya and Football 模拟
  4. css中margin:0 auto没作用
  5. [PHP]基本排序(冒泡排序、快速排序、选择排序、插入排序、二分法排序)
  6. ArcEngine由点生成TIN
  7. Node.js Server
  8. Windows系统下,使用Emacs+Putty操作远程机器
  9. TP-Link发布网格路由器Deco M5
  10. 【bzoj2281】[Sdoi2011]黑白棋