垃圾回收+五种引用

判断垃圾是否可以回收--引用计数

当有引用的时候,引用计数加一,没有引用计数时减一,当引用计数变为0时,将会被当成垃圾进行回收。但是有一个弊端如图:

当对象之间相互循环引用时,两者的引用计数都是1,即使没有别的对象对他进行引用,他们也不会被回收,此时就会造成内存上的泄露;Java中没有采用引用计数法,早期的python采用过;

判断垃圾是否可以回收--可达性分析算法

Java中采用可达性分析算法;

可达性分析算法中首先要确定根对象,根对象就是那些肯定不能被当成垃圾进行回收的对象;如果一个对象被根对象进行直接或者间接的使用,将不会被回收;如果一个对象没有被根对象进行直接或者间接的使用将会被回收;

总结:Java虚拟机中的垃圾回收器采用可达性分析来探索所有存活的对象;扫描堆中的对象,看是否能够沿着GC Root对象为起点的引用链找到该对象,找不到,表示可以回收。

五种引用的分类:

  1. 强引用
  2. 软引用
  3. 弱引用
  4. 虚引用
  5. 终结器引用

  • 图中实心箭头线表示强引用,在编写代码时new一个对象都是强引用,如果从GC Root 有路径可以到达,那么该对象不会被垃圾回收器回收,如果没有路径可以到达,那么会被垃圾回收器回收;
  • 软引用+弱引用:当A2、A3没有直接的被强引用引用时,将会被垃圾回收器回收;例如:对象C通过软引用对A2对象进行引用,同时对象B对A2对象进行强引用,此时A2对象不会被回收;如果对象B不再对A2对象进行强引用了,此时只有对象C通过软引用对A2对象进行引用,此时A2对象将会被回收。什么情况下会被回收呢?垃圾回收时并且内存不够时;
  • 软引用+弱引用:当A2、A3没有直接的被强引用引用时,当内存不够时会回收A2对象,不管内存够不够,A3对象都会被回收;
  • 软引用和弱引用所指的对象被回收之后,如果软引用和弱引用配合引用队列进行使用的话,因为软引用和弱引用本身也是对象,所以他们将会进入引用队列,并对他俩进行内存释放;

  • 软弱引用可以不配合引用队列使用,但是虚引用和终结器引用必须要配合引用队列使用;如果ByteBuffer被回收掉了,此时ByteBuffer所指的直接内存还没有被回收掉,那么虚引用将会进入引用队列,然后会在引用队列中被遍历,利用cleaner根据直接内存的地址,手动调用unsafe.freeMemory进行直接内存回收;

  • 终结器引用:当A4对象不再被强引用时,虚拟机将会创建一个终结器引用,该终结器引用将会进入引用队列中,当引用队列发现里面有一个终结器引用之后,将会调用终结器引用指向的对象A4中的finalize()方法进行对象的回收;

四种引用总结:

  • 强引用
  1. 只有所有GC Roots对象都不通过【强引用】引用该对象,该对象才能被垃圾回收
  • 软引用(SoftReference)
  1. 仅有软引用引用该对象时,在垃圾回收后,内存仍不足时会再次出发垃圾回收,回收软引用对象
  2. 可以配合引用队列来释放软引用自身
  • 弱引用(WeakReference)
  1. 仅有弱引用引用该对象时,在垃圾回收时,无论内存是否充足,都会回收弱引用对象
  2. 可以配合引用队列来释放弱引用自身
  • 虚引用(PhantomReference)
  1. 必须配合引用队列使用,主要配合ByteBuffer使用,被引用对象回收时,会将虚引用入队,由Reference Handler线程调用虚引用相关方法释放直接内存
  • 终结器引用(FinalReference)
  1. 无需手动编码,但其内部配合引用队列使用,在垃圾回收时,终结器引用入队(被引用对象暂时没有被回收),再由Finalizer线程通过终结器引用找到被引用对象并调用它的finalize方法,第二次GC时才能回收被引用对象
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值