简体   繁体   English

构造函数抛出异常后可以调用finalize吗?

[英]Can finalize be called after a constructor throws an exception?

Are there any details on whether or not an object is cleaned up using finalize() if that object's constructor thew an exception. 是否有关于是否使用finalize()清除对象的详细信息finalize()如果该对象的构造函数有异常)。

When this method is called is notoriously ill defined. 众所周知,定义此方法的时间很短。 According to the manual: 根据手册:

The Java programming language does not guarantee which thread will invoke the finalize method for any given object. Java编程语言不保证哪个线程将为任何给定对象调用finalize方法。 It is guaranteed, however, that the thread that invokes finalize will not be holding any user-visible synchronization locks when finalize is invoked. 但是,可以保证,在调用finalize时,调用finalize的线程将不持有任何用户可见的同步锁。 If an uncaught exception is thrown by the finalize method, the exception is ignored and finalization of that object terminates. 如果finalize方法抛出未捕获的异常,则该异常将被忽略,并且该对象的终结将终止。

http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#finalize%28%29 http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#finalize%28%29

I've not been able to trigger the finalize method in this way. 我无法以这种方式触发finalize方法。 Does anyone know if it is garunteed NOT to be called or if it is in some cases called after the constructor failed to initialize the object (thew an exception). 有谁知道构造器无法初始化对象(因此是异常)之后是否要不调用它,或者在某些情况下是否调用了它。

I ask this because I have an object which must not be cleaned up twice. 我之所以这样问,是因为我有一个不能两次清理的物体。 I'm trying to understand if it is safe to clean up before throwing the exception or if I must leave a marker for finalize() to effectively skip and do nothing. 我试图了解在引发异常之前清理是否安全,或者是否必须为finalize()留一个标记以有效地跳过并且什么也不做。

My test shows that it can 我的测试表明它可以

public class Test1 {

    Test1() {
        throw new RuntimeException();
    }

    @Override
    protected void finalize() throws Throwable {
        System.out.println("finalized");
    }

    public static void main(String[] args) throws Exception {
        try {
            new Test1();
        } catch (RuntimeException e) {
            e.printStackTrace();
        }
        System.gc();
        Thread.sleep(1000);
    }
}

prints 版画

java.lang.RuntimeException
    at test.Test1.<init>(Test1.java:13)
    at test.Test1.main(Test1.java:24)
finalized

it is on Java HostSpot Client VM 1.7.0_03 它在Java HostSpot客户端VM 1.7.0_03上

According to section 12.6.1. 根据第12.6.1 Implementing Finalization of the JLS: 实施 JLS的定稿

An object o is not finalizable until its constructor has invoked the constructor for Object on o and that invocation has completed successfully (that is, without throwing an exception). 在对象o的构造函数调用了o上的Object的构造函数并且该调用成功完成(即没有引发异常)之后,该对象o才能终结。

If your constructor throws an exception after the Object constructor completes, then your object should be finalizable, so finalize() could still be called. 如果您的构造函数在Object构造函数完成引发异常,则您的对象应该是可终结的,因此仍可以调用finalize()

There's a good example stepping through object construction in section 12.5. 在第12.5节中有一个很好的示例逐步介绍了对象的构造 Creation of New Class Instances that shows exactly when the Object constructor is called. 创建新类实例 ,该实例准确显示了何时调用Object构造函数。

To demonstrate more clearly: 为了更清楚地演示:

public class Test1 {

    public static class LifeBoat extends RuntimeException
    {
        private Test1 passenger;
        public Test1 getPassenger(){return passenger;}
        public LifeBoat(Test1 passenger){this.passenger=passenger;}
    }

    Test1() {
        super(); //once this is finished, there is an Object to GC per JLS 12.6.1. 
        throw new LifeBoat(this);
    }

    @Override
    protected void finalize() throws Throwable {
        System.out.println("finalized");
    }

    public static void main(String[] args) throws Exception {
        try {
            new Test1();
        } catch (LifeBoat e) {
            Test1 obj;
            obj=e.getPassenger();
            System.out.println(obj);
        }
        System.gc();
        Thread.sleep(1000);
    }
}

prints 版画

java.lang.RuntimeException
    at test.Test1.<init>(Test1.java:13)
    at test.Test1.main(Test1.java:24)
test.Test1@6dc8f3cd
finalized

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM