• java finalize及实践


    https://www.cnblogs.com/Smina/p/7189427.html 

     

    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方法会被及时地执行、而且根本不会保证它们会被执行 由于gc是守护线程,可能不会调用finalize
    • finalize方法可能会带来性能问题。因为JVM通常在单独的低优先级线程中完成finalize的执行(可能达400倍)
    • 超类中的finalize()方法需要显示的调用,super.finalize(),会忘记
    • 任何有finalize()方法抛出的异常都会被GC线程忽略(优先级低)而且不会被进一步传播,事实上也不会在日志文件上记录下来http://blog.csdn.net/maoyeqiu/article/details/49562093
    • 对象再生问题:finalize方法中,可将待回收对象赋值给GC Roots可达的对象引用,从而达到对象再生的目的
    • finalize方法至多由GC执行一次(用户当然可以手动调用对象的finalize方法,但并不影响GC对finalize的行为)
    • 造成gc卡顿

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

     

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

     证明:

    public class TestGcFinalize {
    
        public static void main(String []f) throws InterruptedException {
    
            NoFinalize noFinalize = new NoFinalize();
            WithFinalize withFinalize = new WithFinalize();
            noFinalize = null;
            withFinalize = null;
            System.gc();
            System.out.println("1d");
            Thread.sleep(20000);  // jmap -dump:format=b,file=dump1.dump <pid> nolive
            System.out.println("s2");
            System.gc();
            System.out.println("2d");
            Thread.sleep(20000);  // jmap -dump:format=b,file=dump1.dump <pid> nolive
            System.out.println("d");
        }
    
        private static class NoFinalize {
    
        }
    
        private static class WithFinalize {
    
            @Override
            public void finalize() {
                System.out.println("finalize");
            }
        }
    }
    

          NoFinalize    WithFinalize

    第一次gc  直接回收    调用finalize,下次回收

    第二次gc       /        回收

     可以看到第一次gc,虽然调用了WithFinalize的finazlize方法,但没有直接回收掉,直到第二次gc才回收掉

    finalizedump.zip

    https://www.cnblogs.com/QG-whz/p/6557333.html

    java的finalize()方法与C++的析构函数

     一旦C++的对象要被回收了,在回收该对象之前对象的析构函数将被调用,然后释放对象占用的内存;而java中

    一旦垃圾回收器准备好释放对象占用的存储空间,将首先调用其finalize()方法, 并且在下一次垃圾回收动作发生时,才会真正的回收对象占用的内存(《java 编程思想》)

    可见在java中,调用GC不等于真正地回收内存资源,而且在垃圾回收中对象存在状态的变化。


  • 相关阅读:
    ORACLE 查找数据库中有记录的表
    [原]Asp.Net 错误:无法连接到Asp.Net Developement server
    中国移动手机话费查询号码1008611
    动手修改VS2008的解决方案文件,以让VS2005打开它
    [转]飞秋使用说明与常见问题解决方法
    微软发布Fix it 修复Windows 7等系统0day漏洞
    Oracle DECODE 函数应用示例
    [转]C#实现访问网络共享文件夹
    c#保留小数点后位数的方法
    [转]微软紧急修复高危漏洞 30万网民PC已遭攻击
  • 原文地址:https://www.cnblogs.com/silyvin/p/9106669.html
Copyright © 2020-2023  润新知