前言
了解引用关系主要是为了更好地理解垃圾回收机制,底层对象生命周期,对于我们设计可靠的缓存等框架,或者诊断应用 OOM 等问题,会很有帮助。比如,诊断 MySQL connector-j 驱动在特定模式下(useCompression=true)的内存泄漏问题,就需要我们理解怎么排查幻象引用的堆积问题。
。
提示:以下是本篇文章正文内容,下面案例可供参考
一、四种引用定义
1、强引用
任何具有主动强引用的对象都不符合垃圾收集的条件。对象在垃圾收集时,只有在强引用点为空的变量时才会被收集为垃圾。
MyClass obj = new MyClass ();
obj = null;
//'obj' object is no longer referencing to the instance.
So the 'MyClass type object is now available for garbage collection.
// Java program to illustrate Strong reference
class Gfg
{
//Code..
}
public class Example
{
public static void main(String[] args)
{
//Strong Reference - by default
Gfg g = new Gfg();
//Now, object to which 'g' was pointing earlier is
//eligible for garbage collection.
g = null;
}
}
2、软引用
在软引用中,可以让对象豁免一些垃圾收集,直到JVM急需内存。当JVM耗尽内存时,这些对象会从内存中清除。
3、弱引用
弱引用(WeakReference)并不能使对象豁免垃圾收集,仅仅是提供一种访问在弱引用状态下对象的途径。这就可以用来构建一种没有特定约束的关系,比如,维护一种非强制性的映射关系,如果试图获取时对象还在,就使用它,否则重现实例化。它同样是很多缓存实现的选择
//Code to illustrate Soft reference
import java.lang.ref.SoftReference;
class Gfg
{
//code..
public void x()
{
System.out.println("GeeksforGeeks");
}
}
public class Example
{
public static void main(String[] args)
{
// Strong Reference
Gfg g = new Gfg();
g.x();
// Creating Soft Reference to Gfg-type object to which 'g'
// is also pointing.
SoftReference<Gfg> softref = new SoftReference<Gfg>(g);
// Now, Gfg-type object to which 'g' was pointing
// earlier is available for garbage collection.
g = null;
// You can retrieve back the object which
// has been weakly referenced.
// It successfully calls the method.
g = softref.get();
g.x();
}
}
4、幻象(虚引用)
由幻影引用引用的对象有资格进行垃圾收集。但是,在将它们从内存中删除之前,JVM将它们放入称为‘reference queue’的队列中。在调用finalize()方法后,它们被放入参考队列中。
//Code to illustrate Phantom reference
import java.lang.ref.*;
class Gfg
{
//code
public void x()
{
System.out.println("GeeksforGeeks");
}
}
public class Example
{
public static void main(String[] args)
{
//Strong Reference
Gfg g = new Gfg();
g.x();
//Creating reference queue
ReferenceQueue<Gfg> refQueue = new ReferenceQueue<Gfg>();
//Creating Phantom Reference to Gfg-type object to which 'g'
//is also pointing.
PhantomReference<Gfg> phantomRef = null;
phantomRef = new PhantomReference<Gfg>(g,refQueue);
//Now, Gfg-type object to which 'g' was pointing
//earlier is available for garbage collection.
//But, this object is kept in 'refQueue' before
//removing it from the memory.
g = null;
//It always returns null.
g = phantomRef.get();
//It shows NullPointerException.
g.x();
}
}
<font color=#999AAA >
Exception in thread "main" java.lang.NullPointerException
at Example.main(Example.java:31)
output
GeeksforGeeks
二、扩展
1.对象可达性状态流转分析
强可达(Strongly Reachable),就是当一个对象可以有一个或多个线程可以不通过各种引用访问到的情况。比如,我们新创建一个对象,那么创建它的线程对它就是强可达。
软可达(Softly Reachable),就是当我们只能通过软引用才能访问到对象的状态。
弱可达(Weakly Reachable),类似前面提到的,就是无法通过强引用或者软引用访问,只能通过弱引用访问时的状态。这是十分临近 finalize 状态的时机,当弱引用被清除的时候,就符合 finalize 的条件了。
幻象可达(Phantom Reachable),上面流程图已经很直观了,就是没有强、软、弱引用关联,并且 finalize 过了,只有幻象引用指向这个对象的时候。
当然,还有一个最后的状态,就是不可达(unreachable),意味着对象可以被清除了。
判断对象可达性,是 JVM 垃圾收集器决定如何处理对象的一部分考虑。