java.lang.ref 包分析 引用 弱引用 强引用 虚引用

来源:互联网 发布:淘宝童装店logo图片 编辑:程序博客网 时间:2024/05/22 20:29

java对象的引用类型,决定虚拟机在进行垃圾回收时的行为。
首先,不存在任何引用的对象,在语义上是不存在的,它只在作用域范围内有效,超出作用域后,第一次垃圾回收及被回收;
存在强引用的对象不会被回收;
存在弱引用的对象,在垃圾回收时,并不会被立即回收,只有在有内存压力的垃圾回收中才会被回收;
存在软引用的对象,在下一次垃圾回收时即被回收;
存在虚引用的对象对回收没有什么影响,只是在对象被回收时提供一个系统通知。
不要试图直接集成引用基类Reference<T>,因为虚拟机是根据基类的3个具体的子类决定垃圾回收的。

在java.lang.ref包中共有5个类,

public abstract class Reference<T>  引用根类

public class ReferenceQueue<T> 引用队列


按照引用的由强弱排列如下,

不使用任何 Reference<T>  强引用:至少存在一个从根集到该对象的引用路径,

其中不包含任何Reference<T>类型引用。

public class SoftReference<T>extends Reference<T> 

软引用:至少存在一个从根集到该对象的引用路径,

其中包含至少一个SoftReference<T>类型引用,但是不包含任何WeakReference<T>与PhantomReference<T>类型引用。

优点:集内存缓存和IO的优点于一体,同时避免了本地IO或是网络IO的低效问题和内存缓存的资源浪费问题。

回收时机:内存不足时。


public class WeakReference<T>extends Reference<T>   

弱引用:至少存在一个从根集到该对象的引用路径,

其中包含至少一个WeakReference<T>类型引用,但是不包含任何PhantomReference<T>类型引用。

回收时机:GC时必定回收。


public class PhantomReference<T> extends Reference<T>  

虚引用:至少存在一个从根集到该对象的引用路径,

其中包含至少一个PhantomReference<T>类型引用。

作用:它不影响对象的生命周期,也无法通过引用来获取对象实例,仅在对象被回收时接收一个系统通知。


这里弱的含义是:当垃圾回收别引用对象时,对垃圾回收器有更少的限制。

根集:是指这样的引用集合,它们对于垃圾回收器都是强硬的,它们的当前状态影响垃圾回收器对其它们的处理,不是被动的受垃圾回收器控制。

比如,当前运行的线程、方法参数、本地变量、静态域等。


1 抽象根类Reference<T>

描述引用类型的共有行为,不要直接集成该抽象类,建议集成它的3个子类。

同时,你也不会期待直接集成该抽象类,因为具体引用类的实现与系统垃圾回收机制密切相关。


public class ReferenceQueue<T>


public class SoftReference<T> extends Reference<T>

清除时刻:在没有强引用并且存在内存压力的情况下,清除引用实体。

不要在缓存中使用软引用。在缓存实践中,软引用是不充分的,只能用于内存高速缓存。

因为运行时系统没有足够的信息,以便决定清除哪个引用、保存哪个引用。

更无法接受的是,当给定清除或是继续增长内容时,无法知道去做什么操作。

缺乏对应用程序的每个引用的值的信息,限制软引用的使用。太早的清除引用,引发不必要的工作;太晚又浪费内存。

大多数应用程序应该使用LruCache代替软引用。LruCache拥有有效的回收策略,使用户来协调使用多少内存。

垃圾回收机制:

当垃圾回收器遇到软引用可到达的对象时,发生如下过程:

3.1 一个引用集被创建,其中包括,所有指向该对象的软引用;二级软引用(该软引用的实体强引用该对象)。

3.2 清除在引用集中的所有实体。

3.3 同时或是在未来的某个时刻,把引用集中得所有引用入队。


publicclass WeakReference<T>extends Reference<T>

如果垃圾回收器确认某个对象是弱引用可到达,则发生如下过程:

3.1 创建一个引用集,它包含:指向该对象的所有弱引用;二级弱引用(一个弱引用,从它开始存在到引用对象的软引用链或是强引用链)。

3.2 自动清除引用集中的所有引用。

3.3 所有被该引用集引用的对象成为合格的被销毁者。

使用场景:例,在映射中,如果在外面没有对对象实体的引用,则自动清除引用实体。

弱引用与软引用的不同就在于,在哪个时刻决定清除引用实体和压栈引用。


public class PhantomReference<T> extends Reference<T> 

虚引用的引用实体一定是不可访问的。

回收机制:一但垃圾回收器确定某个引用是虚引用可达到,该引用被立即入队,并且不清除其对应的引用实体。

这意味着虚引用队列必须被应用程序代码显示地处理。因此,没有注册任何引用队列的虚引用时没有任何意义的。

虚引用在实现,回收对象之前必须进行的,清除操作中是非常有用的。在某些时候,它们比Object#finalize()更加有用。


publicclass LruCache<K, V>

持有到一定数量的对象的强引用的缓存。

每次访问一个值时,把其移到对列的头部。它是线程安全的。

当向满的队列中加入新的值时,队尾的值被移除且可能是进行垃圾回收。如果你的缓存值持有资源,你需要覆盖entryRemoved显示明确的释放它。

如果需要为对应的键计算丢失的缓存,覆盖create方法。这简化了调用代码,允许它假设该值是一直存在的,即使缓存丢失了。

默认情况下,是以实体的数量为基础,决定缓存的大小。覆盖sizeOf来设置不同的缓存测量基础。例如,以位图的大小为测量基础。



0 0
原创粉丝点击