强引用、软引用、弱引用、幻象引用有什么区别?

强引用、软引用、弱引用、幻象引用有什么区别?
在java语言中,除了原始数据类型的变量,其他所有都是常用的引用类型,指向各种不同的对象,理解引用对于掌握java对象生命周期和jvm内部机关机制有着重要的作用

不同的引用类型,主要区别是:对象不同的可达性状态和对垃圾收集的影响
所谓强引用就是咱们普通的引用,只要还有强引用指向一个对象,就表明该对象还活着,垃圾收集器不会碰这样的对象,对于一个普通的引用,只要超过了引用的作用域且显式的将引用赋值为null,就可以被垃圾收集了
软引用就是相对于强引用的弱化一些的 引用,可以让对象豁免一些 垃圾收集,只有Jvm认为内存不足时,才会试图回收软引用指向的对象。软引用指向的对象(或者实现的是)通常是些敏感的缓存,如果还有空闲内存,可以暂时保留缓存,如果系统快要抛出oom异常的时候,就要删除软引用来保证内存存在
弱引用 并不能是对象豁免垃圾收集,,仅仅是提供一种访问在弱引用状态下对象的途径。维护一种非强制性的映射关系。如果试图获取的对象还在,就使用它,否则就重新实例。同样是许多缓存实现的选择
幻象引用 虚引用,不能通过它访问对象。幻想引用仅仅是提供了一种确保对象被finalize以后,做某些事情的机制。比如:上一节的Post-Mortem清理机制,java平台自身Claeaner机制等
利用幻想引用监控对象的创建和销毁

诊断MySql connector -j 驱动在特定模式下(useCompression =true)的内存泄露问题

扩展
强可达:就是当一个对象可以有一个或多个线程可以不通过各种引用访问到的情况。比如:我们创建一个对象,创建它的线程对它就是强可达
软可达:就是我们只能通过软引用才能访问到的对象的状态
弱可达:无法通过强引用和软引用访问,只能通过弱引用访问到的状态,十分临进finalize状态的时机
幻象可达:与上述三种引用均无关联,只是在finalize后,只有幻象可达指向这个对象
不可达: 意味着对象可以被清除了

判断对象可达性,是JVM垃圾收集器决定如何让处理对象的一部分考虑

所有引用类型,都是抽象类java.lang.ref.Reference的子类,它提供了get方法:
除了幻象引用外,如果对象还没有被销毁,都可以通过get方法获取原有对象。这意味着,通过软引用和弱引用,我们都可以将访问到的对象,重新指向强引用。

引用队列(ReferenceQueue)的使用
我们创建各种引用并关联到相应对象时,我们可以选择是否需要关联到引用队列,JVM会在特定时机将引用enqueue到队列里,我们可以从队列里获取引用(remove)
尤其是幻想引用,get方法也获取不到,如果再不指定引用队列,那基本上是毫无用处了。处于幻象可达状态时,执行以下处理逻辑

Object counter = new Object();
ReferenceQueue refQueue = new ReferenceQueue<>();
PhantomReference<Object> p = new PhantomReference<>(counter, refQueue);
counter = null;
System.gc();
try {
    // Remove是一个阻塞方法,可以指定timeout,或者选择一直阻塞
    Reference<Object> ref = refQueue.remove(1000L);
    if (ref != null) {
        // do something
    }
} catch (InterruptedException e) {
    // Handle it
}

显式的影响软引用垃圾收集
对于软引用,我们一直对其垃圾收集机制飘忽不定,我们可以用什么方法来影响垃圾收集?
软引用通常都会在最后一次引用后,还能保存一段时间,默认值是以剩余空间计算的。
我们可以以毫秒来单位设置:
-XX:SoftRefLRUPolicyMSPerMB=3000
如果你怀疑引用(finalize)导致的回收问题
可以通过PrintReferebceGC去获取相关信息
jdk8使用ParrllelGC日志,各种引用非常清晰可查

©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页