美文网首页
Java引用

Java引用

作者: 囧囧有神2号 | 来源:发表于2018-05-06 00:11 被阅读0次

四种引用:强引用,软引用,弱引用,虚引用
为什么要引入不同引用的概念?之前由于内存小,对象就两种状态,要么被引用,要么被清除,随着内存的扩大,java充实了对象的状态,于是就有了这四种引用;

强引用

你的代码中绝大多数都是强引用。
如果一个对象,GC root可达,GC清理宁可抛出OOM异常终止程序,也不会清理掉它;

软引用

用于描述那些不是必需的对象,但由于内存充足可保留,适合用作缓存。那么GC什么时候能够清理掉软引用呢?

public class SoftReference<T> extends Reference<T> {

    /**
     * Timestamp clock, updated by the garbage collector
     */
    static private long clock;

    /**
     * Timestamp updated by each invocation of the get method.  The VM may use
     * this field when selecting soft references to be cleared, but it is not
     * required to do so.
     */
    private long timestamp;

    public SoftReference(T referent) {
        super(referent);
        this.timestamp = clock;
    }


    public SoftReference(T referent, ReferenceQueue<? super T> q) {
        super(referent, q);
        this.timestamp = clock;
    }


    public T get() {
        T o = super.get();
        if (o != null && this.timestamp != clock)
            this.timestamp = clock;
        return o;
    }

}

注意这两个变量clock 和 timestamp;
在JVM发生GC时,也会更新clock的值,意味着clock会记录上次GC发生的时间点;
另一个变量timestamp,在软引用初始化时,会被初始化成clock,同时在get方法被调用时,也会更新timestamp的值;
所以如果一个SoftReference长时间没有被调用(即get方法没被调用)那么clock 和 timestamp之间会形成差值;
首先当GC时,会先检查该SoftReference所引用的对象是否还存活,即GC root是否可达;若不可达就会尝试回收引用对象,这里有几种回收策略,如LRUCurrentHeapPolicy;该种策略下,会对clock 和 timestamp差值与某个值进行比较,这个值的大小与上次GC后剩余空间大小正相关,也就是对空间剩余空间越大,对象存活越长;

弱引用

WeakReference:相对于软引用,它的生命周期更短,当发生GC时,如果扫描到一个对象只有弱引用,不管当前内存是否足够,都会对它进行回收。
还记得ThreadLocal里对它的的引用吗?ThreadLocalMap里的Entry继承的就是WeakReference,它将对ThreadLocal对象的引用设为弱引用,在检测到key为null之后会对entry进行清理再重新rehash,如getEntry,set,remove方法;所以我们一般这样使用:

private final static ThreadLocal memory = new ThreadLocal();

延长它的生命周期,并在需要的时候主动调用remove清理,防止OOM。
为什么使用弱引用?如上我们将memory = null,表示要删除存储的数据,则此时ThreadLocal对象只剩弱可达性,那么GC启动后,Entry就会被清理;如果是强引用,那么ThreadLocal对象仍是可达的就不会被清理,容易引发OOM;在WeakHashMap中也是此设计;

虚引用

    /**
     * Returns this reference object's referent.  Because the referent of a
     * phantom reference is always inaccessible, this method always returns
     * <code>null</code>.
     *
     * @return  <code>null</code>
     */
    public T get() {
        return null;
    }

PhantomReference它的get方法返回null;
虚引用的使用场景很窄,在JDK中,目前只知道在申请堆外内存时有它的身影。
申请堆外内存时,在JVM堆中会创建一个对应的Cleaner对象,这个Cleaner类继承了PhantomReference,当DirectByteBuffer对象被回收时,可以执行对应的Cleaner对象的clean方法,做一些后续工作,这里是释放之前申请的堆外内存。
虚引用存在的唯一作用就是当它指向的对象被回收后,虚引用本身会被加入到引用队列中,用作记录它指向的对象已被回收。

Reference

除了强引用外,其他几种都继承自Reference;

    private T referent;         /* Treated specially by GC */

    volatile ReferenceQueue<? super T> queue;

    Reference next;

    transient private Reference<T> discovered;

    private static Reference<Object> pending = null;
  1. referent:指所要引用的对象
  2. queue:ReferenceQueue队列,存放Reference
  3. next: Reference进队列呈链表结构
  4. discovered:被JVM使用,表示下一个要被处理的Reference对象
  5. pending:被JVM使用,当前被处理的Reference对象;

Reference里有个ReferenceHandler线程,优先级极高,负责轮询检查pending值,不为空则放入队列;我们可以利用这点对要清初的对象进行些操作,如下例:

    public static void main(String[] args) {
        final ReferenceQueue queue = new ReferenceQueue();
        new Thread(){
            @Override
            public void run() {
                try {
                    Reference reference = queue.remove();
                    System.out.println(reference + "被回收");
                } catch (InterruptedException e) {

                }
            }
        }.start();
        Object ob = new Object();
        Reference root = new WeakReference(ob, queue);
        System.out.println(root);
        ob = null;
        System.gc();
    }

gc()启动后,弱引用对象ob要被清除于是被赋予到penging上,ReferenceHandler线程会将它放入到我们的queue当中,我们从queue取出进行打印操作;

参考

Java软引用究竟什么时候被回收
如何有效的避免OOM,温故Java中的引用
十分钟理解Java中的弱引用

相关文章

  • JAVA四种引用(强引用,弱引用,软引用,虚引用)

    JAVA四种引用(强引用,弱引用,软引用,虚引用) [toc] 参考:Java 的强引用、弱引用、软引用、虚引用四...

  • Java的引用

    参考链接: Java到底是值传递还是引用传递 Java的四种引用方式 Java中的强引用、软引用、弱引用和虚引用 ...

  • Java基础:Java的四种引用

    在Java基础:java虚拟机(JVM)中,我们提到了Java的四种引用。包括:强引用,软引用,弱引用,虚引用。这...

  • java引用疑问

    java引用疑问 java 引用:深入分析Object.finalize方法的实现原理 - 简书Java软引用究竟...

  • Weak Reference Soft Reference Ph

    JAVA 中的引用 JAVA 中存在4种引用,由强到弱依次是强引用、软引用、弱引用、虚引用。 强引用(Strong...

  • Reference引用源码解析

    一、JAVA引用 JAVA中有四种引用,强引用、软引用、弱引用、虚引用,而这些引用在代码层次都继承了Referen...

  • Java实现的引用

    引用的分类 Java 1.2以后,除了普通的引用外,Java还定义了软引用、弱引用、虚引用等概念。 强引用:GC ...

  • Glide弱引用缓存与java的强引用、软引用、弱引用、幻象引用

    java的强引用、软引用、弱引用、幻象引用,引用队列总结 java除了原始数据类型的变量,其他所有都是引用类型。 ...

  • 面试题笔记

    Java中引用类型的区别,具体的使用场景 Java中引用类型分为四类:强引用、软引用、弱引用、虚引用。 强引用:强...

  • Java引用及其应用

    Java 引用分类 Java 中的引用分为四种,具体如下 强引用(StrongReference)强引用是使用最普...

网友评论

      本文标题:Java引用

      本文链接:https://www.haomeiwen.com/subject/btwerftx.html