引用类型分四种类型:强、软、弱、虚
1. 强引用
强引用就是指在程序代码中普遍存在的,比如A a = new A();这类的引用还存在,GC就永远不会回收掉被引用的对象。
创建方式:A a = new A();
2. 软引用
软引用是用来描述一些还有用但并非必须的对象。对于软引用关联的对象,在系统将要发生内存溢出异常之前,将会把这些对象列进回收范围之中再次进行回收。如果这次回收还没有足够的内存,才会抛出内存溢出的异常。JDK提供了SoftReference类来实现软引用。
软引用回收的根本问题就是内存不够用了,内存不够用时,GC回收掉软引用相关连的对象。内存不够用自动调用GC。
使用场景:
JDK提供了SoftReference类来实现软引用。这个特性很适合用来实现缓存:比如网页缓存、图片缓存、聊天记录。当内存不够用时,自动回收掉这些缓存。
创建方式:
//引用队列:存储被GC回收之后的对象
ReferenceQueue<myArray> queue = new ReferenceQueue<>();
//创建软引用:w就是myArray的软引用
//将软引用与引用队列相关联
SoftReference<myArray> w = new SoftReference<>(new myArray(),queue);
软引用测试代码
class myArray{
byte[] arr = new byte[1024*1024*3]; // 3M
}
public class SoftReferenceTest {
public static void main(String[] args) {
//引用队列:存储被GC回收之后的对象
ReferenceQueue<myArray> queue = new ReferenceQueue<>();
//强引用
// myArray m = new myArray();
//创建软引用:w就是myArray的软引用
//将软引用与引用队列相关联
SoftReference<myArray> w = new SoftReference<>(new myArray(),queue);
System.out.println(queue.poll());
//内存为5M,new arr后内存不够用
byte arr[] = new byte[1024*1024*3];
System.out.println(queue.poll());
}
}
输出结果
3. 弱引用
弱引用也是用来描述非必须对象的,但是它的强度比软引用更弱一些,被弱引用关联的对象只能生存到下一次垃圾收集发生之前。当GC工作时,无论当前内存是否足够,都会回收掉只被若引用关联的对象。JDK提供了WeakReferece类来实现弱引用。
被弱引用关联的对象,当垃圾收集被触发时,不管内存够不够用,都会被回收掉。
使用场景:
适合用在缓存,比如看电影加载问题,没必要保留经看过的,重新看重新加载就好。
创建方式:
//引用队列:用来存储被GC回收掉的对象
ReferenceQueue<myArray> queue = new ReferenceQueue<>();
//weak为myArray的弱引用,并且与引用队列关联
WeakReference<myArray> weak = new WeakReference<>(new myArray(),queue);
弱引用测试代码
public class WeakReferenceTest {
public static void main(String[] args) {
//引用队列:用来存储被GC回收掉的对象
ReferenceQueue<myArray> queue = new ReferenceQueue<>();
//weak为myArray的弱引用,并且与引用队列关联
WeakReference<myArray> weak = new WeakReference<>(new myArray(),queue);
System.out.println(queue.poll());
//手动调用GC
System.gc();
System.out.println("-----------GC发生之后------------");
System.out.println(queue.poll());
}
}
结果:
4. 虚引用
虚引用是最弱的一种引用关系,一个对象是否有虚引用的存在,完全不会对其生存生存时间构成影响,也无法通过虚引用来取得一个对象的实例。由于PhantomReference来重写了获得对象的get方法,永远返回null,为一个对象设置虚引用关联的唯一目的就是你那个在这个对象被GC回收时,收到一个系统通知。
不会对对象造成任何影响,不会影响对象被回收的时机,该几时回收就几时回收。软引用和弱引用都会对对象造成影响。
虚引用的作用:
和引用队列联合使用,判断这个对象是否已经被回收了。
使用场景:
既想使用引用队列,又不想让对象的回收时机造成影响,需要使用弱引用。
创建方式:
//引用队列:存储被GC掉的对象
ReferenceQueue<myArray> queue = new ReferenceQueue<>();
//创建虚引用
PhantomReference<myArray> phan = new PhantomReference<>(new myArray(),queue);
虚引用测试代码
//虚引用
public class PhantomReferenceTest {
public static void main(String[] args) {
//引用队列:存储被GC掉的对象
ReferenceQueue<myArray> queue = new ReferenceQueue<>();
//创建虚引用
PhantomReference<myArray> phan = new PhantomReference<>(new myArray(),queue);
System.out.println(queue.poll());
//手动调用GC
System.gc();
try {
Thread.sleep(1000); //让GC充分发生
} catch (InterruptedException e) {
e.printStackTrace();
}
//队列能够获得到这个对象,说明这个对象被GC了
System.out.println(queue.poll());
}
}
结果
5. 总结
强引用:永远不会被GC回收
软引用:内存不够用时,GC发生时,软引用关联的对象会被回收掉
弱引用:不论聂村是否够用,当GC发生时,都会回收掉弱引用关联的对象
虚引用:不会对对象的回收时机造成任何影响
6. 垃圾回收机制
GC:垃圾回收机制,检测项目中是否有对象没有用了,如果检测到将使用垃圾回收机制将其回收。当内存不够用时,GC发生,这个只有软引用的对象就会回收掉。同时由于触发了GC弱引用也会被回收掉。
使用引用队列,判断这个对象确实被GC掉了,就会回收到队列中。
手动调用回收机制:
Systm.gc();
7. 引用队列
用来存储被GC回收掉的对象
//定义引用队列
ReferenceQueue<myArray> queue = new ReferenceQueue<>();
//创建虚引用与引用队列关联
PhantomReference<myArray> phan = new PhantomReference<>(new myArray(),queue);
引用队列可以与软引用、弱引用以及虚引用一起配合使用,当垃圾回收器准备回收一个对象时,如果发现对象还有引用,那么就会在回收对象之前,把这个引用加入到与之关联的引用队列中去。程序可以通过判断引用队列中是否已经加入了引用,来判断被引用的对象是否将要被垃圾回收,这样就可以在对象被回收之前采取一些必要的措施。