欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JVM中的五种引用

程序员文章站 2022-06-10 14:30:29
...

JVM中的五种引用

JVM中的五种引用

  • 强引用:只有所有的GC Roots对象都不通过强引用引用该对象,该对象才能被垃圾回收
  • 软引用:软引用需要一个由一个GC Root对象指向一个专门的软引用对象(SoftReference对象),然后再由软引用对象指出。仅有软引用引用该对象时,在垃圾回收后,内存仍不足时会再次触发垃圾回收,回收如图上所示的A2对象;而软引用对象自身则配合引用队列释放自己。

软引用的应用场景:一些不是很重要的资源,当内存不足时可以释放掉。

// list --> SoftReference —-> byte[]
// list对SoftReference是强引用,但对SoftReference对byte[]是软引用
List<SoftReference<Byte[]>> list=new ArrayList<>();
ReferenceQueue<byte[]> queue=new ReferenceQueue<>();//引用队列
for(int i=0;i<5;++i){
	//关联了引用队列,当软引用所关联的byte[]回收时,软引用自己也会加入到queue中去
		SoftReference<Byte[]> ref=new SoftReference<>(new Byte[_4MB]);
		list.add(ref);
}
//从list中删除掉无效的引用
Reference<? Extends byte[]> poll=queue.poll();
while(poll!=null){
		list.remove(poll);
		poll=queue.poll();
}

如上面所示代码,用SoftReference类的实例对象指向一个Byte[]对象,这就是软引用,当虚拟机内存不足时,会回收掉这一部分;同时因为我们创建了一个引用队列,当软引用指向的对象被回收时它自己也会被加入到引用队列中等待回收。


  • 弱引用:仅有弱引用引用该对象时,在垃圾回收时,无论内存是否充足,都会回收A3;可以配合引用队列来释放弱引用自身。
  • 虚引用:以NIO为例,在创建ByteBuffer的时候,会创建一个名为Cleaner的虚引用对象,ByteBuffer会分配一个块直接内存,并把内存地址传递给Cleaner;这样做的目的是当ByteBuffer没有被强引用时,会被垃圾回收掉,但是直接内存并不能java的垃圾回收管理,此时Cleaner会进入引用队列,由Reference Handler线程调用Unsafe.freeMemory方法把直接内存释放掉。
  • 终结器引:Java中所有的类都继承自Object类,在Object类中有一个finalize()方法,如果某类重新了这个方法,那么当没有强引用引用时,虚拟机会创建一个终结器引用指向这个对象,把终结器引用加入到引用队列,再由一个优先级很低的线程Finalizer去调用A4的finalize()方法。(详解见JVM垃圾收集器笔记——死亡前的自救