神刀安全网

从面试题中看java的Reference(引用)

常见的面试中会有这么一道题,“谈谈强引用、 软引用、 弱引用、虚引用”。

A:强引用,通过new出来的都是强引用
Q:那弱引用呢?
A:通过WeakReference构造出的,不再有强引用…
Q:那软引用呢,这些引用间的区别是什么?
A:…

面到这个阶段这就比较尴尬了。为了避免类似的尴尬,特地花了点时间去整理这些引用,以便下次面试的时候就这个问题能和面试官谈笑风生。

首先可以在oracle的文档中找到相应的api说明
java.lang.ref
Class Reference<T>

java.lang.Object
java.lang.ref.Reference<T>

Direct Known Subclasses:
PhantomReference, SoftReference, WeakReference

Abstract base class for reference objects. This class defines the operations common to all reference objects. Because reference objects are implemented in close cooperation with the garbage collector, this class may not be subclassed directly.
Since:
1.2

事实上在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象。也就是说,只有对象处于可触及(reachable)状态,程序才能使用它。从JDK 1.2版本开始,把对象的引用分为4种级别,从而使程序能更加灵活地控制对象的生命周期。这4种级别由高到低依次为:强引用、软引用、弱引用和虚引用。

Strong Reference:
强引用是默认实现的引用。垃圾回收器不会回收具有强引用的对象,除非没有任何对象指向它时才会在一次GC 执行后被回收。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题
至此,也许犀利的你发现了这个现象:java中的Reference的子类中并没有一个叫 StrongReference的,在文章中写的也是Strong Reference 。stackoverflow上也有类似的讨论,点击查看

SoftReference

Soft reference objects, which are cleared at the discretion of the garbage collector in response to memory demand. Soft references are most often used to implement memory-sensitive caches.Suppose that the garbage collector determines at a certain point in time that an object is softly reachable. At that time it may choose to clear atomically all soft references to that object and all soft references to any other softly-reachable objects from which that object is reachable through a chain of strong references. At the same time or at some later time it will enqueue those newly-cleared soft references that are registered with reference queues.
All soft references to softly-reachable objects are guaranteed to have been cleared before the virtual machine throws an OutOfMemoryError. Otherwise no constraints are placed upon the time at which a soft reference will be cleared or the order in which a set of such references to different objects will be cleared. Virtual machine implementations are, however, encouraged to bias against clearing recently-created or recently-used soft references.
Direct instances of this class may be used to implement simple caches; this class or derived subclasses may also be used in larger data structures to implement more sophisticated caches. As long as the referent of a soft reference is strongly reachable, that is, is actually in use, the soft reference will not be cleared.Thus a sophisticated cache can, for example, prevent its most recently used entries from being discarded by keeping strong referents to those entries, leaving the remaining entries to be discarded at the discretion of the garbage collector.

请留意文档中标注的片段

  • 软引用对象时刻响应着内存状态
    注意 这里并未明说内存不足时将回收软引用对象,内存充裕时则不会回收,待会儿的测试中就能应证这一点

  • 软引用常用于实现高速缓存。
    这里的缓存指的是高速内存缓存(区别于DiskLruCache)。

  • 所有引用了软可及(softly-reachable)的对象将在JVM抛出OutOfMemoryError异常前完成清除,回收工作。
    由此可见
    1.以SoftReference实现内存缓存是可靠的。
    2.软引用对象存在多种状态:软可及(softly-reachable)只是其中一种状态。

  • SoftReference可被用来实现简单的高速缓存;SoftReference类或派生子类也可用于较大的数据结构中实现更复杂的高速缓存。

  • 只要软引用对象是强可及(strongly reachabl) 在实际应用中软引用将不会被清除。

至此,我们可以通过一个简单的Test来验证。下文是一个通过的测试案例。

@Test public void softReference() { //测试环境,内存充足     Object referent = new Object();     SoftReference<Object> softRerference = new SoftReference<Object>(referent);     assertSame(referent, softRerference.get());//referent '强可及'     System.gc();      assertNotNull(softRerference.get());     assertNotNull(referent);      referent = null;//referent '软可及'      System.gc();     assertNotNull(softRerference.get()); //'软可及'内存充足,不会被被回收 }

WeakReference

Weak reference objects, which do not prevent their referents from being made finalizable, finalized, and then reclaimed. Weak references are most often used to implement canonicalizing mappings.Suppose that the garbage collector determines at a certain point in time that an object is weakly reachable. At that time it will atomically clear all weak references to that object and all weak references to any other weakly-reachable objects from which that object is reachable through a chain of strong and soft references. At the same time it will declare all of the formerly weakly-reachable objects to be finalizable. At the same time or at some later time it will enqueue those newly-cleared weak references that are registered with reference queues.

  • 不论内存是否充裕,弱引用对象都将被回收
  • 弱引用不会阻扰引用对象进行finalizable,finalized还是reclaimed
  • 弱引用常用于实现canonicalizing mappings
    什么是canonicalizing mappings?在此引用一篇文章的解释。原文链接:http://c2.com/cgi/wiki?CanonicalizedMapping

A "canonicalized" mapping is where you keep one instance of the object in question in memory and all others look up that particular instance via pointers or somesuch mechanism. This is where weaks references can help. The short answer is that Weak Reference objects can be used to create pointers to objects in your system while still allowing those objects to be reclaimed by the garbage-collector once they pass out of scope.
通俗的说,弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。一个经典的弱引用的使用场景:哈希表的接口允许使用任何Java对象作为键来使用。当一个键值对被放入到哈希表中之后,哈希表对象本身就有了对这些键和值对象的引用。如果这种引用是强引用的话,那么只要哈希表对象本身还存活,其中所包含的键和值对象是不会被回收的。如果某个存活时间很长的哈希表中包含的键值对很多,最终就有可能消耗掉JVM中全部的内存。

同样的我们测试一下:

@Test public void weakReference() {     Object referent = new Object();     WeakReference<Object> weakRerference = new WeakReference<Object>(referent);          assertSame(referent, weakRerference.get());//referent '强可及'     System.gc();     assertNotNull(weakRerference.get());     assertNotNull(referent);//referent '强可及' 不会被回收     referent = null;//取消强引用,referent '弱可及'      System.gc();     assertNull(weakRerference.get()); //'弱可及'将被回收,此时内存充裕     referent = null;     System.gc();      assertNull(weakRerference.get()); //`不可及` }

‘强可及’,’软可及’ ,’弱可及’ ,’不可及’这些引用状态简直看的人一脸懵逼呀。先不要慌,我们来看看oracle是怎么定义这些状态的:
Reachability
Going from strongest to weakest, the different levels of reachability reflect the life cycle of an object. They are operationally defined as follows:

  • An object is strongly reachable if it can be reached by some thread without traversing any reference objects. A newly-created object is strongly reachable by the thread that created it.
    An object is softly reachable if it is not strongly reachable but can be reached by traversing a soft reference.
  • An object is weakly reachable if it is neither strongly nor softly reachable but can be reached by traversing a weak reference. When the weak references to a weakly-reachable object are cleared, the object becomes eligible for finalization.
  • An object is phantom reachable if it is neither strongly, softly, nor weakly reachable, it has been finalized, and some phantom reference refers to it.
  • Finally, an object is unreachable, and therefore eligible for reclamation, when it is not reachable in any of the above ways.

Since:
1.2
自然而然的Since 1.2 ,看下文档再对比下Test,现在应该明朗多了吧。
PhantomReference

Phantom reference objects, which are enqueued after the collector determines that their referents may otherwise be reclaimed. Phantom references are most often used for scheduling pre-mortem cleanup actions in a more flexible way than is possible with the Java finalization mechanism.If the garbage collector determines at a certain point in time that the referent of a phantom reference is phantom reachable, then at that time or at some later time it will enqueue the reference.
In order to ensure that a reclaimable object remains so, the referent of a phantom reference may not be retrieved: The get method of a phantom reference always returns null.
Unlike soft and weak references, phantom references are not automatically cleared by the garbage collector as they are enqueued. An object that is reachable via phantom references will remain so until all such references are cleared or themselves become unreachable.

  • 一个对象仅如果持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。
  • 虚引用主要用来跟踪对象被垃圾回收器回收的活动。

转载本站任何文章请注明:转载至神刀安全网,谢谢神刀安全网 » 从面试题中看java的Reference(引用)

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址