首页 > 其他分享 >cleaner

cleaner

时间:2024-04-15 16:45:27浏览次数:7  
标签:cleaner hasCleaner 堆外 Cleaner 内存 noCleaner DirectByteBuffer

https://www.cnblogs.com/exmyth/p/14205361.html

 

java.nio提供的DirectByteBuffer提供了sun.misc.Cleaner类的clean()方法,进行系统调用释放堆外内存,触发clean()方法的情况有2种

  • (1) 应用程序主动调用
ByteBuffer buf = ByteBuffer.allocateDirect(1);
((DirectBuffer) byteBuffer).cleaner().clean();
  • (2) 基于GC回收

Cleaner类继承了java.lang.ref.Reference,GC线程会通过设置Reference的内部变量(pending变量为链表头部节点,discovered变量为下一个链表节点),将可被回收的不可达的Reference对象以链表的方式组织起来

Reference的内部守护线程从链表的头部(head)消费数据,如果消费到的Reference对象同时也是Cleaner类型,线程会调用clean()方法(Reference#tryHandlePending())

 

介绍noCleaner策略之前,需要先理解带有Cleaner对象的DirectByteBuffer在初始化时做了哪些事情:

只有在DirectByteBuffer(int cap)构造方法中才会初始化Cleaner对象,方法中检查当前内存是否超过允许的最大堆外内存(可由-XX:MaxDirectMemorySize配置)

如果超出,则会先尝试将不可达的Reference对象加入Reference链表中,依赖Reference的内部守护线程触发可以被回收DirectByteBuffer关联的Cleaner的run()方法

如果内存还是不足, 则执行 System.gc(),触发full gc,来回收堆内存中的DirectByteBuffer对象来触发堆外内存回收,如果还是超过限制,则抛出java.lang.OutOfMemoryError(代码位于java.nio.Bits#reserveMemory()方法)

而Netty在4.1引入可以noCleaner策略:创建不带Cleaner的DirectByteBuffer对象,这样做的好处是绕开带Cleaner的DirectByteBuffer执行构造方法和执行Cleaner的clean()方法中一些额外开销,当堆外内存不够的时候,不会触发System.gc(),提高性能

hasCleaner的DirectByteBuffer和noCleaner的DirectByteBuffer主要区别如下:

  • 构造器方式不同:
    noCleaner对象:由反射调用 private DirectByteBuffer(long addr, int cap)创建
    hasCleaner对象:由 new DirectByteBuffer(int cap)创建

  • 释放内存的方式不同
    noCleaner对象:使用 UnSafe.freeMemory(address);
    hasCleaner对象:使用 DirectByteBuffer 的 Cleaner 的 clean() 方法

Netty在启动时需要判断检查当前环境、环境配置参数是否允许noCleaner策略(具体逻辑位于PlatformDependent的static代码块),例如运行在Android下时,是没有Unsafe类的,不允许使用noCleaner策略,如果不允许,则使用hasCleaner策略

读到这里,也许有读者会问,如果Netty基于hasCleaner策略,通过GC触发Cleaner.clean(),自动回收堆外内存,是不是就可以不用考虑ByteBuf.release()方法的调用,不会内存泄漏?

当然不是,一方面原因是自动触发不实时:需要ByteBuffer对象被GC线程回收才会触发,如果ByteBuffer对象进入老年代后才变得可回收,则需要等到发送频率较低老年代GC才会触发

因为堆巨大无比8g,而直接内存只有2g,堆得gc频率较低,没等堆gc,直接内存先满了

另一方面,Netty需要基于ByteBuf.release()方法执行其他操作,例如池化内存释放回内存池,否则该对象会被内存池一直标记为已使用

 

配置堆外内存大小的参数有-XX:MaxDirectMemorySize和-Dio.netty.maxDirectMemory,这2个参数有什么区别?

  • -XX:MaxDirectMemorySize
    用于限制Netty中hasCleaner策略的DirectByteBuffer堆外内存的大小,默认值是JVM能从操作系统申请的最大内存,如果内存本身没限制,则值为Long.MAX_VALUE个字节(默认值由Runtime.getRuntime().maxMemory()返回),代码位于java.nio.Bits#reserveMemory()方法中

note:-XX:MaxDirectMemorySize无法限制Netty中noCleaner策略的DirectByteBuffer堆外内存的大小

  • -Dio.netty.maxDirectMemory
    用于限制noCleaner策略下Netty的DirectByteBuffer分配的最大堆外内存的大小,如果该值为0,则使用hasCleaner策略,代码位于PlatformDependent#incrementMemoryCounter()方法中
  • (1) hasCleaner的DirectByteBuffer监控
    对于hasCleaner策略的DirectByteBuffer,java.nio.Bits类是有记录堆外内存的使用情况,但是该类是包级别的访问权限,不能直接获取,可以通过MXBean来获取

**note:**MXBean,Java提供的一系列用于监控统计的特殊Bean,通过不同类型的MXBean可以获取JVM进程的内存,线程、类加载信息等监控指标

List<BufferPoolMXBean> bufferPoolMXBeans = ManagementFactoryHelper.getBufferPoolMXBeans();
BufferPoolMXBean directBufferMXBean = bufferPoolMXBeans.get(0);
// hasCleaner的DirectBuffer的数量
long count = directBufferMXBean.getCount();
// hasCleaner的DirectBuffer的堆外内存占用大小,单位字节
long memoryUsed = directBufferMXBean.getMemoryUsed();

note: MappedByteBuffer:是基于FileChannelImpl.map进行进行mmap内存映射(零拷贝的一种实现)得到的另外一种堆外内存的ByteBuffer,可以通过ManagementFactoryHelper.getBufferPoolMXBeans().get(1)获取到该堆外内存的监控指标

  • (2) noCleaner的DirectByteBuffer监控
    Netty中noCleaner的DirectByteBuffer的监控比较简单,直接通过PlatformDependent.usedDirectMemory()访问即可
  • disabled 完全关闭内存泄露检测
  • simple 以约1%的抽样率检测是否泄露,默认级别
  • advanced 抽样率同simple,但显示详细的泄露报告
  • paranoid 抽样率为100%,显示报告信息同advanced

使用方法是在命令行参数设置:

-Dio.netty.leakDetectionLevel=[检测级别]

 

也可以通过jdk自带的Visualvm获取,需要安装Buffer Pools插件,底层原理是访问MXBean中的监控指标,只能获取hasCleaner的DirectByteBuffer的使用情况

 

标签:cleaner,hasCleaner,堆外,Cleaner,内存,noCleaner,DirectByteBuffer
From: https://www.cnblogs.com/silyvin/p/18136344

相关文章

  • JAVA常用类--Cleaner类
    Cleaner类注意:在JDK1.9以上版本可使用在Java程序中提供有GC的垃圾回收机制,如果发现堆内存不足时一定要进行垃圾回收以释放内存空间但如果某些对象在回收前需要做一些处理,可以通过覆写Object类中的finalize()方法来实现这种回收前的处理finalize()方法的定义:@Deprecated(sin......
  • 电脑太卡?ccleaner必不可少
    如果你的电脑有一下问题,那么这篇文章一定能解决你的问题:电脑卡顿c盘爆红(注意很多人会有一个错误的概念,很多人会把磁盘空间成为“内存”,但是这种称呼是错误的)打开方式有许多已经卸载了的软件解决这个问题的软件就是:ccleaner对于一般情况来说,左侧从上往下第一项和第三项工具......
  • [Mac软件]App Cleaner & Uninstaller 8.2.6应用程序清理和卸载
    AppCleaner&Uninstaller是一款Mac应用程序,它可以帮助用户完全删除应用程序及其相关的服务文件、扩展文件等。以下是该应用程序的主要功能:完全删除应用程序:通过将应用程序图标拖到垃圾桶中删除程序,可以彻底清除应用程序及其相关文件,释放磁盘空间。删除所有类型的服务文件:除了删除......
  • [Mac软件]App Cleaner & Uninstaller 8.2.5应用程序清理和卸载
    AppCleaner&Uninstaller是一款Mac应用程序,它可以帮助用户完全删除应用程序及其相关的服务文件、扩展文件等。以下是该应用程序的主要功能:完全删除应用程序:通过将应用程序图标拖到垃圾桶中删除程序,可以彻底清除应用程序及其相关文件,释放磁盘空间。删除所有类型的服务文件:除了删除......
  • ai 图片消除工具, lama-cleaner,安装
    如何使用这是一款开源工具,访问以下网页可供体验。https://huggingface.co/spaces/Sanster/Lama-Cleaner-lama如果你打不开上方的网址,可以尝试自行在电脑上部署。本机部署此功能安装python并确保python被加入到环境变量这一步不多讲解,关于python的安装网络上有特别多文字和......
  • App Cleaner & Uninstaller:全面优化Mac,提升运行效率
    AppCleaner&Uninstaller是一款专业的Mac清理卸载工具,它可以帮助用户轻松地清理Mac系统中的无用文件和卸载不需要的应用程序。通过使用这款工具,用户可以释放磁盘空间,提高系统运行速度,让Mac更加稳定和流畅。AppCleaner&Uninstaller获取AppCleaner&Uninstaller具有直观简......
  • 一款.NET开源的小巧、智能、免费的Windows内存清理工具 - WinMemoryCleaner
    前言我们在使用Windows系统的时候经常会遇到一些程序不会释放已分配的内存,从而导致电脑变得缓慢。今天给大家推荐一款.NET开源的小巧、智能、免费的Windows内存清理工具:WinMemoryCleaner。使用Windows内存清理工具来优化内存,这样不必浪费时间去重新启动电脑。工具主要特点......
  • 简单好用的文件清理工具:ccleaner
    ccleaner是一款简单好用的文件清理工具。ccleaner可以清除系统中的所有垃圾文件,腾出硬盘空间,保护系统隐私。ccleaner体积小、运行快,同时还可以对注册表进行扫描。CCleaner特色功能1、ccleaner可以清理临时文件夹、回收站的里的垃圾文件,还可以扫描清理注册表里的垃圾项;2、ccleane......
  • [Mac软件]MacCleaner 3 PRO 3.2.1应用程序清理和卸载
    应用介绍MacCleanerPRO是一个应用程序包,将帮助您清除磁盘空间并加快Mac的速度!MacCleanerPRO-让您的Mac始终快速、干净和有条理。AppCleaner&UninstallerPRO-完全删除未使用的应用程序并管理Mac扩展。磁盘空间分析仪PRO-分析磁盘空间的使用情况,并找到最庞大的内容。重复文......
  • App Cleaner & Uninstaller - mac系统清理和卸载
    AppCleaner&Uninstaller是一款功能强大的应用程序清理和卸载工具。在这800字的介绍中,我将向您详细说明AppCleaner&Uninstaller的特点、功能和优势。AppCleaner&Uninstaller获取 首先,AppCleaner&Uninstaller提供了一个简洁直观的界面,使用户能够轻松查找和删除......