精华内容
下载资源
问答
  • Java四种引用类型

    千次阅读 2019-05-12 19:01:34
    文章目录引用类型简介对象可达性判断GC Roots对象可达性判断可达性状态类型可达性判断规则状态转换Reference类定义状态变化四种引用类型实现强引用FinalReference软引用SoftReference弱引用WeakReference虚引用...

    引用类型简介

    Java开发者肯定都很熟悉java中的4种引用类型,它们从强到弱分别是:

    引用类型 对象是否可引用 回收时间 使用场景
    强引用 可以 从不回收 普遍对象的状态
    软引用 可以 内存不足时 内存敏感的高速缓存
    弱引用 可以 下一次GC 对象缓存
    虚引用 不可以 下一次GC,不影响对象生命周期 必须和引用队列(ReferenceQueue)一起使用,一般用于追踪垃圾收集器的回收动作。相比对象的finalize方法,虚引用的方式更加灵活和安全。

    但可能大多数对4种引用类型的理解都只停留在概念的记忆上,而并不了解四种引用的实现原理。下面我们结合源代码了解下四种引用的实现原理。当然在了解四种引用的实现原理之前,首先得了解下JVM中实现对象可达性判断的原理。

    对象可达性判断

    目前,大多数JVM都是使用可达性分析算法来判断对象的是否可达。可达性分析算法以GC Roots对象作为起始点进行搜索。当一个对象与GC Roots对象没有任何引用链相连时(也即引用有向图中从GC Roots对象到这个对象是不连通的),则表明该对象是不可用的(不可用的对象不一定被判定为可以回收的对象)。当对象与GC Roots对象有引用链相连时,则需要根据引用链的类型来判断对象是否可达。

    不可用的对象不一定被判定为可以回收的对象:判定对象为”死亡”至少需要经历两次标记的过程。第一次标记:对象可达性分析,如果发现对象没有与GC Roots相连接的引用链,且对象需要执行finalize方法,将会被加入F-Queue队列中。第二次标记:由一个优先级低的Finalizer线程去取F-Queue队列的对象,“尝试执行”对象的finalize方法。

    JVM会保证触发满足条件的对象的finalize方法,但是并不承诺会等待方法执行结束。finalize方法是对象逃脱死亡命运的最后一次机会。

    GC Roots对象

    GC Roots对象包含以下四类:

    • 虚拟机栈(栈桢中的本地变量表)中的引用的对象;
    • 方法区中的类静态属性引用的对象;
    • 方法区中的常量引用的对象;
    • 本地方法栈中JNI(Native方法)引用的对象;

    可达性判断

    可达性状态类型

    Java有5种类型的可达性状态:

    • 强可达(Strongly Reachable):与GC Roots对象之间有强引用相连通,则为强可达的;
    • 软可达(Soft Reachable):与GC Roots对象之间没有强引用相连通,但有软引用相连通,则为软可达的;
    • 弱可达(Weak Reachable):与GC Roots对象之间没有强引用或软引用相连通,但有弱引用相连通,则为弱可达的;
    • 虚可达(Phantom Reachable):与GC Roots对象之间没有强引用、软引用或弱引用相连通,然后该对象finalize方法已执行,并且有虚引用相连通,则为虚可达的;
    • 不可达(Unreachable):如果对象finalize方法已执行并且没有任何引用相连通,则对象是不可达的,可以被回收。

    可达性判断规则

    从GC Roots对象到一个对象的引用链可能存在多条,那么此时会依据两个原则来判断对象的可达性:

    • 单个引用链中,以最弱的引用类型为准;
    • 多引用链联合看时,以最强的引用类型为准;

    可达性判断

    首先,单个引用链中,以最弱的引用类型为准:则GC Roots->Obj1->Obj4是软引用连通的,GC Roots->Obj2->Obj4是弱引用连通的,GC Roots->Obj3->Obj5是弱引用连通的。然后多引用链联合看时,以最强的引用类型为准:则GC Roots到Obj4对象的引用联合来看是弱引用连通的。

    状态转换

    对象可达性状态是随着程序运行而不断变化的,对象可达性状态转换图可参考下图。

    • 对象创建后一般是强可达的。
    • 当GC Roots对象到该对象的强引用被清除后:如果剩余引用链最高为软引用,则状态转换为软可达的;反之如果最高为弱引用,则状态转换为弱可达的,反之则把对象标记为可执行finalize方法状态。
    • 当软可达对象重新被强引用连接时,则转换为强可达状态;当软可达对象的软引用被清除后,如果剩余引用链最高为弱引用,则状态转换为弱可达;反之则把对象标记为可执行finalize方法状态。
    • 当弱可达对象重新被强引用或者软引用连接时,则可转换为强可达或者软可达;当弱可达对象的弱引用被清除后,则把对象标记为可执行finalize方法状态。
    • 可对象被标记为可执行finalize方法状态,如果对象finalize从未被执行,则执行finalize方法,并标记对象的finalize方法已经被执行(在finalize方法可能会重新生成强/软/弱引用等,对象状态会重新转换为强/软/弱可达,不过并不推荐这么做,因为可能会导致对象状态紊乱,无法被正常回收);反之当对象有虚引用连接时,则转换为虚可达状态,否则转换为不可达状态。
    • 虚可达对象在垃圾回收后状态转换为不可达(不能通过虚引用获取对象引用,所以对象状态不会再转换为强/软/弱可达);

    可达性状态转换图

    Reference

    Reference类是所有引用类型的基类,定义了reference对象的通用操作,用来保存对象引用及引用的内部状态。Reference抽象类初始化时,会启动一个ReferenceHandler线程。Reference的referent被回收前,垃圾回收器会把reference添加到pending这个链表里(如果注册了ReferenceQueue),然后ReferenceHandler线程不断的读取pending中的reference,把它加入到对应的ReferenceQueue中(如果Reference是Cleaner类的实例,即虚引用对象,则调用其注册的预处理钩子方法)。

    ReferenceQueue提供了两个静态字段NULL,ENQUEUED。这两个字段的主要功能:NULL是当我们构造Reference实例时queue传入null时,会默认使用NULL,这样在enqueue时判断queue是否为NULL,如果为NULL直接返回,入队失败。ENQUEUED的作用是防止重复入队,reference后会把其queue字段赋值为ENQUEUED,当再次入队时会直接返回失败。

    类定义

    Reference对象的基类。该类定义了reference对象的通用操作。因为reference对象是和垃圾回收器密切配合实现的,因此该类不能直接进行子类化。

    public abstract class Reference<T> {
    	// 用于保存对象的引用,GC会特别对待该变量
        private T referent; 
    	// 如果注册了ReferenceQueue(需要通知机制),用来保存对象引用的队列,
        volatile ReferenceQueue<? super T> queue;
    
        // 保存需要由ReferenceHandler处理的引用
        volatile Reference next;
    
    	// 被JVM使用,保存需要被JVM处理的下一个引用
        transient private Reference<T> discovered;
    
        // 同步锁,用于同步pending队列的进队和出队
        static private class Lock { }
        private static Lock lock = new Lock();
    
        // 一个PENDING队列,配合上述next一起使用,实现类单向循环链表的操作
        private static Reference<Object> pending = null;
    
    	// 高优先级线程,用于将pending队列里面的Reference实例依次添加到不同的ReferenceQueue中
    	private static class ReferenceHandler extends Thread {...}
    	...
    }
    

    状态变化

    一个对象引用有四种内部状态:

    • Active: 新创建的实例的状态,当对象引用被垃圾回收器回收前:如果Reference注册了ReferenceQueue,则会切换为Pending,并且Reference会加入pending链表中,如果没有注册ReferenceQueue,会切换为Inactive。
    • Pending: 在pending链表中的Reference的状态,这些Reference等待被ReferenceHandler内部线程加入ReferenceQueue中。
    • Enqueued: 在ReferenceQueue队列中的Reference的状态,如果Reference从队列中移除,会进入Inactive状态。未注册ReferenceQueue的实例不会到达该状态。
    • Inactive: Reference的最终状态,该状态不会再改变。

    其状态转换图如下:

    Reference内部状态转换图

    四种引用类型实现

    不同引用类型的UML类图如下:

    Reference UML类图

    强引用FinalReference

    对象新建后默认为强引用类型的,是普遍对象引用的类型。查看FinalReference在JDK中的源码发现其只有一个空实现,这也说明强引用是“默认引用类型”。

    /**
     * Final references, used to implement finalization
     */
    class FinalReference<T> extends Reference<T> {
        public FinalReference(T referent, ReferenceQueue<? super T> q) {
            super(referent, q);
        }
    }
    

    软引用SoftReference

    软引用是用来描述一些“还有用但是非必须”的对象。软引用的回收策略在不同的JVM实现会略有不同,JVM不仅仅只会考虑当前内存情况,还会考虑软引用所指向的referent最近的使用情况和创建时间来综合决定是否回收该referent。软引用保存了两个变量:

    • timestamp:每次调用get方法都会更新时间戳。JVM可以利用该字段来选择要清除的软引用,但不是必须要这样做。
    • clock:时间锁,由垃圾收集器更新。

    因此,任何GC都可以使用这些字段并定义清除软引用的策略,例如:最后清除最近创建的或最近使用的软引用。

    /**
     * 软引用对象由垃圾收集器根据内存需要决定是否清除。软引用经常用于实现内存敏感的缓存。
     *
     * 假如垃圾收集器在某个时间确定对象是软可达的,此时它可以选择原子地清除
     * 指向该对象的所有软引用,以及从该对象通过强引用链连接的其他软可达对象的所有软引用。
     * 与时同时或者之后的某个时间,它会将注册了reference queues的新清除的软引用加入队列。
     *
     * 在虚拟机抛出OutOfMemoryError异常之前,将保证清除对软可达对象的所有软引用。
     * 不过,并没有对清除软引用的时间以及清除顺序施加强制约束。
     * 但是,鼓励虚拟机实现偏向不清除最近创建或最近使用的软引用。
     *
     * 该类的直接实例可用于实现简单的缓存。
     * 该类或其派生子类也可用于更大的数据结构以实现更复杂的高速缓存。
     * 只要软引用的引用对象还是强可达的,即还在实际使用中,软引用就不会被清除。
     * 因此,复杂的高速缓存可以通过持有对最近使用缓存对象的强引用来防止其被清除,
     * 而不常使用的剩余缓存对象由垃圾收集器决定是否清除。
     */
    public class SoftReference<T> extends Reference<T> {
    
    	// 时间锁,由垃圾收集器更新。
        static private long clock;
    
    	// 每次调用get方法都会更新该时间戳。JVM可能会在选择要清除的软引用时使用该字段,
    	// 但这不是强制必须的。
        private long timestamp;
    	
    	// 返回对象的引用。如果该引用对象已经被程序或者垃圾收集器清除,则返回null。
    	// 把最近一次垃圾回收时间赋值给timestamp
        public T get() {
            T o = super.get();
            if (o != null && this.timestamp != clock)
                this.timestamp = clock;
            return o;
        }
    
    }
    

    弱引用WeakReference

    当一个对象没有被强引用或者软引用连接,但被弱引用连接时,则处于弱可达状态。只要发生GC,弱可达的对象就会被清除,同时会把弱引用加入到注册的引用队列中(如果存在的话)。弱引用对GC几乎是没有影响的,它不影响对应的referent被终结(finalized)和回收(reclaimed)。因此,弱引用最常用于实现规范化映射(canonicalizing mappings),例如哈希表,如果它们在程序中未被引用,则其键和值将从映射中删除。

    /**
     * 弱引用对象不能阻止自身的引用被回收。
     * 弱引用常用于实现规范化映射(对象实例可以在程序的多个地方同时使用)。
     *
     * 假如垃圾收集器在某个时间点确定对象是弱可达的。那时它将原子地清除对该对象的所有弱引用
     * 以及该引用通过强引用或者软引用连接的所有其他弱可达对象的所有弱引用。
     * 同时,它将表明前面所指的所有弱可达对象都可以执行finalize方法。
     * 与此同时或之后某一个时间,它将注册了reference queues的那些新清除弱引用加入队列。
     */
    public class WeakReference<T> extends Reference<T> {
    
    	// 创建没有注册ReferenceQueue的弱引用
        public WeakReference(T referent) {
            super(referent);
        }
    
    	// 创建注册了ReferenceQueue的弱引用
        public WeakReference(T referent, ReferenceQueue<? super T> q) {
            super(referent, q);
        }
    }
    

    虚引用PhantomReference

    虚引用是所有引用类型中最弱的一种。一个对象是否关联到虚引用,完全不会影响该对象的生命周期,也无法通过虚引用来获取一个对象的实例。为对象设置一个虚引用的唯一目的是:能在此对象被垃圾收集器回收的时候收到一个系统通知,它就是利用ReferenceQueue实现的。当referent被gc回收时,JVM自动把虚引用对象本身加入到ReferenceQueue中,表明该reference指向的referent被回收。然后可以通过去queue中取到reference,可以通过这个来做额外的清理工作。可以用虚引用代替对象finalize方法来实现资源释放,这样更加灵活和安全。

    /**
     * 虚引用对象在被垃圾收集器检查到后加入reference queues队列,否则会被回收。
     * 虚引用最常用于实现比Java finalization机制更灵活的安排额外的清理工作。
     *
     * 如果垃圾收集器在某个时间点确定虚引用对象是虚可达的,那么在那个时间或之后某个时间它会将引用加入reference queues队列。
     *
     * 为了确保可回收对象保持不变,虚引用的引用无法使用:虚引用对象的get方法始终返回null。
     *
     * 与软引用和弱引用不同,当虚引用加入reference queues队列后垃圾收集器不会被自动清除。
     * 只通过虚引用可达的对象将保持不变,直到所有此类引用都被清除或自已变为不可达。
     */
    public class PhantomReference<T> extends Reference<T> {
    
        // 由于不能通过虚引用访问对象,因此此方法始终返回null。
        public T get() {
            return null;
        }
    
        // 使用空ReferenceQueue队列创建一个虚引用没有意义:它的get方法总是返回null,
    	// 并且由于它没有注册队列,所以也不会被加入队列有任何清理前的预处理操作。
        public PhantomReference(T referent, ReferenceQueue<? super T> q) {
            super(referent, q);
        }
    }
    
    展开全文
  • 四种类型引用

    千次阅读 2016-08-06 15:13:38
    从Java SE2开始,就提供了四种类型的引用:强引用、软引用、弱引用和虚引用。Java中提供这四种引用类型主要两个目的:第一是可以让程序员通过代码的方式决定某些对象的生命周期;第二是有利于JVM进行垃圾回收。

    从Java SE2开始,就提供了四种类型的引用:强引用、软引用、弱引用和虚引用。

    Java中提供这四种引用类型主要有两个目的:第一是可以让程序员通过代码的方式决定某些对象的生命周期;第二是有利于JVM进行垃圾回收。

    1、强引用

    平时开发new对象都属于强引用

    只要某个对象有强引用与之关联,JVM必定不会回收这个对象,即使在内存不足的情况下,JVM宁愿抛出OutOfMemory错误也不会回收这种对象。

    如果想中断强引用和某个对象之间的关联,可以显示地将引用赋值为null,这样一来的话,JVM在合适的时间就会回收该对象。

      比如Vector类的clear方法中就是通过将引用赋值为null来实现清理工作的:
      
    这里写图片描述

    2、软引用

    有用但不必须 SoftReference

    与软引用关联着的对象,只有在内存不足的时候JVM才会回收该对象。因此,这一点可以很好地用来解决OOM的问题,并且这个特性很适合用来实现缓存:比如网页缓存、图片缓存等。

      软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被JVM回收,这个软引用就会被加入到与之关联的引用队列中。

    应用场景:假如有一个应用需要读取大量的本地图片,如果每次读取图片都从硬盘读取,则会严重影响性能,但是如果全部加载到内存当中,又有可能造成内存溢出,此时使用软引用可以解决这个问题。

    3、弱引用

    弱引用也是用来描述非必需对象的,当JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象。

    在java中,用java.lang.ref.WeakReference类来表示。
    弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被JVM回收,这个软引用就会被加入到与之关联的引用队列中。

    这里写图片描述

    执行后显示:

    Hello
    Null

    4、虚引用

    PhantomReference

    不影响对象的生命周期,
    如果一个对象与虚引用关联,则跟没有引用与之关联一样,在任何时候都可能被垃圾回收器回收。

    虚引用必须和引用队列关联使用,当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会把这个虚引用加入到与之 关联的引用队列中。程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。

    展开全文
  • java四种引用类型

    万次阅读 2020-05-11 10:04:53
    编程语言都自己操作内存中元素的方式,例如在 C 和 C++ 里是通过指针,而在 Java 中则是通过“引用”。 java不同于c/c++,它不需要程序员自已来管理内存(分配,释放内存),java 会自己来管理内存,比如销毁...

    背景:

    每种编程语言都有自己操作内存中元素的方式,例如在 C 和 C++ 里是通过指针,而在 Java 中则是通过“引用”。 java不同于c/c++,它不需要程序员自已来管理内存(分配,释放内存),java 会自己来管理内存,比如销毁某些不再被使用的对象。这些操作都是在一个后台线程默默进行(Garbage Collector Thread),也就是垃圾收集器线程,根据jvm实现的策略来释放对象内存。但是程序编写者却无法控制这个后台线程,无法让它在你想要的时候开始释放内存,销毁对象,按照你的规定来销毁那些对象,释放内存,这些都是都jvm自己控制的。但是随着 java.lang.ref这个包下的类的引进,程序员拥有了一点点控制你创建的对象何时释放,销毁的权利,当然只是一点点。

    四种引用类型

    在 JDK1.2 之前,Java中的定义很传统:如果 reference 类型的数据中存储的数值代表的是另外一块内存的起始地址,就称为这块内存代表着一个引用。

    Java 中的垃圾回收机制在判断是否回收某个对象的时候,都需要依据“引用”这个概念。

    但是,JDK1.2 之前,一个对象只有“已被引用”和"未被引用"两种状态,这将无法描述某些特殊情况下的对象,比如,当内存充足时需要保留,而内存紧张时才需要被抛弃的一类对象。

    所以在 JDK.1.2 之后,Java 对引用的概念进行了扩充,将引用分为了:强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)、虚引用(Phantom Reference)4 种,这 4 种引用的强度依次减弱。

    强引用:

    只要强引用存在,垃圾回收器将永远不会回收被引用的对象,哪怕内存不足时,JVM也会直接抛出OutOfMemoryError,不会去回收。如果想中断强引用与对象之间的联系,可以显示的将强引用赋值为null,这样一来,JVM就可以适时的回收对象了(代码优化:某个大对象使用完后,如果后面的业务耗时久并且不会使用该对象,可以考虑赋值null)

    在 JDK1.2 之后,用java.lang.ref.FinalReference类来表示软引用。

    /**
     * Final references, used to implement finalization
     */
    class FinalReference<T> extends Reference<T> {
        public FinalReference(T referent, ReferenceQueue<? super T> q) {
            super(referent, q);
        }
    }
    

     

    软引用:

    软引用是用来描述一些“还有用但是非必须”的对象。在内存足够的时候,软引用对象不会被回收,只有在内存不足时,系统则会回收软引用对象,如果回收了软引用对象之后仍然没有足够的内存,才会抛出内存溢出异常这种特性常常被用来实现缓存技术,比如网页缓存,图片缓存等。

    但实际上,软引用的回收策略在不同的JVM实现会略有不同,JVM不仅仅只会考虑当前内存情况,还会考虑软引用所指向的referent最近的使用情况和创建时间来综合决定是否回收该referent。软引用保存了两个变量:

    timestamp:每次调用get方法都会更新时间戳。JVM可以利用该字段来选择要清除的软引用,但不是必须要这样做。
    clock:时间锁,由垃圾收集器更新。
    因此,任何GC都可以使用这些字段并定义清除软引用的策略,例如:最后清除最近创建的或最近使用的软引用。

    在 JDK1.2 之后,用java.lang.ref.SoftReference类来表示软引用。

    /**
     * 软引用对象由垃圾收集器根据内存需要决定是否清除。软引用经常用于实现内存敏感的缓存。
     *
     * 假如垃圾收集器在某个时间确定对象是软可达的,此时它可以选择原子地清除
     * 指向该对象的所有软引用,以及从该对象通过强引用链连接的其他软可达对象的所有软引用。
     * 与时同时或者之后的某个时间,它会将注册了reference queues的新清除的软引用加入队列。
     *
     * 在虚拟机抛出OutOfMemoryError异常之前,将保证清除对软可达对象的所有软引用。
     * 不过,并没有对清除软引用的时间以及清除顺序施加强制约束。
     * 但是,鼓励虚拟机实现偏向不清除最近创建或最近使用的软引用。
     *
     * 该类的直接实例可用于实现简单的缓存。
     * 该类或其派生子类也可用于更大的数据结构以实现更复杂的高速缓存。
     * 只要软引用的引用对象还是强可达的,即还在实际使用中,软引用就不会被清除。
     * 因此,复杂的高速缓存可以通过持有对最近使用缓存对象的强引用来防止其被清除,
     * 而不常使用的剩余缓存对象由垃圾收集器决定是否清除。
     */
    public class SoftReference<T> extends Reference<T> {
    
    	// 时间锁,由垃圾收集器更新。
        static private long clock;
    
    	// 每次调用get方法都会更新该时间戳。JVM可能会在选择要清除的软引用时使用该字段,
    	// 但这不是强制必须的。
        private long timestamp;
    	
    	// 返回对象的引用。如果该引用对象已经被程序或者垃圾收集器清除,则返回null。
    	// 把最近一次垃圾回收时间赋值给timestamp
        public T get() {
            T o = super.get();
            if (o != null && this.timestamp != clock)
                this.timestamp = clock;
            return o;
        }
    
    }
    

    弱引用:

    弱引用的引用强度比软引用要更弱一些,无论内存是否足够,只要 JVM 开始进行垃圾回收,那些被弱引用关联的对象都会被回收

    当一个对象没有被强引用或者软引用连接,但被弱引用连接时,则处于弱可达状态。只要发生GC,弱可达的对象就会被清除,弱引用无法阻止自身被回收,同时会把弱引用加入到注册的引用队列中(如果存在的话)。弱引用对GC几乎是没有影响的,它不影响对应的referent被终结(finalized)和回收(reclaimed)。因此,弱引用最常用于实现规范化映射(canonicalizing mappings),例如哈希表,如果它们在程序中未被引用,则其键和值将从映射中删除。

    在 JDK1.2 之后,用 java.lang.ref.WeakReference 来表示弱引用。

    /**
     * 弱引用对象不能阻止自身的引用被回收。
     * 弱引用常用于实现规范化映射(对象实例可以在程序的多个地方同时使用)。
     *
     * 假如垃圾收集器在某个时间点确定对象是弱可达的。那时它将原子地清除对该对象的所有弱引用
     * 以及该引用通过强引用或者软引用连接的所有其他弱可达对象的所有弱引用。
     * 同时,它将表明前面所指的所有弱可达对象都可以执行finalize方法。
     * 与此同时或之后某一个时间,它将注册了reference queues的那些新清除弱引用加入队列。
     */
    public class WeakReference<T> extends Reference<T> {
    
    	// 创建没有注册ReferenceQueue的弱引用
        public WeakReference(T referent) {
            super(referent);
        }
    
    	// 创建注册了ReferenceQueue的弱引用
        public WeakReference(T referent, ReferenceQueue<? super T> q) {
            super(referent, q);
        }
    }
    

    虚引用:

    虚引用是所有引用类型中最弱的一种。一个对象是否关联到虚引用,完全不会影响该对象的生命周期,也无法通过虚引用来获取一个对象的实例。虚引用和弱引用的回收机制差不多,都是可以被随时回收的。

    为对象设置一个虚引用的唯一目的是:它的构造方法必须强制传入ReferenceQueue,因为在jvm回收前(重点:软引用和弱引用都是回收后)JVM自动把虚引用对象本身(PhantomReference对象)加入到ReferenceQueue中,表明该reference指向的referent被回收。然后可以通过去queue中取到reference,可以通过这个来做额外的清理工作。可以用虚引用代替对象finalize方法来实现资源释放,这样更加灵活和安全。还有一点就是PhantomReference.get()方法永远返回空,不管对象有没有被回收。

    在 JDK1.2 之后,用 java.lang.ref.PhantomReference 来表示弱引用。

    /**
     * 虚引用对象在被垃圾收集器检查到后加入reference queues队列,否则会被回收。
     * 虚引用最常用于实现比Java finalization机制更灵活的安排额外的清理工作。
     *
     * 如果垃圾收集器在某个时间点确定虚引用对象是虚可达的,那么在那个时间或之后某个时间它会将引用加入reference queues队列。
     *
     * 为了确保可回收对象保持不变,虚引用的引用无法使用:虚引用对象的get方法始终返回null。
     *
     * 与软引用和弱引用不同,当虚引用加入reference queues队列后垃圾收集器不会被自动清除。
     * 只通过虚引用可达的对象将保持不变,直到所有此类引用都被清除或自已变为不可达。
     */
    public class PhantomReference<T> extends Reference<T> {
    
        // 由于不能通过虚引用访问对象,因此此方法始终返回null。
        public T get() {
            return null;
        }
    
        // 使用空ReferenceQueue队列创建一个虚引用没有意义:它的get方法总是返回null,
    	// 并且由于它没有注册队列,所以也不会被加入队列有任何清理前的预处理操作。
        public PhantomReference(T referent, ReferenceQueue<? super T> q) {
            super(referent, q);
        }
    }
    

     

    展开全文
  • 四种引用类型及引用队列

    千次阅读 2017-11-23 18:17:00
    1 强引用(StrongReference) 2 软引用(SoftReference) 3 弱引用(WeakReference) 4 幽灵引用/虚引用(PhantomReference) 5 引用队列(ReferenceQueue) 1 强引用(StrongReference) 效果:存在强引用...

    本文目录

    1 强引用(StrongReference)

    2 软引用(SoftReference)

    3 弱引用(WeakReference)

    4 幽灵引用/虚引用(PhantomReference)

    5 引用队列(ReferenceQueue)

     

    1 强引用(StrongReference)

    效果:存在强引用的对象,不会被JVM回收。

    // 强引用
    String str = new String("Reference");

     

    回收:当所有的强引用都断开后,在JVM进行垃圾回收时,该对象会被回收。

    // 置空
    obj = null;
    
    // 指向另一对象
    obj= newObject();

     

    2 软引用(SoftReference)

    效果:存在软引用的对象,在内存不足时,才会被JVM回收。

    应用:缓存数据,提高数据的获取速度。

    // 软引用:缓存数据
    SoftReference<String> sr = new SoftReference<String>(new String("CacheData"));
    
    // 获取数据
    String str = sr.get();
    
    // 断开强引用
    str= null;

     

    3 弱引用(WeakReference)

    效果:存在弱引用的对象,每次JVM进行垃圾回收时,该对象都会被回收。

    应用:短时间缓存某些次要数据。

    // 弱引用
    WeakReference<String> wr = new WeakReference<String>(new String("CacheData"));
    
    // 获取数据
    String str = wr.get();
    
    // 断开强引用
    str= null;
     
    // 弱引用Map
    WeakHashMap<String, String> whm = new WeakHashMap<String,String>();

     

    4 幽灵引用/虚引用(PhantomReference)

    效果:相当于无引用,使对象无法被使用,必须与引用队列配合使用。

    应用:使对象进入不可用状态,等待下次JVM垃圾回收,从而使对象进入引用列队中。

    // 引用队列
    ReferenceQueue<String> rq = new ReferenceQueue<String>();
    
    // 幽灵引用
    PhantomReference<String> pr = new PhantomReference<String>(new String(""), rq);
    
    // 永远为null(幽灵引用相当于无引用)
    System.out.println(pr.get());

     

    5 引用队列(ReferenceQueue)

    效果:引用队列可以配合软引用、弱引用及幽灵引用使用,当引用的对象将要被JVM回收时,会将其加入到引用队列中。

    应用:通过引用队列可以了解JVM垃圾回收情况。

    // 引用队列
    ReferenceQueue<String> rq = new ReferenceQueue<String>();
     
    // 软引用
    SoftReference<String> sr = new SoftReference<String>(new String("Soft"), rq);
    // 弱引用
    WeakReference<String> wr = new WeakReference<String>(new String("Weak"), rq);
    // 幽灵引用
    PhantomReference<String> pr = new PhantomReference<String>(new String("Phantom"), rq);
     
    // 从引用队列中弹出一个对象引用
    Reference<? extends String> ref = rq.poll();

     

    展开全文
  • java中四种引用类型

    千次阅读 2015-08-27 11:42:50
    今天看代码,里面一个类java.lang.ref.SoftReference把小弟弄神了,试想一下,接触java已经3年了哇,连lang包下面的类都不了解,怎么混。后来在网上查资料,感觉收获颇多,现记录如下。对象的强、软、弱和虚引用...
  • JAVA的四种引用类型

    千次阅读 2016-08-11 14:16:54
    Java四种引用类型1.引用的基本概念强引用:当我们使用new创建对象时,被创建的对象就是强引用,如Object object = new Object(),其中的object就是一个强引用了。如果一个对象具有强引用,JVM就不会去GC它,JVM宁可...
  • Java 的四种引用类型

    千次阅读 2018-09-23 18:02:42
    本篇主要介绍Java强软弱虚引用的区别以及GC对他们执行怎样的操作。 首先介绍下为什么要有引用类型?...其次介绍Java的四种引用类型 强引用(Strong Reference) 强引用就是我们平时写的新建对象的用...
  • Java的四种引用类型

    千次阅读 2011-12-31 12:53:06
    在Java中有四种引用类型,他们是:强引用(Strong Reference),软引用(Soft Reference),弱引用(Weak Reference) 和 虚引用(Phantom Reference)。 一.四种引用类型的解释: JVM会持有一般对象直到他们不再是可...
  • Java对象的四种引用类型

    万次阅读 2016-04-03 20:18:27
    参考博客:http://my.oschina.net/Bruce370/blog/511707在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象。...这4级别由高到低依次为:强引用、软引用、弱引用和虚引
  • Java有四种引用类型,strongreference,softreference,weakreference,phantomreference。这四种引用的强度按照上面的顺序依次减弱,下面通过几个例子简单了解一下这四种引用类型。 StrongReference 这个不用...
  • Java引用类型有哪些

    万次阅读 2019-07-05 16:48:32
    其中,引用数据类型在存储堆中对需要引用的对象进行引用,引用是Java面向对象的一个特点,在Java入门中,我们会接触到四种Java的引用类型,接下来就说说这四种Java引用类型有哪些吧: 1、Java中哪几引用?...
  • java中的四种引用类型

    千次阅读 2016-06-17 00:55:24
    一、强引用(StrongReference):相当于生活中的必需品,平时接触最多,不会被GC回收。当内存空间不足时,java虚拟机宁愿抛出OutOfMemoryEerror异常,也不愿意回收强引用对象来解决内存不足的问题。二、弱引用...
  • 四种引用类型分别为强引用,软引用,弱引用和虚引用。 所谓强引用,就是我们最常见的普通对象引用,我们 new 出来的对象就是强引用,只要尚且存在强引用指向某一个对象,那就能表明该对象还存活,GC 不能去回收...
  • 对象的强、软、弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象。...这4级别由高到低依次为:强引用、软引用、弱引用和虚引用。   ⑴强引用(StrongReference)
  • 对于一个对象来说,只要有引用的存在,它就会一直存在于内存中。如果这样的对象越来越多,超出了JVM中的内存总数,JVM就会抛出OutOfMemory错误。虽然垃圾回收的具体运行是由JVM来控制的,但是开发人员
  • Android四种引用

    千次阅读 2019-02-19 08:36:57
    四种类型引用(Strong Reference) 经常使用,内存不足,抛出OOM异常使程序异常终止。不会回收强引用对象来解决内存不足问题 软引用(Soft Reference) 当无强引用指向时,会在内存中停留一段时间。垃圾回收器根据JVM...
  • Java一共八大基础类型,分为三类:整型(byte,int,short,long,float,double),字符类型(char...注意:字符串String不在java的基础类型里面,它是java的引用类型 四大引用类型 分为:数组,类,接口,字符串。
  • Java四种引用类型 1.引用的基本概念 强引用:当我们使用new创建对象时,被创建的对象就是强引用,如Object object = new Object(),其中的object就是一个强引用了。如果一个对象具有强引用,JVM就不会去GC它,JVM...
  • Java 5种引用类型(对象类型):类 接口 数组 枚举 标注 引用类型:底层结构和基本类型差别较大 JVM的内存空间: (1). Heap 堆空间:分配对象 new Student() (2). Stack 栈空间:临时变量 Student stu (3)...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 629,178
精华内容 251,671
关键字:

引用类型有四种