1

I want to check the condition in termination with finalize, but finalize never be executed each time. Can anybody tell me why?

public class Test
{

    public static void main(String[] args)
    {   
        Tank tank=new Tank();
        tank.fill();
        System.gc();
    } 
}  
public class Tank    {

    private boolean emptied=true;

    public void fill()
    {
        this.emptied=false;
    }

    public void empty()
    {
        this.emptied=true;
    }

    public Tank()
    {
        this.emptied=true;
    }

    protected void finalize()
    {
        if(this.emptied==false)
        {
            System.out.println("Termination Verification Error: Tank should be emptied");
        }
    }
}
4

2 回答 2

5

finalize()方法仅在对象被 GC 销毁和终结时调用,这发生在对对象的最后一个引用被丢弃后的某个未定义的时间点。如果该对象从未被释放(例如,您仍然有对它的引用),则finalize()永远不会被调用。

还要记住,您无法控制何时 finalize()调用,或者它是否会被调用。请参阅 的一般说明Object.finalize()

EvenSystem.gc()不能保证强制 GC 做任何事情。这只是对 JVM 的一个建议。见一般描述System.gc()

通常,如果您发现自己试图像这样操作 GC 以执行这些类型的检查,通常有更好的方法。这是finalize()对 GC 的不当使用。

例如,如果您尝试检查假定条件是否为真,请考虑assert在适当的位置使用(但请注意:assert不是功能的替代品if;它只是自我记录和测试设计时假定的条件) .

如果您的应用程序的高级功能的一部分是在退出之前验证条件是否为真,那么您应该在退出之前明确验证条件是否为真,例如在您的情况下:

public static void main(String[] args)
{   
    Tank tank=new Tank();
    tank.fill();
    // check explicitly before terminating
    if (!tank.empty()) 
        System.err.println("Warning: Ending with non-empty tank!");
} 

除了尝试从错误中恢复的能力之外,显式检查还可以让您完全控制它何时发生。

更新:另一个很好的选择,MadProgrammer 在下面的评论中很有帮助地提出,是使用关机钩子,如果这适合你的话。如果您的应用程序有多个您无法消除或控制的退出点,这将提供一种在关闭时退出代码的干净方式。

对于更复杂的应用程序,顺便说一下,你会发现单元测试等测试策略,结合良好的模块化设计(例如明确定义的前置条件、后置条件、不变量),可以提供完整的应用程序逻辑测试,而无需自测测试成为应用程序正常运行的一部分。并不是说后者有什么问题,尤其是在简单的应用程序中,但您可能有兴趣了解它以供将来参考。

于 2013-11-08T22:09:18.490 回答
2

根据JLS 12.6。类实例的最终确定

Java 编程语言没有指定终止器将在多长时间内被调用,只是说它会在对象的存储被重用之前发生。

于 2013-11-08T22:09:18.330 回答