JDK的4种引用类型
在java中,大致有以下几种引用类型,强引用(StrongReference)、软引用(SoftReference)、弱引用(WeakReference)、虚引用(PhantomReference)
--- 强引用-FinalReference
强引用是平时最常见的,类似诸如
String a = new String("helloworld");
这个a就是强引用类型,最主要的一点是:即使内存不够,程序宁愿抛出异常,也不会去进行回收
--- 软引用-SoftReference
软引用(softReference)在强度上弱于强引用,通过类 SoftReference 来表示。它的作用是告诉垃圾回收器,程序中的哪些对象是不那么重要,当内存不足的时候是可以被暂时回收的。当JVM中的内存不足的时候,垃圾回收器会释放那些只被软引用所指向的对象。如果全部释放完这些对象之后,内存还不足,才会抛出OutOfMemory错误。软引用非常适合于创建缓存。当系统内存不足的时候,缓存中的内容是可以被释放的。
比如考虑一个图像编辑器的程序。该程序会把图像文件的全部内容都读取到内存中,以方便进行处理。而用户也可以同时打开多个文件。当同时打开的文件过多的时候,就可能造成内存不足。如果使用软引用来指向图像文件内容的话,垃圾回收器就可以在必要的时候回收掉这些内存。
--- 弱引用-WeakReference
弱引用的强度弱于软引用,简单来说就是,一旦某个引用不需要使用的时候,JVM就会自动回收,而程序员本身无须做其他操作,在Java源码中的java.util.WeakHashMap
中的key
就是使用弱引用
--- 虚引用-PhantomReference
在介绍虚引用之前,要先介绍Java提供的对象终止化机制(finalization)。在Object类里面有个finalize方法,其设计的初衷是在一个对象被真正回收之前,可以用来执行一些清理的工作。因为Java并没有提供类似C++的析构函数一样的机制,就通过 finalize方法来实现。但是问题在于垃圾回收器的运行时间是不固定的,以这些清理工作的实际运行时间也是不能预知的。虚引用(phantom reference)可以解决这个问题。在创建虚引用PhantomReference的时候必须要指定一个引用队列。当一个对象的finalize方法已经被调用了之后,这个对象的虚引用会被加入到队列中。通过检查该队列里面的内容就知道一个对象是不是已经准备要被回收了。
举个栗子
package com.xxg; import java.io.Serializable; import java.lang.ref.PhantomReference; import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; import java.lang.ref.WeakReference; public class PhantomBuffer { public static void main(String[] args) throws InterruptedException { //强引用类型:变量strongReference对对象的引用为强引用 User strongReference = new User("strongReference"); System.out.println(strongReference.getName()); //strongReference //弱引用类型: 变量weakReference对对象的引用为弱引用 WeakReference<User> weakReference = new WeakReference<User>(new User("weakReference")); System.out.println(weakReference.get().getName()); //weakReference //弱引用测试 System.out.println(weakReference.get());//user对象 System.gc();//调用jvm 垃圾回收器(不一定立即执行) Thread.sleep(10000);//阻塞线程10秒,等待gc执行 System.out.println(weakReference.get()); //null //软引用类型: 变量softReference对对象的引用为软引用 SoftReference<User> softReference = new SoftReference<User>(new User("softReference")); System.out.println(softReference.get().getName()); //softReference System.out.println(softReference.get()); //com.xxg.PhantomBuffer$User@6d06d69c //虚引用类型: PhantomReference<User> phantomReference = new PhantomReference<User>(new User("phantomReference"), new ReferenceQueue<>()); System.out.println(phantomReference.get()); //null } static class User implements Serializable{ private static final long serialVersionUID = 1L; private String name; public User(String name){ this.name = name; } public String getName(){ return name; } public void setName(String name) { this.name = name; } } }
参考资料:Java 四种引用介绍及使用场景