Files
rikako-note/java se/垃圾回收和引用.md

109 lines
5.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

- [垃圾回收和引用](#垃圾回收和引用)
- [finalize](#finalize)
- [引用](#引用)
- [Reference](#reference)
- [get](#get)
- [clear](#clear)
- [enqueue](#enqueue)
- [isEnqueue](#isenqueue)
- [引用的可达性](#引用的可达性)
- [强可达(strongly reachable)](#强可达strongly-reachable)
- [软可达(softly reachable)](#软可达softly-reachable)
- [弱可达(weakly reachable)](#弱可达weakly-reachable)
- [终结器可达(finalizer reachable)](#终结器可达finalizer-reachable)
- [幽灵可达(phantom reachable)](#幽灵可达phantom-reachable)
- [引用类型](#引用类型)
- [软引用(SoftReference)](#软引用softreference)
- [弱引用(WeakReference)](#弱引用weakreference)
- [幽灵可达](#幽灵可达)
- [Weak Hash Map](#weak-hash-map)
- [引用队列](#引用队列)
- [ReferenceQueue.poll](#referencequeuepoll)
- [ReferenceQueue.remove](#referencequeueremove)
- [弱引用和软引用的使用](#弱引用和软引用的使用)
# 垃圾回收和引用
## finalize
finalize方法将会在对象的空间被回收之前被调用。如果一个对象被垃圾回收器判为不可达而需要被回收时垃圾回收器将调用该对象的finalize方法通过finalize方法可以清除对象的一些非内存资源。
在每个对象中finalize方法最多被调用一次。
> finalize方法可以抛出任何异常但是抛出的异常将被垃圾回收器忽略。
在finalize方法调用时该对象引用的其他对象可能也是垃圾对象并且已经被回收。
## 引用
### Reference
Reference是一个抽象类是所有特定引用类的父类。
#### get
```java
public Object get()
```
将会返回引用对象指向的被引用对象
#### clear
```java
public void clear()
```
清空引用对象从而使其不指向任何对象
#### enqueue
```java
public boolean enqueue()
```
如果存在引用对象将引用对象加入到注册的引用队列中如果加入队列成功返回true如果没有成功加入到队列或者该引用对象已经在队列中那么返回false
#### isEnqueue
```java
public boolean isEnqueue()
```
如果该引用对象已经被加入到引用队列中那么返回true否则返回false
### 引用的可达性
#### 强可达(strongly reachable)
至少通过一条强引用链可达
#### 软可达(softly reachable)
不是强可达,但是至少可以通过一条包含软引用的引用链可达
#### 弱可达(weakly reachable)
不是弱可达,但是至少通过一条包含弱引用的引用链可达
#### 终结器可达(finalizer reachable)
不是弱可达但是该对象的finalize方法尚未执行
#### 幽灵可达(phantom reachable)
如果finalize方法已经执行但是可通过至少一条包含幽灵引用的引用链可达
### 引用类型
#### 软引用(SoftReference)
对于软可达的对象垃圾回收程序会随意进行处置如果可用内存很低回收器会清空SoftReference对象中的引用之后该被引用对象则能被回收
> 在抛出OOM之前所有的SoftReference引用将会被清空
#### 弱引用(WeakReference)
弱可达对象将会被垃圾回收器回收如果垃圾回收器认为对象是弱可达的所有指向其的WeakReference对象都会被清空
#### 幽灵可达
幽灵可达并不是真正的可达,虚引用并不会影响对象的生命周期,如果一个对象和虚引用关联,则该对象跟没有与该虚引用关联一样,在任何时候都有可能被垃圾回收。虚引用主要用于跟踪对象垃圾回收的活动。
### Weak Hash Map
WeakHashMap会使用WeakReference来存储key。
如果垃圾回收器发现一个对象弱可达时会将弱引用放入到引用队列中。WeakHashMap会定期检查引用队列中新到达的弱引用并且新到的弱引用代表该key不再被使用WeakHashMap会移除关联的entry。
### 引用队列
如果对象的可达性状态发生了改变,那么执行该对象的引用类型将会被放置到引用队列中。引用队列通常被垃圾回收器使用。
也可以在自己的代码中对引用队列进行使用,通过引用队列,可以监听对象的可达性改变。
> 例如当对象不再被强引用,变为弱可达时,引用将会被添加到引用队列中,再通过代码监听引用队列的变化,即可监听到对象可达性的变化
> ReferenceQueue是线程安全的。
#### ReferenceQueue.poll
```java
pulbic Reference poll()
```
该方法会删除并且返回队列中的下一个引用对象若队列为空则返回值为null
#### ReferenceQueue.remove
```java
public Reference remove() throws InterruptedException
```
该方法同样会删除并返回队列中下一个引用对象,但是该方法在队列为空时会无限阻塞下去
```java
public Reference remove(long timeout) throws InterruptedException
```
引用对象在构造时,会和特定的引用队列相关联,当被引用对象的可达性状态发生变化时,被添加到引用队列中。在被添加到队列之前,引用对象都已经被清空。
### 弱引用和软引用的使用
弱引用和软引用都提供两种类型的构造函数,
- 只接受被引用对象,并不将引用注册到引用队列
- 既接受被引用对象,还将引用注册到指定的引用队列,然后可以通过检查引用队列中的情况来监听被引用对象可达状态变更