主要目的?
可人为通过代码的方式去决定某个对象的生命周期。
有利于垃圾回收。
四种引用主要特点:
强引用:我就是不回收,宁愿抛出一个e
rror "OOM"也不回收。
软引用:内存不足就回收
弱引用:不管内存够不够,只要清理就回收。
虚引用:只要清理,就回收,但是会把回收通知放进一个ReferenceQueue中。
强引用:
强应用是我们用到最多的,
Object object = new Object();
这个就是强引用,只要某个对象具有强引用,那这个对象就不会被回收。就算内存空间不够用了,JVM已经抛出OOM错误了,程序都终止运行了,这个具有强引用的对象也不会被回收。也就是说JVM不会依靠回收具有强引用的对象来解决内存空间不足的问题。
那什么时候会去回收强引用对象呢?很简单,弱化它,让强引用与对象中断。
object = null;
这样JVM就可以实现清理。
软引用:
具有弱引用的对象,在内存空间足够的时候,垃圾回收不会进行回收,但是当内存不够用时,就会去回收这些对象。
软应用就是把对象用SoftReference处理一下,当我们需要获取这个对象的时候,就get一下这个软引用对象。
public static void main(String[] args) {SoftReference<String> hqz = new SoftReference<String>(new String("hello,world!"));System.out.println(hqz.get());}
做个实验:
public static void main(String[] args) {//我先给一下软引用对象,里面包个byte[],大小1000M.SoftReference<byte[]> hqz = new SoftReference<byte[]>(new byte[1024*1024*1000]);System.out.println(hqz.get());//手动gcSystem.gc();System.out.println(hqz.get());//再给一个byte[]大小1000M.byte[] bytes = new byte[1024 * 1024 * 1000];System.out.println(hqz.get());}
先看一下结果:
[B@14ae5a5[B@14ae5a5null
这个运行结果第一行结果就是这个byte[],不用管它是什么,
地方行结果是在手动GC后输出的,和第一次一样,也就是说手动清理后这个byte[]还是在的。这个时候我再创建一个大小1000M的byte[],发现输出编程null了,这个意思也就是这个时候最大堆内存满了,不够用了,然后就把这个软引用包的这个byte[]给清理了。这也即使:内存不够才回收。
软引用比较适合用作缓存,内存够用,那就继续拿缓存,不够用了,我就先清理点缓存。
弱引用:
弱引用和软引用区别不大,就是把softReference换成
WeakReference。
public static void main(String[] args) {WeakReference<byte[]> hqz = new WeakReference<byte[]>(new byte[1024*1024*1000]);System.out.println(hqz.get());System.gc();System.out.println(hqz.get());}
结果:
[B@14ae5a5null
结合刚才软引用的实验,能看出来,当创建一个大小1000M的byte[]时,内存肯定是够的,但是再手动gc后,第二次直接输出null,byte[]已经被清理了。
这也就是说 弱引用不管内存够不够,只要清理,就会被回收。但是垃圾回收器又不一定能很快发现这个具有弱引用的对象,因为垃圾回收器的线程优先级还是挺低的。
虚引用:
顾名思义,形同虚设,有没有虚引用其实无所谓,和没有引用一,任何时候都会被回收。但是虚引用必须和引用队列
ReferenceQueue
一起用。再垃圾回收器回收对象的时候,发现这个对象具有虚引用,那么就在回收内存之前,先把它加入到关联的队列种。
public static void main(String[] args) {ReferenceQueue<String> qqq= new ReferenceQueue<String>();PhantomReference<String> hqz = new PhantomReference<String>(new String("hello,world!"), qqq);System.out.println(hqz.get());}
结果:
null