在NIO技术中,使用allocateDirect()方法可以创建直接内存;如何释放该内存呢?

(1)通过手动释放内存(Cleaner+虚引用)
(2)交给JVM进行处理(Full GC)

文章目录

  • 1.直接内存的创建与销毁
  • 2.通过Cleaner+虚引用完成堆外内存回收
  • 3.总结创建与销毁流程
  • 4.如何一步步顺序解读源码流程
  • 5.使用直接内存的利弊分析

1.直接内存的创建与销毁

base = UNSAFE.allocateMemory(size);

在DirectByteBuffer类构造方法中,主要通过allocateMemory方法完成堆外内存的创建,这个方法是Unsafe类中,这个类是干什么的呢?通过名字我们可以也可以看出这个类是不安全的,也就是它是能够直接操作堆外内存,超出了JVM的管辖范围!

UNSAFE.freeMemory(address);

需要注意的是通过Unsafe开辟的直接内存,需要通过调用freeMemory手动回收(当然帮你写了)

2.通过Cleaner+虚引用完成堆外内存回收

Java对象有四种引用方式:强软弱虚
虚引用PhantomReference一般来说极少使用,而且它不能单独使用,它需要和引用队列 ReferenceQueue一块使用

首先分析allocateDirect()方法底层(DirectByteBuffer类)

通过它的构造方法可以看出创建了Cleaner对象和Deallocator对象,首先分析Cleaner对象,通过看它的源码可以得出,它的底层维护了一个双向链表,当Cleaner对象初始化时,就会加入到这个Cleaner双向链表中(而且是安全的,使用了Synchronized,Cleaner类继承了虚引用)

   public static Cleaner create(Object ob, Runnable thunk) {if (thunk == null)return null;return add(new Cleaner(ob, thunk));}

当DirectByteBuffer对象不存在时,Cleaner对象不再处于引用链中,等到下一次GC时,Cleaner会被加入到ReferenceQueue队列中,并执行clean方法;将将自身从Cleaner双向链表中移除(remove),然利用多态调用了Deallocator类中的run方法释放内存

public void clean() {if (!remove(this))return;try {thunk.run();} catch (final Throwable x) {AccessController.doPrivileged(new PrivilegedAction<>() {public Void run() {if (System.err != null)new Error("Cleaner terminated abnormally", x).printStackTrace();System.exit(1);return null;}});}}
public void run() {if (address == 0) {// Paranoiareturn;}UNSAFE.freeMemory(address);address = 0;Bits.unreserveMemory(size, capacity);}

3.总结创建与销毁流程

分析下图总结流程(来源百度图片)

初始时,创建了一个DirectByteBuffer对象,在DirectByteBuffer的构造函数中创建了一个Cleaner对象和Deallocator对象;Cleaner对象初始化时将自身加入到了链表中;一旦DirectByteBuffer对象被回收,那么下次GC时Cleaner(继承了虚引用)对象会被放到ReferenceQueue队列中并执行clean方法(多态调用了Deallocator中的run方法释放内存)


4.如何一步步顺序解读源码流程

(1)ByteBuffer抽象类的allocateDirect方法

(2)DirectByteBfufer的构造方法
(3)Cleaner类的create方法
(4)Cleaner类的add方法
(5)回到第二步

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

(6)Deallocator类的构造方法

将Cleaner类中分配的直接内存的地址、大小等进行复制,因为这个类的run方法是进行内存回收的根方法。

5.使用直接内存的利弊分析

使用直接内存肯定也有坏处,否者还有堆内存什么事;使用直接内存不受JVM的管辖,稍有不慎容易造成内存泄漏!当然使用直接内存减少了GC的时间(交给了操作系统进行管理),另一方面与磁盘交互时使用直接内存减少了复制操作,效率得到提高。

【大白话系列】深入浅出Cleaner+虚引用完成堆外内存的回收相关推荐

  1. Java 四种引用类型:强引用、软引用、弱引用、虚引用

    以前学习强软弱虚引用的时候,只是走马观花看看博客,并没有自己写代码去实践.去证明,导致每次看完后,过不了多久就忘了,后来下定决心,一定要自己敲敲代码,这样才能让印象更加深刻,古人云:纸上得来终觉浅,绝 ...

  2. 强软弱虚引用,只有体会过了,才能记住

    以前学习强软弱虚引用的时候,只是走马观花看看博客,并没有自己写代码去实践.去证明,导致每次看完后,过不了多久就忘了,后来下定决心,一定要自己敲敲代码,这样才能让印象更加深刻,古人云:纸上得来终觉浅,绝 ...

  3. 阿里面试: 说说强引用、软引用、弱引用、虚引用吧

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 我们都知道 JVM 垃圾回收中,GC判断堆中的对象实例或数 ...

  4. java-基础-强、软、弱、虚引用

    Java的四种引用,强弱软虚,用到的场景. JDK1.2之前只有强引用,其他几种引用都是在JDK1.2之后引入的. 强引用(Strong Reference) 最常用的引用类型,如Object obj ...

  5. 回过头来看对象的四种状态强软弱虚引用的理解

    一.对象的四种引用状态描述 在JDK1.2之后,Java对引用的概念进行了扩充,将引用分为强引用(Strong Reference).软引用(Soft Reference).弱引用(Weak Refe ...

  6. java 对象引用 弱引用吗_Java对象的强引用、软引用、弱引用和虚引用 笔记

    从JDK1.2版本开始,把对象的引用分为四种级别,从而使程序能更加灵活的控制对象的生命周期.这四种级别由高到低依次为:强引用.软引用.弱引用和虚引用. 1.强引用 使用最普遍的引用.如果一个对象具有强 ...

  7. 那些令人发燥的JAVA虚引用

    在Java的世界里,对象的存在层次,也有三六九等,充满了阶层之间的嘲弄.强软弱虚各种引用,对于熟悉Java的同学一定不会感到陌生,它们随着等级的降低,越来越没存在感.平常使用的对象,大多数就是强引用的 ...

  8. java基础-----弱引用,软引用,强引用,虚引用

    转自:http://www.cnblogs.com/blogoflee/archive/2012/03/22/2411124.html 1.概述 在JDK1.2以前的版本中,当一个对象不被任何变量引用 ...

  9. 强引用 弱引用 软引用 虚引用 的区别以及使用场景

    一·. 强引用(Strong Reference) 我们使用的大部分的引用都是强引用,这是使用最普遍的引用.如果一个对象具有强引用,那就类似于必不可少的生活用品,垃圾回收器绝不会回收它.当内存空间不足 ...

最新文章

  1. 小米做的这件事,捍卫了你的隐私
  2. 虚拟桌面最佳组合---Windows 7
  3. 脚本:获取CSDN文章的访问量
  4. 在Editplus中搭建Ruby开发环境
  5. Android之提示Could not find com.android.support:appcompat-v7:25.3.1.
  6. cf1556B B. Take Your Places!
  7. Linux的SOCKET编程 简单演示
  8. oracl 单行字符型函数
  9. STM32之SysTick例程
  10. 假如给Go语言加上注解,程序会变怎样?
  11. Linux之父和Redis之父,Redis之父:10x程序员应该具备哪些素质
  12. Javascript加号的作用、数据类型、输入用户的输入第四课
  13. Java加密的几种方式
  14. 计算机cad知识,计算机与Cad制图知识点.doc
  15. Linux嵌入式系统的电子相册代码,基于嵌入式Linux和Qt编程实现数码相框的设计
  16. H3C新华三笔记本FN键锁定
  17. kali linux 怎么攻击IP,Kali Linux实战篇:Ettercap 使用教程 DNS欺骗攻击实战
  18. 7.交易开拓者-公式进阶(一)
  19. 商城-商品规格管理-商品规格参数管理
  20. 国家与地区缩写 + 各国语言缩写

热门文章

  1. 学习总结初篇:发现问题
  2. controller需要捕获异常吗_Spring之Controller异常处理
  3. java类加载器_类加载器
  4. java成果_JAVA WEB期末项目第二阶段成果
  5. 数组排序思想———选择排序
  6. CSS基本选择器、层次选择器、结构伪类选择器、属性选择器
  7. mysql 重启失败,重启MySQL服务失败
  8. python输入水果求个数问题_水果爱好者:用Python解决一个简单的分类问题
  9. 软工专硕考研_分析|华北电力(北京)大学20计算机考研报录分析!电子信息复试狂刷114人,软工专硕复试录取高达1:4.7!...
  10. 二、 elasticsearch安装和概念