java之虚引用及其适用场景
写在前面本文看下虚引用以及其相关内容。1虚引用以及其使用场景虚引用使用在需要监听对象的回收操作并在对象回收时执行某些操作的场景。如下例子// JVM 配置-Dfile.encodingutf-8 -Xms20m -Xmx20mpackagecom.demo.xx;importjava.lang.ref.PhantomReference;importjava.lang.ref.Reference;importjava.lang.ref.ReferenceQueue;importjava.util.*;publicclassLoadByClassLoader{publicstaticvoidmain(String[]args)throwsException{// 创建引用队列ReferenceQueueObjectreferenceQueuenewReferenceQueue();// 创建一个大对象ObjectobjnewObject();System.out.println(对象创建: obj);// 创建虚引用PhantomReferenceObjectphantomRefnewPhantomReference(obj,referenceQueue);// 尝试通过虚引用获取对象 - 总是返回nullSystem.out.println(通过虚引用获取对象: phantomRef.get());// 将强引用置为null使对象变为可回收objnull;// 检查引用队列// Reference? ref null;newThread(()-{try{Reference?refreferenceQueue.remove();if(ref!null){System.out.println(对象已被回收收到通知);System.out.println(回收的引用: ref);}}catch(InterruptedExceptione){e.printStackTrace();}}).start();ListStringobjsnewArrayList();for(inti0;iInteger.MAX_VALUE;i){objs.add(newString(UUID.randomUUID().toString()));Thread.sleep(1);}}}运行对象创建: java.lang.Object15db9742 通过虚引用获取对象: null 对象已被回收收到通知 回收的引用: java.lang.ref.PhantomReference3694916f2实际的使用场景2.1NIO堆外内存释放java.nio.ByteBuffer.allocateDirect:publicstaticByteBufferallocateDirect(intcapacity){returnnewDirectByteBuffer(capacity);}构造函数DirectByteBuffer(intcap){// package-private...cleanerCleaner.create(this,newDeallocator(base,size,cap));attnull;}这里cleaner就是一个虚引用关联到了bufferpublicclassCleanerextendsPhantomReferenceObject{}Deallocator是真正的在buffer被回收时释放堆外内存的类privatestaticclassDeallocatorimplementsRunnable{// ...publicvoidrun(){if(address0){// Paranoiareturn;}// 释放堆外内存!!!unsafe.freeMemory(address);address0;Bits.unreserveMemory(size,capacity);}}3重要特性ref.get方法永远返回null不要指望通过get方法获取指向的实际对象。必须配合ReferenceQueue一起使用jdk就是这么设计的所以只能这么用。比finalize更可靠finalize首先不一定保证执行并且可能会带来性能问题而虚引用更靠谱。所以如果你遇到类似的业务需求无脑使用就对了。写在后面参考文章列表