java ----------finalize方法总结、GC执行finalize的过程

java finalize方法总结、GC执行finalize的过程

分类: Java2013-10-06 16:42 73人阅读 评论(0) 收藏 举报

finalizejavajvm

目录(?)[+]

注:本文的目的并不是鼓励使用finalize方法,而是大致理清其作用、问题以及GC执行finalize的过程。

1. finalize的作用

  • finalize()是Object的protected方法,子类可以覆盖该方法以实现资源清理工作,GC在回收对象之前调用该方法。
  • finalize()与C++中的析构函数不是对应的。C++中的析构函数调用的时机是确定的(对象离开作用域或delete掉),但Java中的finalize的调用具有不确定性
  • 不建议用finalize方法完成“非内存资源”的清理工作,但建议用于:① 清理本地对象(通过JNI创建的对象);② 作为确保某些非内存资源(如Socket、文件等)释放的一个补充:在finalize方法中显式调用其他资源释放方法。其原因可见下文[finalize的问题]

2. finalize的问题

  • 一些与finalize相关的方法,由于一些致命的缺陷,已经被废弃了,如System.runFinalizersOnExit()方法、Runtime.runFinalizersOnExit()方法
  • System.gc()与System.runFinalization()方法增加了finalize方法执行的机会,但不可盲目依赖它们
  • Java语言规范并不保证finalize方法会被及时地执行、而且根本不会保证它们会被执行
  • finalize方法可能会带来性能问题。因为JVM通常在单独的低优先级线程中完成finalize的执行
  • 对象再生问题:finalize方法中,可将待回收对象赋值给GC Roots可达的对象引用,从而达到对象再生的目的
  • finalize方法至多由GC执行一次(用户当然可以手动调用对象的finalize方法,但并不影响GC对finalize的行为)

3. finalize的执行过程(生命周期)

(1) 首先,大致描述一下finalize流程:当对象变成(GC Roots)不可达时,GC会判断该对象是否覆盖了finalize方法,若未覆盖,则直接将其回收。否则,若对象未执行过finalize方法,将其放入F-Queue队列,由一低优先级线程执行该队列中对象的finalize方法。执行finalize方法完毕后,GC会再次判断该对象是否可达,若不可达,则进行回收,否则,对象“复活”。

(2) 具体的finalize流程:

对象可由两种状态,涉及到两类状态空间,一是终结状态空间 F = {unfinalized, finalizable, finalized};二是可达状态空间 R = {reachable, finalizer-reachable, unreachable}。各状态含义如下:

  • unfinalized: 新建对象会先进入此状态,GC并未准备执行其finalize方法,因为该对象是可达的
  • finalizable: 表示GC可对该对象执行finalize方法,GC已检测到该对象不可达。正如前面所述,GC通过F-Queue队列和一专用线程完成finalize的执行
  • finalized: 表示GC已经对该对象执行过finalize方法
  • reachable: 表示GC Roots引用可达
  • finalizer-reachable(f-reachable):表示不是reachable,但可通过某个finalizable对象可达
  • unreachable:对象不可通过上面两种途径可达

状态变迁图:

变迁说明:

  1. 新建对象首先处于[reachable, unfinalized]状态(A)
  2. 随着程序的运行,一些引用关系会消失,导致状态变迁,从reachable状态变迁到f-reachable(B, C, D)或unreachable(E, F)状态
  3. 若JVM检测到处于unfinalized状态的对象变成f-reachable或unreachable,JVM会将其标记为finalizable状态(G,H)。若对象原处于[unreachable, unfinalized]状态,则同时将其标记为f-reachable(H)。
  4. 在某个时刻,JVM取出某个finalizable对象,将其标记为finalized并在某个线程中执行其finalize方法。由于是在活动线程中引用了该对象,该对象将变迁到(reachable, finalized)状态(K或J)。该动作将影响某些其他对象从f-reachable状态重新回到reachable状态(L, M, N)
  5. 处于finalizable状态的对象不能同时是unreahable的,由第4点可知,将对象finalizable对象标记为finalized时会由某个线程执行该对象的finalize方法,致使其变成reachable。这也是图中只有八个状态点的原因
  6. 程序员手动调用finalize方法并不会影响到上述内部标记的变化,因此JVM只会至多调用finalize一次,即使该对象“复活”也是如此。程序员手动调用多少次不影响JVM的行为
  7. 若JVM检测到finalized状态的对象变成unreachable,回收其内存(I)
  8. 若对象并未覆盖finalize方法,JVM会进行优化,直接回收对象(O)
  9. 注:System.runFinalizersOnExit()等方法可以使对象即使处于reachable状态,JVM仍对其执行finalize方法

4. 一些代码示例

(1) 对象复活

[java] view plaincopy

  1. public class GC {
  2. public static GC SAVE_HOOK = null;
  3. public static void main(String[] args) throws InterruptedException {
  4. SAVE_HOOK = new GC();
  5. SAVE_HOOK = null;
  6. System.gc();
  7. Thread.sleep(500);
  8. if (null != SAVE_HOOK) { //此时对象应该处于(reachable, finalized)状态
  9. System.out.println("Yes , I am still alive");
  10. } else {
  11. System.out.println("No , I am dead");
  12. }
  13. SAVE_HOOK = null;
  14. System.gc();
  15. Thread.sleep(500);
  16. if (null != SAVE_HOOK) {
  17. System.out.println("Yes , I am still alive");
  18. } else {
  19. System.out.println("No , I am dead");
  20. }
  21. }
  22. @Override
  23. protected void finalize() throws Throwable {
  24. super.finalize();
  25. System.out.println("execute method finalize()");
  26. SAVE_HOOK = this;
  27. }
  28. }

(2)覆盖finalize方法以确保资源释放

作为一个补充操作,以防用户忘记“关闭“资源,JDK中FileInputStream、FileOutputStream、Connection类均用了此”技术“,下面代码摘自FileInputStream类

[java] view plaincopy

  1. /**
  2. * Ensures that the <code>close</code> method of this file input stream is
  3. * called when there are no more references to it.
  4. *
  5. * @exception  IOException  if an I/O error occurs.
  6. * @see        java.io.FileInputStream#close()
  7. */
  8. protected void finalize() throws IOException {
  9. if ((fd != null) &&  (fd != FileDescriptor.in)) {
  10. /* if fd is shared, the references in FileDescriptor
  11. * will ensure that finalizer is only called when
  12. * safe to do so. All references using the fd have
  13. * become unreachable. We can call close()
  14. */
  15. close();
  16. }
  17. }

参考:

12.6 Finalization of Class Instances https://notendur.hi.is//~snorri/SDK-docs/lang/lang083.htm

深入理解java的finalize http://zhang-xzhi-xjtu.iteye.com/blog/484934

The Finalizable Object  http://www.artima.com/interfacedesign/Finalizable.html

时间: 2025-01-02 03:53:07

java ----------finalize方法总结、GC执行finalize的过程的相关文章

Android内存优化1 了解java GC 垃圾回收机制2 GC执行finalize的过程

1. finalize的作用 finalize()是Object的protected方法,子类可以覆盖该方法以实现资源清理工作,GC在回收对象之前调用该方法. finalize()与C++中的析构函数不是对应的.C++中的析构函数调用的时机是确定的(对象离开作用域或delete掉),但Java中的finalize的调用具有不确定性 不建议用finalize方法完成"非内存资源"的清理工作,但建议用于:① 清理本地对象(通过JNI创建的对象):② 作为确保某些非内存资源(如Socket.

详解java垃圾回收机制(转)及finalize方法(转)

详细介绍Java垃圾回收机制 垃圾收集GC(Garbage Collection)是Java语言的核心技术之一,之前我们曾专门探讨过Java 7新增的垃圾回收器G1的新特性,但在JVM的内部运行机制上看,Java的垃圾回收原理与机制并未改变.垃圾收集的目的在于清除不再使用的对象.GC通过确定对象是否被活动对象引用来确定是否收集该对象.GC首先要判断该对象是否是时候可以收集.两种常用的方法是引用计数和对象引用遍历. 引用计数收集器 引用计数是垃圾收集器中的早期策略.在这种方法中,堆中每个对象(不是

Java中的finalize方法理解

首先:system.gc()并不是你调用就马上执行的, 而是根据虚拟机的各种算法来来计算出执行垃圾回收的时间,另外,程序自动结束时不会执行垃圾回收的. 其次:对象被回收时,要经过两次标记,第一次标记,如果finalize被重写,或者finalize被调用过,那么垃圾回收并不会去执行finalize,第二次标记,如果对象不能在finalize中成功拯救自己,那真的就要被回收了. 咱们用的虚拟机一般都是sun的hotspot,以下描述都是针对hotspot虚拟机,当然其他虚拟机也差不多, ,,他是根

java: system.gc()和 finalize 的使用情景

finalize的作用的在进行垃圾回收前,执行的一个方法,这个方法里面不能放回收资源的东西,比如关闭流等,因为这个方法不一定被调用 这个方法只有进行垃圾回收时才被调用 下面这个例子是关于finalize的一个使用情景 package day20150814; public class Finalize { public static void main(String[] args) { Check check1 = new Check(),check2 = new Check(); check1

Java中final、finally、finalize的区别(转)

Java中final.finally.finalize的区别与用法,困扰了不少学习者,下面我们就这个问题进行一些探讨,希望对大家的学习有所帮助. 方法/步骤 1 简单区别: final用于声明属性,方法和类,分别表示属性不可交变,方法不可覆盖,类不可继承. finally是异常处理语句结构的一部分,表示总是执行. finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,供垃圾收集时的其他资源回收,例如关闭文件等. END 方法/步骤2 1 中等区别: 虽然这三

Effective Java Item7:Avoid Finalizers,解释为什么finalize是不安全的,不建议使用

我的上一篇博客:System.gc()和-XX:+DisableExplicitGC启动参数,以及DirectByteBuffer的内存释放 在讨论如何回收堆外内存的时候,提到"NIO中direct memory的释放并不是通过finalize(),因为finalize不安全而且影响能".Effective Java一书中也提到:Avoid Finalizers.人都有潜在的叛逆意识,别人给的结论或者制定的规范,除非有足够的理由说服你,除非懂得这么做背后的原因,否则只能是死记硬背,没有

【翻译】finalize方法到底要干嘛

以下是JDK中的描述: Called by the garbage collector on an object when garbage collection determines that there are no more references to the object. A subclass overrides the finalize method to dispose of system resources or to perform other cleanup. 当垃圾回收器发现

finalize与System.gc()

finalize Finalize是Object类的一个方法,可以用来被重写 finalize的工作原理应该是这样的:一旦垃圾收集器准备好释放对象占用的存储空间,它首先调用finalize(),而且只有在下一次垃圾收集过程中,才会真正回收对象的内存.所以如果使用finalize(),就可以在垃圾收集期间进行一些重要的清除或清扫工作. 问题:finalize()在什么时候被调用? 回答: 有三种情况 1.所有对象被Garbage Collection时自动调用,比如运行System.gc()的时候

Java虚拟机详解----GC算法和种类

本文主要内容: GC的概念 GC算法  引用计数法(无法解决循环引用的问题,不被java采纳) 根搜索算法 现代虚拟机中的垃圾搜集算法: 标记-清除 复制算法(新生代) 标记-压缩(老年代) 分代收集 可触及性 Stop-The-World 一.GC的概念: GC:Garbage Collection 垃圾收集 1960年 Lisp使用了GC Java中,GC的对象是Java堆和方法区(即永久区) 我们接下来对上面的三句话进行一一的解释: (1)GC:Garbage Collection 垃圾收