Skip to content

Commit

Permalink
Add "探索 Java 类 Cleaner 和 Finalizer"
Browse files Browse the repository at this point in the history
  • Loading branch information
moralok committed Dec 28, 2023
1 parent 27c94a8 commit 12c2f62
Show file tree
Hide file tree
Showing 6 changed files with 488 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,16 @@ tags: [java]

`Reference``引用对象`的抽象基类。此类定义了所有引用对象通用的操作。由于引用对象是与垃圾收集器密切合作实现的,因此该类可能无法直接子类化。

<div style="width:80%;margin:auto">{% asset_img "Pasted image 20231227230915.png" Reference 相关类图 %}</div>
<div style="width:70%;margin:auto">{% asset_img "Pasted image 20231227230915.png" Reference 相关类图 %}</div>

### 构造函数

- `referent`: `引用对象`关联的对象
- `queue`: `引用对象`准备注册到的`引用队列`

`Reference` 提供了两个构造函数,一个需要传入`引用队列``ReferenceQueue`),一个不需要。如果一个`引用对象``Reference`)注册到一个`引用队列`,在检测到适当的可达性变化后,垃圾收集器将把该`引用对象`添加到该引用队列。
`Reference` 提供了两个构造函数,一个需要传入`引用队列``ReferenceQueue`),一个不需要。如果一个`引用对象``Reference`)注册到一个`引用队列`,在检测到关联对象有适当的可达性变化后,垃圾收集器将把该`引用对象`添加到该引用队列。

> “关联对象有适当的可达性变化”并不容易理解,在很多表述中它很容易被简化为“可以被回收”,但是同时我们又拥有另一条规则,即“一个对象是否可回收的判断依据是是否从 `Root` 对象可达”。在面对 `Reference` 的子类时,我们有种割裂感,好像一条和谐的规则出现了特殊条例。{% post_link explore-the-Java-classes-Cleaner-and-Finalizer '探索 Java 类 Cleaner 和 Finalizer' %}
```java
Reference(T referent) {
Expand All @@ -39,7 +41,7 @@ Reference(T referent, ReferenceQueue<? super T> queue) {

#### 成员变量

- `referent`: `引用对象`关联的对象,**该对象将被垃圾收集器特殊对待**。我们很难直观地感受何谓“被垃圾收集器特殊对待”,它大概对应着“在检测到关联对象有特定的可达性变化后,垃圾收集器将把`引用对象`添加到该引用队列”。
- `referent`: `引用对象`关联的对象,**该对象将被垃圾收集器特殊对待**。我们很难直观地感受何谓“被垃圾收集器特殊对待”,它对应着“在检测到关联对象有适当的可达性变化后,垃圾收集器将把`引用对象`添加到该引用队列”。
- `queue`: `引用对象`注册到的`引用队列`
- `next`: 用于指向下一个`引用对象`,当`引用对象`已经添加到`引用队列`中,`next` 指向`引用队列`中的下一个`引用对象`
- `discovered`: 用于指向下一个`引用对象`,用于在全局的 `pending` 链表中,指向下一个待添加到`引用队列``引用对象`
Expand All @@ -51,7 +53,7 @@ Reference(T referent, ReferenceQueue<? super T> queue) {
> 注意:`lock``pending` 是全局共享的。
- `lock`: 用于与垃圾收集器同步的对象,**垃圾收集器必须在每个收集周期开始时获取此锁**。因此至关重要的是持有此锁的任何代码必须尽快运行完,不分配新对象并避免调用用户代码。
- `pending`: 等待加入`引用队列``引用对象`链表。垃圾收集器将`引用对象`添加到 `pending` 链表中,而 `Reference Handler` 线程将删除它们,并做清理或入队操作。`pending` 链表受上述 `lock` 对象的保护,并使用 `discovered` 字段来链接下一个元素。
- `pending`: 等待加入`引用队列``引用对象`链表。垃圾收集器将`引用对象`添加到 `pending` 链表中,而 `Reference-Handler` 线程将删除它们,并做清理或入队操作。`pending` 链表受上述 `lock` 对象的保护,并使用 `discovered` 字段来链接下一个元素。

```java
public abstract class Reference<T> {
Expand All @@ -74,17 +76,17 @@ public abstract class Reference<T> {
`pending` 链表:

<div style="width:80%;margin:auto">{% asset_img "Pasted image 20231227191324.png" pending 链表 %}</div>
<div style="width:70%;margin:auto">{% asset_img "Pasted image 20231227191324.png" pending 链表 %}</div>

`ReferenceQueue`

<div style="width:80%;margin:auto">{% asset_img "Pasted image 20231227191330.png" ReferenceQueue %}</div>
<div style="width:70%;margin:auto">{% asset_img "Pasted image 20231227191330.png" ReferenceQueue %}</div>

### ReferenceHandler 线程

启动任意一个非常简单的 Java 程序,通过 JVM 相关的工具,比如 JConsole,你都能看到一个名为 Reference Handler 的线程。
启动任意一个非常简单的 `Java` 程序,通过 `JVM` 相关的工具,比如 `JConsole`,你都能看到一个名为 `Reference Handler` 的线程。

<div style="width:60%;margin:auto">{% asset_img "Snipaste_2023-12-27_19-41-19.png" Reference Handler 线程 %}</div>
<div style="width:60%;margin:auto">{% asset_img "Snipaste_2023-12-27_19-41-19.png" Reference-Handler 线程 %}</div>

`ReferenceHandler` 类本身的代码并不复杂。

Expand Down Expand Up @@ -120,7 +122,7 @@ private static class ReferenceHandler extends Thread {

#### 创建线程并启动

`ReferenceHandler` 线程是通过静态代码块创建并启动的。
`Reference-Handler` 线程是通过静态代码块创建并启动的。

```java
static {
Expand Down Expand Up @@ -377,7 +379,7 @@ public Reference<? extends T> remove(long timeout)
`Reference` 实例(引用对象)可能处于四种内部状态之一:

- `Active`: 新创建的实例处于 `Active` 状态,受到垃圾收集器的特殊处理。收集器在检测到`关联对象`的可达性变为适当状态后的一段时间,会将实例的状态更改为 `Pending``Inactive`,具体取决于实例在创建时是否注册到`引用队列`中。在前一种情况下,它还会将实例添加到待 `pending-Reference` 列表中。
- `Pending`: 实例处在 `pending-Reference` 列表中,等待 `Reference Handler` 线程将其加入`引用队列`。未注册到`引用队列`的实例永远不会处于这种状态。
- `Pending`: 实例处在 `pending-Reference` 列表中,等待 `Reference-Handler` 线程将其加入`引用队列`。未注册到`引用队列`的实例永远不会处于这种状态。
- `Enqueued`: 处在创建实例时注册到的`引用队列`中。当实例从引用队列中删除时,该实例将变为 `Inactive` 状态。未注册到`引用队列`的实例永远不会处于这种状态。
- `Inactive`: 没有进一步的操作。一旦实例变为 `Inactive` 状态,其状态将永远不会再改变。

Expand All @@ -388,7 +390,9 @@ public Reference<? extends T> remove(long timeout)
- `Enqueued`: `queue == ReferenceQueue.ENQUEUED && (next == Following || this)`(在队列末尾时,`next` 指向自身,目前没有体现出这么设计的必要性啊?)
- `Inactive`: `queue == ReferenceQueue.NULL && next == this`

<div style="width:80%;margin:auto">{% asset_img "Pasted image 20231227235157.png" Reference 相关类图 %}</div>
<div style="width:70%;margin:auto">{% asset_img "Pasted image 20231227235157.png" Reference 相关类图 %}</div>

## Reference 的子类

## 参考文章

Expand Down
Loading

0 comments on commit 12c2f62

Please sign in to comment.