• java学习之(垃圾回收)


    程序无法精确控制java垃圾回收的时机,但依然可以强制系统进行垃圾回收--这种强制只是通知系统进行垃圾回收, 但系统是否进行垃圾回收依然不确定。大部分时候,程序强制系统垃圾回收后总会有一些效果,强制系统垃圾回收 有如下两种方式。
    1.调用System类的gc()静态方法:System.gc();
    2.调用Runtime对象的gc()实例方法:Runtime.GetRuntime().gc();
     
     
    public class GcTest
    {
        public static void main(String[] args)
        {
            for(int i=0;i<4;i++)
            {
                new GcTest();
                System.gc();
            }
        }
        public void finalize()
        {
            System.out.println("系统正在清理GcTest对象的资源...");
        }
    }
     
    javac GcTest后也看不到任何输出
    但使用下面命令可以看到清理垃圾的操作
     
    java -verbose:gc GcTest
     
     
     
     
     
    finalize方法
     在垃圾回收机制回收某个对象所占用的内存之前,通常要求程序调用适当的方法来清理资源,在没有明确指定清理资源的情况下,java提供了默认机制清理该对象的资源,这个机制就是finalize()方法。
    该方法是定义在Object类里的实例方法,方法原型为:
        protected void finalize() throws Throwable
    当finalize()方法返回后,对象消失,垃圾回收机制开始执行。方法原型中的throws Throwable表示它可以抛出任何类型的异常。
        任何Java类都可以重写Object类的finalize()方法,在该 方法中清理该对象占用的资源,如果程序终止之前始终没有进行垃圾回收,则不会调用失去引用对象的finalize()方法清理资源。垃圾回收机制何时调用对象的finalize()方法是完全透明的,只有当程序认为需要更多的额外内存时,垃圾回收机制才会进行垃圾回收,因此,完全有可能出现这样的一种情形,某个失去引用的对象只占用了少量内存,耐用系统没有产生严重的内存需求,因此垃圾回收机制并没有试图回收该对象所占用的资源,所以该对象的finalize()方法也不会得到调用。
     finalize()方法具有如下4个特点
    1. 永远不要主动调用某个对象的finalize()方法,该方法应交给垃圾回收机制调用。
    2.finalize()方法何时被调用,是否被调用具有不确定性,不要把finalize()方法当成一定会被执行的方法。
    3.当JVM执行可恢复对象的finalize()方法时,可能使该对象或系统中其他对象重新变成可达状态。
    4.当JVM执行finalize()方法时出现异常时,垃圾回收机制不会报告任何异常,程序继续执行
     
     
       由于finalize()方法并不一定会被执行,因此如果想清理某个类里打开的资源,则不要放在finalize()方法中 进行清理。
     
     
     
     
    public class FinalizeTest
    {
        private static FinalizeTest ft=null;
        public void info()
        {
            System.out.println("测试资源清理的Finalize方法");
        }
        public static void main(String[] args)throws Exception
        {
            //创建FinalizeTest对象立即进入可恢复状态
            new FinalizeTest();
            //通知系统进行资源回收
            System.gc();
            //强制垃圾回收机制调用可恢复对象的finalize()方法
            //Runtime.getRuntime().runFinalizAtion();
            System.runFinalization();
            ft.info();
        }
     
        public void finalize()
        {
            //让ft引用到试图回收的可恢复对象,即可恢复对象重新变成可达对象;
            ft=this;
        }
    }
     
     
     
     
    上面的程序中定义了一个FinalizeTest类,重写了该类的finalize()方法,在该方法中把需要清理的可恢复对象重新赋给了ft引用变量,从而让该可恢复对象重新就可达状态。
    上面程序中的main()方法创建了一个FinalizeTest类的匿名对象,因为创建后没有把这个对象赋给任何引用变量,所以该对象立即进入可恢复状态。进入可恢复状态后,系统调用System.gc();通知系统进行垃圾回收,而System.runFinalization(); 强制系统立即调用可恢复对象的finalize()方法,再次调用ft对象的info方法。编辑运行上面程序 看到如下结果:
     
     
     
     
    如果不执行System.gc()方法,程序并没有通知系统开始执行垃圾回收,因此系统通常不会立即 进行垃圾回收,也就不会调用 FinalizeTest对象的finalize()方法,这样FinalizeTest的ft类变量将依然保持为null,这样就导致了空指针异常。
    上面程序中如果不执行 Runtime.getRuntime().runFinalization();
    或System.runFinalization(); 由于JVM垃圾回收机制的不确定性,JVM往往并不立即调用可恢复对象的finalize()方法,这样FinalizeTest的ft类变量可能依然为null,可能依然会导致指针异常。
  • 相关阅读:
    JS实现在线ps功能
    Vmware 下安装linux虚拟机
    一文了解:Redis主从复制
    一文了解:Redis过期键删除策略
    一文了解:Redis的AOF持久化
    一文了解:Redis的RDB持久化
    一文了解:Redis事务
    一文了解:Redis基础类型
    并发一:Java内存模型和Volatile
    干了这杯java之ThreadLocal
  • 原文地址:https://www.cnblogs.com/haofaner/p/5541600.html
Copyright © 2020-2023  润新知