type
status
date
slug
summary
tags
category
icon
password
引用类型
- SoftReference
普通的GC不会回收软引用,只有在即将发生OOM的时候(即最后一次Full GC),如果被引用的对象只有SoftReference指向的引用,才会被回收.
- WeakReference
当发生GC时,如果被引用的对象只有WeakReference指向的引用,就会被回收
- PhantomReference
不能通过虚引用获取到其关联的对象,但是当GC发生时,如果其引用的对象被回收,这个事件是可以感知的,这样就可以做相应的处理.
- 强引用
GC是如何决定一个对象是否被回收?
从GC Root开始向下搜索,如果对象与GC之间存在引用链,则对象是可达的(reachable),GC会根据是否可达,以及对象的可达性来决定对象是否可以被回收.
而对象的可达性与引用类型相关:
- 强可达
- 软可达
- 虚可达
- 弱可达
- 不可达
Refercence的几种状态
一个Reference对象可能处于以下4种状态中的一种:
- Active
新创建的对象都是处于这个状态;
GC检测到引用的对象可达性改变时,会将状态转变成Pending或者Inactiive(如果refercence创建时带了referenceQueue,则会将refercence加入到pending 引用队列中)
- Pending
马上要被放进队列中的对象,即即将被回收的对象
pending引用队列中的一个元素,等着被ReferenceHandler线程(一个守护线程)去enqueue.
没有注册(即创建时没有带queue的)的对象不会处于这个状态;
- Enqueued
对象的内存已经被回收了,已经把这个对象放到了一个队列中
当一个对象从它的引用队列中移除时,它就是Inactive状态了,未注册的对象不会处于这个状态;
- Inactive
最终状态,不会再改变了.
处理流程
JVM在进行GC的时候,如果当前对象只被Reference对象引用,JVM会根据Reference的具体类型和堆内存的使用情况来决定:
是否把对应的Reference对象加入到一个由Reference构成的pending链表上(即Refercence中的next属性).
如果能加入到pending链表上,则JVM会同时通知ReferenceHandler线程进行处理.
ReferenceHandler线程是在Reference初始化的时候创建的,它是一个守护线程,并拥有最高优先级:
再来看看ReferenceHandler:
ReferenceHandler线程内部的run方法,会不断从pending链表中获取Refercence对象,
如果能获取到,则根据不同的引用类型进行处理;
如果获取不到,则调用wait方法等待GC回收对象,处理pending链表的通知.
参考文章
- 作者:姜康
- 链接:https://jiangkang.tech/article/c7ce7ada-34c7-4425-a2f4-a8d8f7ec0277
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。