1
0
mirror of https://github.com/Snailclimb/JavaGuide synced 2025-06-25 02:27:10 +08:00

[docs uodate]添加了对 finalize 方法的简单介绍

This commit is contained in:
guide 2021-12-29 20:58:12 +08:00
parent 39c8980e46
commit 0257a01f32
2 changed files with 51 additions and 39 deletions

View File

@ -71,6 +71,7 @@ Java 堆是垃圾收集器管理的主要区域,因此也被称作**GC 堆G
接下来我们提供一个调试脚本来测试这个过程。 接下来我们提供一个调试脚本来测试这个过程。
**调试代码参数如下** **调试代码参数如下**
``` ```
-verbose:gc -verbose:gc
-Xmx200M -Xmx200M
@ -85,7 +86,9 @@ Java 堆是垃圾收集器管理的主要区域,因此也被称作**GC 堆G
-XX:+UseConcMarkSweepGC -XX:+UseConcMarkSweepGC
-XX:+UseParNewGC -XX:+UseParNewGC
``` ```
**示例代码如下:** **示例代码如下:**
```java ```java
/* /*
* 本实例用于java GC以后新生代survivor区域的变化以及晋升到老年代的时间和方式的测试代码。需要自行分步注释不需要的代码进行反复测试对比 * 本实例用于java GC以后新生代survivor区域的变化以及晋升到老年代的时间和方式的测试代码。需要自行分步注释不需要的代码进行反复测试对比
@ -133,6 +136,7 @@ public class JavaGcTest {
``` ```
注意:如下输出结果中老年代的信息为 `concurrent mark-sweep generation` 和以前版本略有不同。另外,还列出了某次 GC 后是否重新生成了 threshold以及各个年龄占用空间的大小。 注意:如下输出结果中老年代的信息为 `concurrent mark-sweep generation` 和以前版本略有不同。另外,还列出了某次 GC 后是否重新生成了 threshold以及各个年龄占用空间的大小。
```bash ```bash
2021-07-01T10:41:32.257+0800: [GC (Allocation Failure) 2021-07-01T10:41:32.257+0800: [ParNew 2021-07-01T10:41:32.257+0800: [GC (Allocation Failure) 2021-07-01T10:41:32.257+0800: [ParNew
Desired survivor size 3145728 bytes, new threshold 1 (max 3) Desired survivor size 3145728 bytes, new threshold 1 (max 3)
@ -150,6 +154,7 @@ Heap
Metaspace used 153K, capacity 2280K, committed 2368K, reserved 4480K Metaspace used 153K, capacity 2280K, committed 2368K, reserved 4480K
``` ```
![堆内存常见分配策略 ](./pictures/jvm垃圾回收/堆内存.png) ![堆内存常见分配策略 ](./pictures/jvm垃圾回收/堆内存.png)
### 1.1 对象优先在 eden 区分配 ### 1.1 对象优先在 eden 区分配
@ -366,10 +371,17 @@ JDK1.2 以后Java 对引用的概念进行了扩充,将引用分为强引
### 2.4 不可达的对象并非“非死不可” ### 2.4 不可达的对象并非“非死不可”
即使在可达性分析法中不可达的对象,也并非是“非死不可”的,这时候它们暂时处于“缓刑阶段”,要真正宣告一个对象死亡,至少要经历两次标记过程;可达性分析法中不可达的对象被第一次标记并且进行一次筛选,筛选的条件是此对象是否有必要执行 finalize 方法。当对象没有覆盖 finalize 方法,或 finalize 方法已经被虚拟机调用过时,虚拟机将这两种情况视为没有必要执行。 即使在可达性分析法中不可达的对象,也并非是“非死不可”的,这时候它们暂时处于“缓刑阶段”,要真正宣告一个对象死亡,至少要经历两次标记过程;可达性分析法中不可达的对象被第一次标记并且进行一次筛选,筛选的条件是此对象是否有必要执行 `finalize` 方法。当对象没有覆盖 `finalize` 方法,或 `finalize` 方法已经被虚拟机调用过时,虚拟机将这两种情况视为没有必要执行。
被判定为需要执行的对象将会被放在一个队列中进行第二次标记,除非这个对象与引用链上的任何一个对象建立关联,否则就会被真的回收。 被判定为需要执行的对象将会被放在一个队列中进行第二次标记,除非这个对象与引用链上的任何一个对象建立关联,否则就会被真的回收。
> `Object` 类中的 `finalize` 方法一直被认为是一个糟糕的设计,成为了 Java 语言的负担,影响了 Java 语言的安全和 GC 的性能。JDK9 版本及后续版本中各个类中的 `finalize` 方法会被逐渐弃用移除。忘掉它的存在吧!
>
> 参考:
>
> - [JEP 421: Deprecate Finalization for Removal](https://openjdk.java.net/jeps/421)
> - [是时候忘掉 finalize 方法了](https://mp.weixin.qq.com/s/LW-paZAMD08DP_3-XCUxmg)
### 2.5 如何判断一个常量是废弃常量? ### 2.5 如何判断一个常量是废弃常量?
运行时常量池主要回收的是废弃的常量。那么,我们如何判断一个常量是废弃常量呢? 运行时常量池主要回收的是废弃的常量。那么,我们如何判断一个常量是废弃常量呢?

View File

@ -246,7 +246,7 @@ JVM内存会划分为堆内存和非堆内存堆内存中也会划分为**年
finalize()是Object类的一个方法、一个对象的finalize()方法只会被系统自动调用一次经过finalize()方法逃脱死亡的对象,第二次不会再调用。 finalize()是Object类的一个方法、一个对象的finalize()方法只会被系统自动调用一次经过finalize()方法逃脱死亡的对象,第二次不会再调用。
补充一句并不提倡在程序中调用finalize()来进行自救。建议忘掉Java程序中该方法的存在。因为它执行的时间不确定甚至是否被执行也不确定Java程序的不正常退出而且运行代价高昂无法保证各个对象的调用顺序甚至有不同线程中调用。在Java9中已经被标记为 **deprecated** 且java.lang.ref.Cleaner也就是强、软、弱、幻象引用的那一套中已经逐步替换掉它会比finalize来的更加的轻量及可靠。 补充一句并不提倡在程序中调用finalize()来进行自救。建议忘掉Java程序中该方法的存在。因为它执行的时间不确定甚至是否被执行也不确定Java程序的不正常退出而且运行代价高昂无法保证各个对象的调用顺序甚至有不同线程中调用。在Java9中已经被标记为 **deprecated** ,且 `java.lang.ref.Cleaner`(也就是强、软、弱、幻象引用的那一套)中已经逐步替换掉它,会比 `finalize` 来的更加的轻量及可靠。
     
![](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-11/c807dab33f8b42329c1910d609e7ed21-new-image565aeab2-6d3e-4c2c-80f6-7a7b0f629fda.png) ![](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-11/c807dab33f8b42329c1910d609e7ed21-new-image565aeab2-6d3e-4c2c-80f6-7a7b0f629fda.png)