JVM的引用
- 我们希望能描述这样一类对象:当内存空间还足够的时候,如果内存空间在进行垃圾收集后还是很紧张,则可能抛弃这些对象,
-【既偏门又非常高频的面试题】强引用、软引用、弱引用、虚引用有什么区别?具体使用.场景是什么? - 在在JDK 1.2版之后,Java对引用的概念进行了扩充,将引用分为强引用(Strong Reference)、软引用(Soft Reference) 、弱引用(Weak Reference) 和虚引用(Phantom Reference) 4种,这4种引用强度依次逐渐减弱。
- 除了强引用外,其他3种引用均可以在java.lang.ref包中找到它们的身影。如下图,显示了这3种引用类型对应的类,开发人员可以在应用程序中直接使用它们。
Reference子类中只有终结器引用是包内可见的(该类没有被public修饰),其他3种引用类型均为public class,可以在应用程序中直接使用。
对于强、软、弱、虚这四种引用对象的垃圾回收特点的描述,都是指的在引用关系还存在的情况下:
- 强引用(StrongReference):最传统的“引用”的定义,是指在程序代码中普遍存在的引用赋值,即类似“0bject obj=new object( )”这种引用关系。无论任何情况下,只要强引用关系还存在,垃圾收集器就永远不会回收掉被引用的对象。
- 软引用(SoftReference) :在系统将要发生内存溢出之前,会把这些对象列入回收范围之中,以备进行第二次(第一次指的是回收了不可触及的垃圾对象)垃圾回收的时候回收它们。如果这次回收后还没有足够的内存,才会抛出内存溢出异常。
- 弱引用(WeakReference):被弱引用关联的对象只能生存到下一次来及收集之前,当垃圾收集器工作时,无论内存空间是否足够,都会回收掉被弱引用关联的对象。
- 虚引用(PhantomReference) :一个对象是否有虛引用的存在,完全不会对其生存时 间构成影响,也无法通过虚引用来获得一个对象的实例。为一个对象设置虛引用关联的唯一目的就是能在这个对象被收集器回收时收到一个系统通知(回收跟踪)。
强引用:不回收
- 在Java程序中,最常见的引用类型是强引用(普通系统99%以上都是强引用),也就是我们最常见的普通对象引用,也是默认的引用类型。
- 当在Java语言中使用new操作符创建一个新的对象, 并将其赋值给一个变量的时候,这个变量就成为指向该对象的一个强引用。
- 强引用的对象是可触及的(可达的),垃圾收集器就永远不会回收掉被引用的对象。
- 对于一个普通的对象,如果没有其他的引用关系,只要超过了引用的作用域或者显式地将相应(强)引用赋值为null,才可以当做垃圾被收集,当然具体回收时机还是要看垃圾收集策略。
- 相对的,软引用、弱引用和虚引用的对象都是软可触及、弱可触及和虚可触及的,在一定条件下,都是可以被回收的,所以,强引用是造成Java内存泄露的主要原因之一
示例代码:
public class StrongReferenceTest {
public static void main(String[] args) {
StringBuffer str = new StringBuffer ("Hello,尚硅谷");
StringBuffer str1 = str;
str = null;
System.gc();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(str1);
}
}
StringBuffer str = new StringBuffer (“Hello,尚硅谷”);
局部变量str指向StringBuffer实例所在堆空间,通过str可以操作该实例,那么str就是StringBuffer实例的强引用。
对应内存结构:
此时,如果再运行一个赋值语句:StringBuffer str1 = str;
对应内存结构:
本例中的两个引用,都是强引用,强引用具备以下特点:
- 强引用可以直接访问目标对象
- 强引用所指的对象子啊任何时候都不会被系统回收,虚拟机宁愿抛出OOM异常,也不会回收强引用的对象
- 强引用可能导致内存泄露
软引用:内存不足即回收
- 软引用是来 描述一 些还有用,但非必需的对象。只被软引用关联着的对象,在系统将要发生内存溢出异常前,会把这些对象列进回收范围之中进行第二次回收,如果这次回收还没有足够的内存,才会抛出内存溢出异常。
- 软引用通常用来实现内存敏感的缓存。比如:高速缓存就有用到软引用。如果还有空闲内存,就可以暂时保留缓存,当内存不足时清理掉,这样就保证了使用缓存的同时,不会耗尽内存。
- 垃圾回收器在某个时刻决定回收软可达的对象的时候,会清理软引用,并可选地把引用存放到一个引用队列( Reference Queue)。
- 类似弱引用,只不过java虚拟机会尽量让软引用的存活时间长一些,迫不得已才清理
- 软引用:
- 当内存足够: 不会回收软引|用的可达对象
- 当内存不够时: 会回收软引用的可达对象
- 在JDK1.2版本之后,提供了java.lang.ref.SoftReference类来实现软引用。
Object obj = new object(); //声明强引用
SoftReference<0bject> sf = new SoftReference<0bject>(obj);