finalize 订阅
finalize-方法名。Java 技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。 展开全文
finalize-方法名。Java 技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。
信息
示    例
package Initialization;
限    制
Dispose
中文名
finalize
进程终止
DLL_PROCESS_DETACH
finalize介绍
这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在 Object 类中定义的,因此所有的类都继承了它。子类覆盖 finalize() 方法以整理系统资源或者执行其他清理工作。finalize() 方法是在垃圾收集器删除对象之前被自动调用的。垃圾收集器只知道释放那些由new分配的内存,所以不知道如何释放对象的“特殊”内存。为解决这个问题,Java提供了一个名为finalize()的方法,它的工作原理应该是这样的:一旦垃圾收集器准备好释放对象占用的存储空间,它首先调用finalize(),而且只有在下一次垃圾收集过程中,才会真正回收对象的内存。所以如果使用finalize(),就可以在垃圾收集期间进行一些重要的清除或清扫工作(如关闭流等操作)。但JVM(Java虚拟机)不保证此方法总被调用。Finalize 操作具有下列限制:垃圾回收过程中执行终结器的准确时间是不确定的。不保证资源在任何特定的时间都能释放,除非调用 Close 方法或 Dispose 方法。即使一个对象引用另一个对象,也不能保证两个对象的终结器以任何特定的顺序运行。即,如果对象 A 具有对对象 B 的引用,并且两者都有终结器,则当对象 A 的终结器启动时,对象 B 可能已经终结了。运行终结器的线程是未指定的。在下面的异常情况下,Finalize 方法可能不会运行完成或可能根本不运行:另一个终结器无限期地阻止(进入无限循环,试图获取永远无法获取的锁,诸如此类)。由于运行时试图运行终结器来完成,所以如果一个终结器无限期地阻止,则可能不会调用其他终结器。进程终止,但不给运行时提供清理的机会。在这种情况下,运行时的第一个进程终止通知是 DLL_PROCESS_DETACH 通知。在关闭过程中,只有当可终结对象的数目继续减少时,运行时才继续 Finalize 对象。如果 Finalize 或 Finalize 的重写引发异常,并且运行库并非寄宿在重写默认策略的应用程序中,则运行库将终止进程,并且不执行任何活动的 try-finally 块或终结器。如果终结器无法释放或销毁资源,此行为可以确保进程完整性。给实现者的说明 默认情况下,Object.Finalize 不执行任何操作。只有在必要时才必须由派生类重写它,因为如果必须运行 Finalize 操作,垃圾回收过程中的回收往往需要长得多的时间。 如果 Object 保存了对任何资源的引用,则 Finalize 必须由派生类重写,以便在垃圾回收过程中,在放弃 Object 之前释放这些资源。 当类型使用文件句柄或数据库连接这类在回收使用托管对象时必须释放的非托管资源时,该类型必须实现 Finalize。有关辅助和具有更多控制的资源处置方式,请参见 IDisposable 接口。 Finalize 可以采取任何操作,包括在垃圾回收过程中清理了对象后使对象复活(即,使对象再次可访问)。但是,对象只能复活一次;在垃圾回收过程中,不能对复活对象调用 Finalize。析构函数是执行清理操作的 C# 机制。析构函数提供了适当的保护措施,如自动调用基类型的析构函数。在 C# 代码中,不能调用或重写 Object.Finalize。
收起全文
精华内容
下载资源
问答
  • finalize

    千次阅读 2019-02-17 12:39:19
    finalize 当某个类重载finalize()方法后,该类的实例对象在没被引用而被GC清理时会执行finalize()方法。 文档原文: Called by the garbage collector on an object when garbage collectiondetermines that there ...

    finalize

    当某个类重载finalize()方法后,该类的实例对象在没被引用而被GC清理时会执行finalize()方法。

    • 文档原文:
      Called by the garbage collector on an object when garbage collectiondetermines that there are no more references to the object.A subclass overrides the finalize method to dispose ofsystem resources or to perform other cleanup.
    	代码清单:
    	protected void finalize()
    	{
    		switch(m_id)
    		{
    		case 1:
    			System.out.print("《飘》");
    			break;
    		case 2:
    			System.out.print("《java程序设计教程》");
    			break;
    		case 3:
    			System.out.print("《罗马假日》");
    			break;
    		default:
    			System.out.print("未知书籍");
    			break;
    	    }
    		System.out.println("所对应的实例对象存储单位被收回");
    	 }
    	
    	public static void main(String[] args)
    	{
    		J_book book1=new J_book(1);
    		new J_book(2);
    		new J_book(3);
    		System.gc();// TODO Auto-generated method stub
    	}
    
    	执行结果:
    	 《罗马假日》所对应的实例对象存储单位被收回
    	 《java程序设计教程》所对应的实例对象存储单位被收回
    
    展开全文
  • Finalize

    2014-03-19 09:23:09
    类的Finalize方法,可以告诉垃圾回收器应该执行的操作,该方法从Object类继承而来。在从堆中永久删除对象之前,垃圾回收器调用该对象的Finalize方法。注意,无法确切地保证垃圾回收器何时调用该方法,也无法保证调用...
    类的Finalize方法,可以告诉垃圾回收器应该执行的操作,该方法从Object类继承而来。在从堆中永久删除对象之前,垃圾回收器调用该对象的Finalize方法。注意,无法确切地保证垃圾回收器何时调用该方法,也无法保证调用不同对象的方法的顺序。即使一个对象包含另一个对象的引用,或者在释放一个对象很久以前就释放了另一个对象,也可能会以任意的顺序调用这两个对象的Finalize方法。如果必须保证采用特定的顺序,则必须提供自己的特有清理方法。


    public class FinalizeTest {

    public FinalizeTest() {}

    public static void main(String [] args) {
    FinalizeTest og = new FinalizeTest();
    //很明显,og没有存在的意义了
    og = null;
    //由于垃圾回收是不定时的,我们还是手动回收看看吧
    System.gc();
    }
    //当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。
    protected void finalize() {
    System.out.println("我已经被垃圾回收器回收了...");
    }
    }
    finalize 的常规协定是:当 JavaTM 虚拟机已确定尚未终止的任何线程无法再通过任何方法访问此对象时,将调用此方法,除非由于准备终止的其他某个对象或类的终结操作执行了某个操作。finalize 方法可以采取任何操作,其中包括再次使此对象对其他线程可用;不过,finalize 的主要目的是在不可撤消地丢弃对象之前执行清除操作。例如,表示输入/输出连接的对象的 finalize 方法可执行显式 I/O 事务,以便在永久丢弃对象之前中断连接。

    对于任何给定对象,Java 虚拟机最多只调用一次 finalize 方法。

    finalize 方法抛出的任何异常都会导致此对象的终结操作停止,但可以通过其他方法忽略它。

    finalize就是一个对象的遗书,你把一个对象给杀了总的让他说点什么把。只不过你要注意finalize是垃圾回收启动来清理对象才来调用的,就算自己掉这个方法这个对象也不会就从内存消失的,代码楼上就行。还有就是这个遗书可以把自己复活,另外如果在这个方法抛异常会导致此对象的终结操作停止,这两种都是死而复生的手段。
    展开全文
  • finalize()

    万次阅读 多人点赞 2019-06-03 11:58:06
    finalize()是Object中的方法,当垃圾回收器将要回收对象所占内存之前被调用,即当一个对象被虚拟机宣告死亡时会先调用它finalize()方法,让此对象处理它生前的最后事情(这个对象可以趁这个时机挣脱死亡的命运)。...

    finalize()是Object中的方法,当垃圾回收器将要回收对象所占内存之前被调用,即当一个对象被虚拟机宣告死亡时会先调用它finalize()方法,让此对象处理它生前的最后事情(这个对象可以趁这个时机挣脱死亡的命运)。要明白这个问题,先看一下虚拟机是如何判断一个对象该死的。

     

    判定死亡

    "GC ROOTS"定义:GC管理的主要区域是Java堆,一般情况下只针对堆进行垃圾回收。方法区、栈和本地方法区不被GC所管理,因而选择这些区域内的对象作为GC roots,被GC roots引用的对象不被GC回收。

    "GC ROOTS"也可以看做是引用链的最顶级。

    Java采用可达性分析算法来判定一个对象是否死期已到。Java中以一系列"GC  Roots"对象作为起点,如果一个对象的引用链可以最终追溯到"GC  Roots"对象,那就天下太平。
    否则如果只是A对象引用B,B对象又引用A,A,B引用链均为能达到"GC  Roots"的话,那它俩将会被虚拟机宣判符合死亡条件,具有被垃圾回收器回收的资格。

     

    最后的救赎

    上面提到了判断死亡的依据,但被判断死亡后,还有生还的机会。
    如何自我救赎:
    1.对象覆写了finalize()方法(这样在被判死后才会调用此方法,才有机会做最后的救赎);
    2.在finalize()方法中重新引用到"GC  Roots"链上(如把当前对象的引用this赋值给某对象的类变量/成员变量,重新建立可达的引用).


    需要注意:


    finalize()只会在对象内存回收前被调用一次(The finalize method is never invoked more than once by a Java virtual machine for any given object. );
    finalize()的调用具有不确定行,只保证方法会调用,但不保证方法里的任务会被执行完(比如一个对象手脚不够利索,磨磨叽叽,还在自救的过程中,被杀死回收了)。

     

    finalize()的作用


    虽然以上以对象救赎举例,但finalize()的作用往往被认为是用来做最后的资源回收。
    基于在自我救赎中的表现来看,此方法有很大的不确定性(不保证方法中的任务执行完)而且运行代价较高。所以用来回收资源也不会有什么好的表现。

    综上:finalize()方法并没有什么鸟用。

    至于为什么会存在这样一个鸡肋的方法:书中说“它不是C/C++中的析构函数,而是Java刚诞生时为了使C/C++程序员更容易接受它所做出的一个妥协”。

    参考:《深入理解Java虚拟机:JVM高级特性与最佳实践》
     

    展开全文
  • finalize方法定义在Object中:protected void finalize() throws Throwable { }在对象中我们可以重定义这个方法。在这个方法中可以释放各种资源。关于这一点,相信大多数人都比较熟悉了。但是关于 finalize 到底什么...

    本文是Reference相关内容的最后一篇了。在这一篇,我们介绍一下 FinalReference 和 finalize方法。

    finalize方法定义在Object中:

    protected void finalize() throws Throwable { }

    在对象中我们可以重定义这个方法。在这个方法中可以释放各种资源。关于这一点,相信大多数人都比较熟悉了。但是关于 finalize 到底什么时候被调用,好像没有人能说清楚。我们来看一下 hotspot 到底是怎么来实现的。

    首先,hotspot 里会把类的构造方法的最后一条指令,也就是Java虚拟机指令的return,重写为一个特殊的指令:

    void Rewriter::rewrite_Object_init(methodHandle method, TRAPS) {
      RawBytecodeStream bcs(method);
      while (!bcs.is_last_bytecode()) {
        Bytecodes::Code opcode = bcs.raw_next();
        switch (opcode) {
          case Bytecodes::_return: *bcs.bcp() = Bytecodes::_return_register_finalizer; break;
    // 以下代码略

    这个指令,在解释器里是这样被执行的:

    if 

    这其实是一段手写的汇编,大概是这样的,Klass结构的指针先加载到rdi寄存器,然后,去取得它的acess_flag,去检查这个Klass是否定义了finalize方法。如果一个类里定义了finalize,那么在加载的时候,就会使它的access_flag中的JVM_ACC_HAS_FINALIZER置位。

    也就是说,如果这个Klass中定义了finalize方法,就会调用 register_finalizer 这个方法。这个方法我们就不去看了,有兴趣的同学自己去查。

    反正最终呢,会调用到Finalizer.java中定义的这个类中:

      /* Invoked by VM */
        static void register(Object finalizee) {
            new Finalizer(finalizee);
        }

    就是说,如果一个定义了finalize方法的类在初始化的时候,就会调用一下这个static方法,生成一个Finalizer对象,而我们自己的对象就是这个方法中所使用的finalizee。

    也就是说,我们新建一个带 finalize 方法的对象,就会伴生一个 Finalizer 对象。我们看一下,这个类的定义:

    final class Finalizer extends FinalReference<Object> { /* Package-private; must be in
                                                              same package as the Reference
                                                              class */
    
        private static ReferenceQueue<Object> queue = new ReferenceQueue<>();
        private static Finalizer unfinalized = null;
        private static final Object lock = new Object();
    
        private Finalizer
            next = null,
            prev = null;
    
        private boolean hasBeenFinalized() {
            return (next == this);
        }
    
        private void add() {
            synchronized (lock) {
                if (unfinalized != null) {
                    this.next = unfinalized;
                    unfinalized.prev = this;
                }
                unfinalized = this;
            }
        }
    
        private void remove() {
            synchronized (lock) {
                if (unfinalized == this) {
                    if (this.next != null) {
                        unfinalized = this.next;
                    } else {
                        unfinalized = this.prev;
                    }
                }
                if (this.next != null) {
                    this.next.prev = this.prev;
                }
                if (this.prev != null) {
                    this.prev.next = this.next;
                }
                this.next = this;   /* Indicates that this has been finalized */
                this.prev = this;
            }
        }
    
        private Finalizer(Object finalizee) {
            super(finalizee, queue);
            add();
        }

    Hoho,绕了半天,这和上节课所讲的Cleaner何其相似,都是一个双向队列,在构造的时候就把新建的Finalizer对象加入到一个双向链表中。

    注意上面这段代码里的queue,大家还记得Reference Handler线程吗?那个线程会把所有的Reference从pending链表上取出来,然后加入到一个queue中。对于FinalReference,就都会加入到上述代码中的queue中。这个queue中的所有对象,都会被一个名为Finalizer的线程所处理。我们之前也介绍过Reference Handler是2号线程,Finalizer线程是3号线程。Finalizer线程的代码如下所示:

    private 

    最终就是会从队列中不断地取出Finalizer对象,然后去调用它的runFinalizer方法。

      private void runFinalizer(JavaLangAccess jla) {
            synchronized (this) {
                if (hasBeenFinalized()) return;
                remove();
            }
            try {
                Object finalizee = this.get();
                if (finalizee != null && !(finalizee instanceof java.lang.Enum)) {
                    jla.invokeFinalize(finalizee);
    
                    /* Clear stack slot containing this variable, to decrease
                       the chances of false retention with a conservative GC */
                    finalizee = null;
                }
            } catch (Throwable x) { }
            super.clear();
        }

    这个方法使用了JavaLangAccess做为参数,其实就是一次虚函数调用,调用到finalizee中的 finalize 方法。

    hasBeenFinalized的作用就是保证finalize方法只会被调用一次。

    Finalizer vs. Cleaner

    因为Finalizer也是一种Reference,所以前边Reference的处理逻辑是和Weak, Soft reference的逻辑十分相似的。

    而且Finalizer和Cleaner的作用也十分相似,但有一个巨大的不同在于,finalize方法里可以使object 复活,而 Cleaner 的 clean 方法中不能使得对象复活。

    这是因为 finalize 中,可以通过 this 指针访问到 object 对象,例如:

    public void finalize() {
        Other.ref = this;
    }

    这样的话,一个本来应该被回收的对象又在finalize之后复活了。但是Cleaner为什么不行呢?因为它的基类是一个PhantomReference,这个“鬼引用”的 get 方法是这样的:

    public class PhantomReference<T> extends Reference<T> {
        public T get() {
            return null;
        }
        // 其它代码略
    }

    永远返回null,也就是说对于Cleaner,创建了以后,就再也不能访问它的referent了。

    所以现在有人提案,在Java中去掉finalize方法,只使用Cleaner来维护。

    其实,这里面还有其他的一些细节,比如为什么Weak的referent会被JVM清掉,而Finalizer又不会清掉自己的referent呢。这些就都不重要了。我就不再讲解了。

    我想,经过了这四节课,我们就可以把WeakReference, SoftReference, PhantomReference和Cleaner, FinalReference和Finalizer这6种对象全部搞清楚了。

    上一节课:PhantomReference & Cleaner

    下一节课:Tracing GC(1)

    课程目录:课程目录

    展开全文
  • finalize method

    2020-12-01 14:38:03
    <div><p>Just watched episode 52 and saw you using finalize method. There is a rule in java never use finalize because finalize is not guaranteed to be called. Rather use destroy or close ore something...
  • Java中final、finally和finalize的区别

    万次阅读 多人点赞 2017-03-28 20:00:13
    final、finally、finalize的区别 1、final修饰符(关键字)。被final修饰的类,就意味着不能再派生出新的子类,不能作为父类而被子类继承。因此一个类不能既被abstract声明,又被final声明。将变量或方法声明为...
  • finalize机制

    2018-09-22 13:25:42
    虽然JDK9之后用Cleaner机制代替了finalize机制进行内存清理,但是平时开发用的这里还是还是JDK8,emmmm.......就简单总结一下finalize机制吧。 finalize()是Object类下的方法,所以任何类都可以重写finalize()方法...
  • finalize方法

    2018-10-10 14:59:57
    finalize 是Object类的一个方法,该方法的访问修饰符为protected。 finalize函数的最后一个语句通常是 super.finalize(),通过这种方式,可以实现从下到上实现finalize的调用,即先释放自己的资源,再释放父类的...
  • 日记 finalize

    2019-09-17 19:34:03
    finalize 方法名。Java 技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在 Object 类中定义的,...
  • finalize作用

    2020-09-14 08:00:11
    finalize()是Object中的方法,当垃圾回收器将要回收对象所占内存之前被调用,即当一个对象被虚拟机宣告死亡时会先调用它finalize()方法,让此对象处理它生前的最后事情(这个对象可以趁这个时机挣脱死亡的命运)。...
  • java finalize

    2018-02-06 11:31:49
    1. finalize的作用   finalize()是Object的protected方法,子类可以覆盖该方法以实现资源清理工作,GC在回收对象之前调用该方法。finalize()与C++中的析构函数不是对应的。C++中的析构函数调用的时机是确定的...
  • finalize理解

    2018-11-14 23:44:15
    finalize不是c++里面的析构函数,c++中对象销毁时一定调用析构函数,对象一定会被销毁(如果程序没有出错);java的对象却并非总是被垃圾回收。 1、对象可能不被垃圾回收; 2、垃圾回收并不等于“析构”; 3、...
  • Java finalize

    2017-04-30 11:01:24
    finalize是什么? finalize是Object类中定义的一个方法:protected void finalize() throws Throwable { }。 垃圾回收器在垃圾收集时,会调用被回收对象的此方法。
  • <div><p>MPII_Coll_finalize deregisters collectives progress hook. But that is needed by MPID_Finalize that calls Allreduce collective. Change the order.</p><p>该提问来源于开源项目:pmodels/mpich...
  • Finalize operator results

    2020-12-30 06:24:57
    <div><p>To set sort orders and table clustering in #2000, several operators needed to first finalize their results. With that we realized that all read-only operators should always <code>finalize()...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 13,964
精华内容 5,585
关键字:

finalize