- 浏览: 369285 次
- 性别:
- 来自: 成都
文章分类
最新评论
-
tuspark:
关于javadoc这里讲解的更全面:《javadoc设置》。
Eclipse中生成javadoc【Z】 -
yuexiang1007:
帮我解决了问题,谢谢!!!
java.math.BigInteger使用心得总结 -
netwelfare:
个人感觉,文章对HashMap的遍历分析的有点浅,不如这里的介 ...
HashMap遍历的两种方式【Z】 -
memoryisking:
关于java.math.BigInteger讲解在这里可以看到 ...
java.math.BigInteger使用心得总结 -
巴尾的兔兔帅:
divide应该是除吧?不是减。dividepublic Bi ...
java.math.BigInteger使用心得总结
目录
基本预备相关知识
对象的销毁过程
对象重生的例子
对象的finalize的执行顺序
何时及如何使用finalize
参考
基本预备相关知识
1 java的GC只负责内存相关的清理,所有其它资源的清理必须由程序员手工完成。要不然会引起资源泄露,有可能导致程序崩溃。
2 调用GC并不保证GC实际执行。
3 finalize抛出的未捕获异常只会导致该对象的finalize执行退出。
4 用户可以自己调用对象的finalize方法,但是这种调用是正常的方法调用,和对象的销毁过程无关。
5 JVM保证在一个对象所占用的内存被回收之前,如果它实现了finalize方法,则该方法一定会被调用。Object的默认finalize什么都不做,为了效率,GC可以认为一个什么都不做的finalize不存在。
6 对象的finalize调用链和clone调用链一样,必须手工构造。
如
- protected void finalize() throws Throwable {
- super .finalize();
- }
protected void finalize() throws Throwable { super.finalize(); }
对象的销毁过程
在对象的销毁过程中,按照对象的finalize的执行情况,可以分为以下几种,系统会记录对象的对应状态:
unfinalized 没有执行finalize,系统也不准备执行。
finalizable 可以执行finalize了,系统会在随后的某个时间执行finalize。
finalized 该对象的finalize已经被执行了。
GC怎么来保持对finalizable的对象的追踪呢。GC有一个Queue,叫做F-Queue,所有对象在变为finalizable的时候会加入到该Queue,然后等待GC执行它的finalize方法。
这时我们引入了对对象的另外一种记录分类,系统可以检查到一个对象属于哪一种。
reachable 从活动的对象引用链可以到达的对象。包括所有线程当前栈的局部变量,所有的静态变量等等。
finalizer-reachable 除了reachable外,从F-Queue可以通过引用到达的对象。
unreachable 其它的对象。
来看看对象的状态转换图。
好大,好晕,慢慢看。
1 首先,所有的对象都是从Reachable+Unfinalized走向死亡之路的。
2 当从当前活动集到对象不可达时,对象可以从Reachable状态变到F-Reachable或者Unreachable状态。
3 当对象为非Reachable+Unfinalized时,GC会把它移入F-Queue,状态变为F-Reachable+Finalizable。
4
好了,关键的来了,任何时候,GC都可以从F-Queue中拿到一个Finalizable的对象,标记它为Finalized,然后执行它的
finalize方法,由于该对象在这个线程中又可达了,于是该对象变成Reachable了(并且Finalized)。而finalize方法执行
时,又有可能把其它的F-Reachable的对象变为一个Reachable的,这个叫做对象再生。
5
当一个对象在Unreachable+Unfinalized时,如果该对象使用的是默认的Object的finalize,或者虽然重写了,但是新的实
现什么也不干。为了性能,GC可以把该对象之间变到Reclaimed状态直接销毁,而不用加入到F-Queue等待GC做进一步处理。
6 从状态图看出,不管怎么折腾,任意一个对象的finalize只至多执行一次,一旦对象变为Finalized,就怎么也不会在回到F-Queue去了。当然没有机会再执行finalize了。
7 当对象处于Unreachable+Finalized时,该对象离真正的死亡不远了。GC可以安全的回收该对象的内存了。进入Reclaimed。
对象重生的例子
- class C {
- static A a;
- }
- class A {
- B b;
- public A(B b) {
- this .b = b;
- }
- @Override
- public void finalize() {
- System.out.println("A finalize" );
- C.a = this ;
- }
- }
- class B {
- String name;
- int age;
- public B(String name, int age) {
- this .name = name;
- this .age = age;
- }
- @Override
- public void finalize() {
- System.out.println("B finalize" );
- }
- @Override
- public String toString() {
- return name + " is " + age;
- }
- }
- public class Main {
- public static void main(String[] args) throws Exception {
- A a = new A( new B( "allen" , 20 ));
- a = null ;
- System.gc();
- Thread.sleep(5000 );
- System.out.println(C.a.b);
- }
- }
class C { static A a; } class A { B b; public A(B b) { this.b = b; } @Override public void finalize() { System.out.println("A finalize"); C.a = this; } } class B { String name; int age; public B(String name, int age) { this.name = name; this.age = age; } @Override public void finalize() { System.out.println("B finalize"); } @Override public String toString() { return name + " is " + age; } } public class Main { public static void main(String[] args) throws Exception { A a = new A(new B("allen", 20)); a = null; System.gc(); Thread.sleep(5000); System.out.println(C.a.b); } }
期待输出
- A finalize
- B finalize
- allen is 20
A finalize B finalize allen is 20
但是有可能失败,源于GC的不确定性以及时序问题,多跑几次应该可以有成功的。详细解释见文末的参考文档。
对象的finalize的执行顺序
所有finalizable的对象的finalize的执行是不确定的,既不确定由哪个线程执行,也不确定执行的顺序。
考虑以下情况就明白为什么了,实例a,b,c是一组相互循环引用的finalizable对象。
何时及如何使用finalize
从以上的分析得出,以下结论。
1 最重要的,尽量不要用finalize,太复杂了,还是让系统照管比较好。可以定义其它的方法来释放非内存资源。
2 如果用,尽量简单。
3 如果用,避免对象再生,这个是自己给自己找麻烦。
4 可以用来保护非内存资源被释放。即使我们定义了其它的方法来释放非内存资源,但是其它人未必会调用该方法来释放。在finalize里面可以检查一下,如果没有释放就释放好了,晚释放总比不释放好。
5 即使对象的finalize已经运行了,不能保证该对象被销毁。要实现一些保证对象彻底被销毁时的动作,只能依赖于java.lang.ref里面的类和GC交互了。
参考
关于引用类型,GC,finalize的相互交互可以参考ReferenceQueue GC finalize Reference 测试及相关问题
发表评论
-
JSTL中的<c:标签【Z】
2011-08-31 20:48 1146Taglib 伪指令 Java代码 ... -
java接口嵌套【Z】
2011-05-18 17:09 1342在Java语言中,接口可以嵌套在类或其它接口中。由于Jav ... -
JMF安装【Z】
2011-05-07 20:52 1094下载并安装JMF 在MyEclipse中选择 窗口/首选项/ ... -
javaMail【Z】
2011-04-18 16:12 1078commons-email-1.1.jar: 这是Apache ... -
java生成PDF文件【Z】
2011-01-14 15:03 1211如果应用程序需要动态 ... -
字符集编码【Z】
2010-12-29 18:54 893问题研究 --字符集 ... -
java常用第三方jar包【Z】
2010-12-26 22:39 3360commons-digester.jar Digeste ... -
不使用JNI获得系统信息【Z】
2010-12-22 13:28 589在Java中,可以获得总的物理内存、剩余的物理内存、已使用的物 ... -
java获得当前路径【Z】
2010-12-18 14:37 9421、利用System.getProperty()函数获取当前路 ... -
java容器类-1【Z】
2010-12-17 21:43 1013对象的集合 如果程序的对象数量有限 ... -
java UIManager的风格【Z】
2010-12-17 12:28 2671Java'中的几种Look and Feel 1、Met ... -
serialVersionUID的作用和意义【Z】
2010-12-15 10:38 1553在Java中,软件的兼容性是一个大问题,尤其在使用到对象串行性 ... -
HashMap遍历的两种方式【Z】
2010-12-07 18:42 968HashMap遍历的两种方式 ... -
23个经典JDK设计模式——系统JDK使用设计模式的例子【Z】
2010-12-05 21:33 1030酷壳 版主陈皓近日发表博文《JDK里的设计模式 》,文中他 ... -
String/StringBuffer/StringBuild【Z】
2010-11-12 14:10 1346[编辑] String,StringBuffer和String ... -
tomcat中web.xml详解【Z】
2010-10-18 14:47 9251 定义头和根元素 部 ... -
Java 理论与实践: 线程池与工作队列【Z】
2010-10-18 09:45 932线程池有助于实现最 ... -
单例模式完全剖析【Z】
2010-10-17 22:48 790Buildfile: build.xml ... -
在MyEclipse中直接查看class文件(在没有源码的情况下)【Z】
2010-10-17 22:04 1309想直接在myeclipse中查看class文件,就像查看普通的 ... -
HashMap实现及冲突【Z】
2010-10-12 21:41 962了解 HashMap 原理对于日后的缓存机制多少有 ...
相关推荐
Java 中 finalize() 的用法 Java 中的 finalize() 方法是垃圾回收器在回收对象时调用的第一个方法。finalize() 方法相当于析构函数,它是垃圾回收器回收一个对象时第一个要调用的方法。finalize() 方法的主要作用是...
深入理解 `final` 关键字可以帮助开发者写出更加安全、高效的代码。 首先,`final` 关键字可以用于声明变量。当一个变量被声明为 `final` 时,它的值一旦被赋值后就不能再改变。这适用于成员变量、局部变量以及静态...
深入理解`final`、`finally`和`finalize`,开发者可以编写更加健壮和高效的代码。`final`帮助保持代码的稳定性和防止意外的修改,`finally`保证了资源的正确关闭,而避免使用`finalize`则有助于避免不必要的复杂性和...
深入理解 Java 虚拟机笔记 Java 虚拟机(JVM)是 Java 语言的运行环境,它负责解释和执行 Java 字节码。下面是 Java 虚拟机相关的知识点: 虚拟机内存结构 Java 虚拟机的内存结构主要包括以下几个部分: * 方法...
自Java 9开始,JVM引入了ZGC(Z Garbage Collector),它极大地减少了对`finalize()`的依赖。此外,JDK 11中`finalize()`方法被标记为`@Deprecated`,正式建议开发者避免使用。 综上所述,为了编写更加高效、可靠...
第2章 深入理解Java Binder和MessageQueue 2.1 概述 2.2 Java层中的Binder架构分析 2.2.1 Binder架构总览 2.2.2 初始化Java层Binder框架 2.2.3 addService实例分析 2.2.4 Java层Binder架构总结 2.3 心系两界...
Java 中 finalize 方法使用 finalize 方法是 Java 编程语言中一个非常重要的方法,它与 Java 编程中的垃圾回收器有着紧密的关系。当一个对象变成一个垃圾对象的时候,如果此对象的内存被回收,那么就可以调用系统中...
Java中的`finalize()`方法是Java语言提供的一种机制,用于在对象被垃圾回收之前进行资源清理。这个方法在Java的`Object`类中被定义为`protected`类型,因此所有Java类都能够覆盖它来实现特定的清理操作。在垃圾回收...
Java垃圾收集(GC)机制是Java编程中...理解Java的GC机制有助于优化程序性能,避免因内存管理不当引起的系统不稳定。开发者应根据应用需求选择合适的垃圾收集策略,并注意合理使用各种引用类型,避免不必要的内存占用。
深入理解 final、finally、finalize 浅拷贝和深拷贝 关于四种引用类型 Java 开发最容易忽视的 10 个 Bug Java 浅拷贝和深拷贝 Java 创建对象的五种方式 Exception 和 Error 的区别 for 、foreach 、iterator 三种...
在Java编程语言中,`final`, `finally`, 和 `finalize` 是三个非常重要的关键字,它们各自扮演着不同的角色,尤其在处理程序的可预测性、数据的不可...在Java面试中,理解和掌握这些关键字的用法是非常基础且重要的。
下面我们将深入探讨finalize()方法的用法和应用场景。 一、final关键字 final是Java的关键字,它所表示的是“这部分是无法修改的”。在程序设计中,我们有时可能希望某些数据是不能够改变的,这个时候final就有...
java.lang.object原始码最终不推荐使用java.lang.Object.finalize() 我的博客文章中的示例的Gradle源代码存储库。 在Linux Mint(SUSE Linux)上构建和测试。 由于gradle当前不支持Java 11,因此可以使用标准Java...
Java中final,finally,finalize三个关键字的区别_动力节点Java学院整理
深入理解这些概念对于编写高效、健壮的Java代码至关重要。 ### final 1. **不可变性**:`final` 关键字用于声明一个变量、方法或类为最终状态,意味着一旦赋值或定义后,其值或状态不能被修改。例如,当一个变量被...
以下是对Java垃圾回收的深入解析: 1. **垃圾回收的基本概念** - **对象生命周期**:当程序创建一个对象时,Java虚拟机(JVM)会在堆内存中为这个对象分配内存空间。一旦对象不再被任何引用指向,那么这个对象就...
本文将深入探讨这个包中的四种主要引用类型:StrongReference、SoftReference、WeakReference 和 PhantomReference,以及它们的特性、用法和作用。 首先,强引用(StrongReference)是我们在日常编程中最常见的引用...
Java中的`finalize()`方法是对象生命周期的一部分,它与C++中的析构函数类似,但在功能和调用时机上有所不同。`finalize()`方法是在对象被GC标记为可回收并准备释放之前调用的,提供了在对象被彻底删除前执行某些...
java中final, finally, finalize 的区别
Java编程中的`final`, `finalize`, 和`finally`是三个重要的关键字,它们各自在不同的场景下发挥着关键作用。理解这三个关键字的区别对于Java开发者来说至关重要,尤其是在面试中常常会被问及。 首先,`final`是一...