Java直接内存回收

5 篇文章 0 订阅

  直接内存在面试中被问到还是挺多的。记得有次被问直接内存如何回收的?当时还有所准备,就回答 直接内存 属于堆外内存,不由gc直接回收,但是gc操作会触发回收操作。实际回收是由Cleaner完成,而Cleaner继承于幻引用(PhantomReference)。当时被问 由于幻引用不影响垃圾回收,有没可能Cleaner把直接内存回收了,但是直接内存的引用还有效呢,这不就有问题了么?当时心想还真是…
  显然不会出现这种情况:直接内存引用还有效的情况下,堆外内存被Cleaner偷偷的回收了。当时没能回答上来一方面是自己掌握的不够扎实,另一方面就是面试官混淆了概念把自己绕进去了。
  我们说幻引用指向不会影响对象的被回收,这个对象是指referent,而不是reference。
一个简单示意:

Object referent = new Object();
PhantomReference reference= new PhantomReference(referent, null);

  即:referent 什么时候被回收,跟reference 的引用没有关系。
  但referent 被回收收后,reference 是可以做一些事情的。这也是直接内存回收的大致逻辑。
DirectByDireteBuffer里初始化cleaner:

cleaner = Cleaner.create(this, new Deallocator(base, size, cap))

  this 是DirectByDireteBuffer。Deallocator 实现了Runnable ,run方法里面才是真正进行回收的地方。

  所以Cleaner不会在DirectByDireteBuffer 还有效的情况下提前 进行回收操作。只有DirectByDireteBuffer被判定为可回收之后才会触发 直接内存的回收操作。对于Cleaner具体细节可以搜索相关文档。
测试代码

 ByteBuffer byteBuffer = ByteBuffer.allocateDirect(1024 *  1024 * 256);
        byte[] data = new byte[1024 *  1024 * 256];
        Arrays.fill(data, (byte)1);
        byteBuffer.put(data);
        byteBuffer = null;
        System.gc();
        Thread.sleep(1000*600);

回收时调用栈
在这里插入图片描述
回收前后进程内存占用情况
在这里插入图片描述
第一列数差值两百多M左右,跟实际分配的内存大小差不多。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值