0
点赞
收藏
分享

微信扫一扫

DirectBuffer的释放探究

芒果六斤半 2021-09-28 阅读 54
码哥

基础知识

  • java中mmap过程如下,最终的mappedByteBuffer实际是一个DirectByteBuffer对象
        File file = new File("xxx");
        FileChannel fileChannel = new RandomAccessFile(file, "rw").getChannel();
        MappedByteBuffer mappedByteBuffer = fileChannel.map(MapMode.READ_WRITE, 0, 4096);

  • 看一下DirectByteBuffer构建源码,可以看到每一个DirectByteBuffer都会包含一个Cleaner实例(视图viewer没有)

  • Cleaner里面是利用的虚引用,当DirectByteBuffer对象被垃圾回收时,会调用构造Cleaner时传入的回调方法,对MappedByteBuffer来说就是执行unmap,具体逻辑在FileChannelImpl的内部类Unmapper。对普通DirectByteBuffer来说就是Deallocator中的unsafe.freeMemory()
  • 当我们想要主动释放内存映射时,最简单的办法就是直接调用((DirectBuffer) mappedByteBuffer).cleaner().clean()

进阶部分

  • 后来了解到Cleaner类在java9前后的包是不一样的,所以如果代码里持有Cleaner的对象,就不能在所有jdk中编译了,当然直接调用((DirectBuffer) mappedByteBuffer).cleaner().clean()肯定没有问题
java9前:sun.misc.Cleaner
java9后:java.lang.ref.Cleaner
  • 联想到netty是直接内存使用大户,看下netty中的做法。netty中有两个类CleanerJava6、CleanerJava9对应不同的jdk版本分别使用

rocket中的做法

  • 在rocket中unmap的逻辑如下,也是通过反射调用clean()方法,和我之前就关注的一个同学的博客做法完全一致,希望以后面基 :)

疑惑思考

  • 为啥大家都非要用反射来调用clean呢?((DirectBuffer) mappedByteBuffer).cleaner().clean()简单粗暴不香吗?还有就是viewed()方法中的viewedBuffer是什么,没看到有这个名字的方法啊?
举报

相关推荐

0 条评论