java中的四种引用类型
Java中有四种引用类型:强引用、软引用、弱引用、虚引用。
强引用
强引用是最常见的一种引用类型,在实际开发中,几乎都是强引用类型。
Object obj = new Object();
当我们的对象有强引用的时候,即使内存不足,JVM宁愿抛出OOM,也不会把该对象回收掉。如果需要让垃圾回收器回收此对象,需要将强引用关系打破,最简单的方式就是将对象赋值为null。
扩展知识:
java在回收对象时,都会调用对象的finalize()方法,我们可以重写此方法来查看对象被回收的情况。
但是在生产环境上,一定不要去重写 finalize() 方法,有内存溢出的风险。由于每个对象在进行垃圾回收时都会去调用该对象的 finalize() 方法,该方法默认是空的,啥都没做,执行效率是非常快的。但是如果重写后就会影响垃圾回收的效率,假设此时业务上还有大量的对象产生,垃圾回收的效率小于对象产生的效率,时间一长就会内存溢出。
软引用
软引用就是用 SoftReference 将引用对象包装一下,通过 get() 方法获取包装的对象,使用方式如下:
SoftReference<byte[]> softReference = new SoftReference<>(new byte[1024 * 1024 * 10]);
softReference.get();//获取软引用对象
软引用的特点:在系统将要发生内存溢出异常之前,将会把这些对象实例列进回收范围之中进行第二次回收。如果这次回收还没有足够的内存,才会抛出内存溢出异常。
也就是当JVM进行垃圾回收时,如果第一次回收后内存足够,那么不会回收软引用对象;如果第一次回收后内存依旧不够,那么就会回收掉软引用对象。
根据这个特点,软引用可以用来做缓存,当系统内存足够时,通过缓存获取值,如果内存不够时,先回收掉缓存,释放一定的内存空间,延迟OOM。
弱引用
弱引用也是用来描述非必需对象的,但是它的强度比软引用更弱一些 ,被弱引用关联的对象实例只能生存到下一次垃圾收集发生之前。当垃圾收集器工作时,无论当前内存是否足够,都会回收掉只被弱引用关联的对象实例 。在JDK 1.2之后,提供了WeakReference类来实现弱引用。 来看下WeakReference的源码:
public class WeakReference<T> extends Reference<T> {
public WeakReference(T referent) {
super(referent);
}
public WeakReference(T referent, ReferenceQueue<? super T> q) {
super(referent, q);
}
}
WeakReference(T referent): referent就是被弱引用的对象(注意区分弱引用对象和被弱引用的对应,弱引用对象是指WeakReference的实例或者其子类的实例),比如有一个Apple实例apple,可以如下使用,并且通过get()方法来获取apple引用。也可以再创建一个继承WeakReference的类来对Apple进行弱引用,下面就会使用这种方式。 WeakReference(T referent, ReferenceQueue<? super T> q): 与上面的构造方法比较,多了个ReferenceQueue,在对象被回收后,会把弱引用对象,也就是WeakReference对象或者其子类的对象,放入队列ReferenceQueue中,注意不是被弱引用的对象,被弱引用的对象已经被回收了。
WeakReference<Order> weakReference = new WeakReference<>(new Order());
// 获取弱引用的值
System.out.println(weakReference.get());
而ThreadLocalMap中是如何使用的呢?
它继承了WeakReference类,在该类的构造方法,调用父类WeakReference类的构造方法,传入了ThreadLocal类的对象,也就是这个ThreadLocal对象是一个被弱引用的对象。
虚引用
1、 例如: PhantomReference a = new PhantomReference(new A(), referenceQueue);
2、 也称为幽灵引用或者幻影引用,它是最弱的引用关系。无法通过虚引用来取得一个对象实例。 为一个对象设置虚引用关联的唯一目的就是能在这个对象被收集器回收时收到一个系统通知。PhantomReference类来实现虚引用。
2、必须配合引用队列一起使用,当虚引用所引用的对象被回收时(a对象、b对象),由 Reference Handler 线程将虚引用对象入队,这样就可以知道哪些对象被回收,从而对它们关联的资源做进一步处理。
总结
1、对于强引用,平时在编写代码时会经常使用。
2、而其他三种类型的引用,使用得最多就是软引用和弱引用,这两种既有相似之处又有区别,他们都来描述非必须对象。
3、被软引用关联的对象只有在内存不足时才会被回收,而被弱引用关联的对象在JVM进行垃圾回收时总会被回收。
4、Java中4种引用的级别由高到低依次为:强引用 > 软引用 > 弱引用 > 虚引用