理解JVM-引用类型

在gc 过程中,对于处于不用引用状态的对象,可以使用不同的回收策略。

引用的一些概念

  • 普通的java 类型
Object obj = new Object();

在gc 的过程中,只要obj (这是一个引用)可以被GC root 访问到, 那么obj 所引用的HEAP 的对象被认为是强引用。 强引用对应的HEAP 上的内存不会被释放。 相反, obj 如果不能被GC root 访问到, 那么HEAP 上的对象就被回收(但未必立即被回收, 需要考虑finalize) 。

  • 引用类型
    Java 中引入了 Reference 对象(非强引用)。这里有两个概念, reference(引用对象) 和 Referent(被引用对象).
//obj 对StringBuilder 是一个强引用, StringBuilder 是一个普通的java 类型
StringBuilder obj = new StringBuilder("ref test" );

// refObj 是一个引用类型变量
// 其中 refObj 为引用对象(refence) , obj 为被引用对象( referent) 
WeakReference<StringBuilder> refObj =new WeakReference<StringBuilder>(  obj );

Java 中的引用类型支持

Java 中多数类型都为强引用类型(如果被引用,就是强引用)。Java 中引入了引用类型来表示非强引用的 引用类型,SoftRefernce(直接中文译为软引用,也不容易理解), WeakReference, PhantomReference。
就引用的强弱关系

    StrongReference > SoftRefernce >WeakRefence >PhantomReference

对象引用强弱的判断

  • 强引用状态
//obj 对StringBuilder 是一个强引用, StringBuilder 是一个普通的java 类型
StringBuilder obj = new StringBuilder("ref test" );

我们可以说StringBuilder 建立的对象被obj 强引用。
在上面的基础上我们添加代码

  • Soft 引用状态
SoftReference<StringBuilder> refObj =new SoftReference<StringBuilder>(  obj );

这时候我们并不能说对象是处于SoftReference 的状态。 虽然StringBuilder 对象被refObj softreference, 但是同时被obj 强引用, 那么该对象依旧处于强引用状态。
我们继续添加代码

obj= null;
//stepToSoft

执行到 stepToSoft, 这时候obj = null, StringBuilder 不再被引用了, 只有refObj 的soft引用, 这时候StringBuilder 处于SoftReference状态(准确来说来不是#1).

  • Weak 引用状态
    和Soft 引用判断有些相似,如果对象被强引用,或者Soft 引用, 即使同时也被Weak 引用, 对象也不是处于 Weak 引用状态。 只有不被强引用或者Soft 引用的情况是, Weak 引用才被认为对象的引用状态。

  • Phantom 引用状态
    和上面引用状态的判断类似。 如果被对象对多种方式引用,则最强的引用作为其当前被引用的状态

不同引用状态对象GC 不同的处理方式

GC 的第一个过程是EmumerationRoot, 得到GC root。 第二个过程 trace reachable。 第三个过程会进行内存的回收。

在过程二 中,会确定对应的引用状态。gc对不同的引用状态,会有不同的处理方式。

  • 强引用
    对象占有的内存不会被回收
  • soft 引用
    在内存不足(这个由gc 来判断)时, 引用对象的referent 将被置空。 这时候, 应用将无法通过引用对象访问到referent,referent 占有的资源就可以回收了。
  • weak 引用
    只要发生gc, 引用对象的referent 就被置空, 对象占有额资源就可以回收了(#2)。
  • phantom 引用
    应用无法通过phantom 引用 获取(get方法)到referent, 他总是返回空。它所引用的referent 不需要被置空,直接就可以回收(#2)。

说明

#1 准确来说obj当前还是被强引用的,它被方法栈的本地变量表引用。
#2 如果说这些对象的class 实现了finallize, 他们将处于finalizable 状态,等待执行fianllize。下次gc 再执行trace,判断引用状态, 确定是否可以被回收。

猜你喜欢

转载自blog.csdn.net/taozhen1987/article/details/80471125
今日推荐