Java虚拟机有5个不同级别的对象的可达性。
●强可达(Strongly reachable)
如果一个对象可以被一些线程直接使用而不用通过其他引用对象(reference objects),那么它就是强可达。一个新创建的对象对创建它的线程来讲就是强可达的。
这是我们知道并且一直在使用的引用类型(译注:通常被new出来的对象都是强可达的,他们的引用就是强引用)。任何通过强引用所使用的对象(在一个活动线程中)都不会被GC回收。
●软可达(Softly reachable)
如果一个对象没有强可达性,但是它可以通过一个软引用(soft reference.)来使用,那么它就具有软可达性。
只有当系统需要更多内存时,GC才会回收具有软可达性的对象。在内存不足前,GC保证一定回收软可达的对象。
有可能我们会在代码中写下这么几行:“嘿,我想要把一些数据保存在内存中。但只要JVM快把内存用光的时候,就可以直接将这些东西回收并将这些引用置为null。我会在代码里面处理这种情况。”关于软引用(SoftReference)何时应该被回收的算法依赖于不同的JVM发行版本。它往往是一个跟引用(reference)的使用频率和使用间隔有关的函数。
软引用可用来实现内存敏感的高速缓存.但是你懂的,具体的行为还是得依赖于JVM。并且多少跟内存回收机制有关,保障很少并且跟具体的JVM发行版本有关。为了缓存的可靠(及其他更多特性),大多数人都会选用像Ehcache而不是用软引用实现自己的缓存。但在一些场合,使用软引用确实可以让代码非常优雅、简洁。
●弱可达(Weakly reachable)
如果一个对象既没有强可达性,也没有软可达性,但是它可以通过一个弱引用(weak reference)来使用,那么他就具有弱可达性。当弱引用指向的弱可达对象没有其他的引用,那么这个对象就会被回收。
弱引用不能阻止垃圾回收机制清理他指向的引用。弱引用最常见的使用情景是通过WeakHashMap。它是一种简单地将对象的生命周期跟Map中对象的索引域(key)绑定的方式。只有当WeakHashMap中的Key是强可达,也就是WeakHashMap中的数据域(Data域)的对象,在应用程序的其他地方有别的引用的时候,它里面的值才不会被回收。一旦应用程序中没有其他对WeakHashMap中对象的引用,那么它的所有的key就会变成弱可达,不需要用户的额外干预,所有WeakHashMap中的对象都会被清除。这是一种优雅地防止内存泄露的方式。
●虚可达(Phantom reachable)
如果一个对象既没有强可达性,也没有软可达性、弱可达性,他已经被终结(finalized),并且有一些虚引用(phantom reference)指向它,那么它就具有虚可达性。
虚引用(PhantomReference)指向的对象是不能被取回使用的。它的get()方法永远返回null,所以它有什么用呢?
所有的引用类型都允许在构造函数中指定一个引用队列(ReferenceQueue)。从语义上讲一个虚引用(PhantomReference)以什么方式、何时入队让对象终结(finalization)以一种更好、更健壮的方式进行。
●不可达(Unreachable)
当一个对象不能通过以上的方式指向,那么这个对象就变得不可达,并因此适合被回收。
本文翻译自:
Garbage Collection, Reference types and Reachability – Strong, Soft, Weak, Phantom, Unreachable6