【问题标题】:How to make sure resource is released, with nested object hierarchy?如何确保资源被释放,嵌套对象层次结构?
【发布时间】:2015-12-12 15:02:53
【问题描述】:

我有这样的代码(简化):

class A {

    B b = new B();

    void close() {
        b.close();
    }
}

class B {

    Closeable mustBeClosed = new Closeable() {
        {
            System.out.println("create");
        }
        @Override
        public void close() {
            System.out.println("close");
        }
    };

    int n = 0 / 0;

    void close() {
        mustBeClosed.close();
    }
}

//code
try (A a = new A()) {
    //do something
}

如何保证mustBeClosed被释放?

当对象层次结构复杂时,可能会发生这种情况。覆盖 B 的 finalize 可能不是一个完美的解决方案。

有针对此问题的最佳实践或原则吗?

修改后的版本如下:

class B {
    Closeable mustBeClosed;
    B() {
        try {

            mustBeClosed = ...

            //other initialization which might raise exceptions

        } catch (throwable t) {
            close();
            throw t;
        }
    }

    void close() {
        if (mustBeClosed != null) {
            try {
                mustBeClosed.close();
            } catch (Throwable t) {
            }
        }
        //all other resources that should be closed
    }
}

然而,这需要太多的代码并且远非优雅。更重要的是,所有权层次结构中的所有类似乎都应该遵循相同的样式,这会导致大量代码。

有什么建议吗?

【问题讨论】:

    标签: java resource-management


    【解决方案1】:

    您的问题是,如果构造函数抛出异常,try-with-resources 将不会(实际上不能)调用close()

    任何分配资源的对象构造,并且在构造过程中可能会失败在分配资源之后必须在异常级联之前释放该资源调用堆栈。

    两种解决方法:

    1) 确保确保资源分配是最后执行的操作。在您的情况下,这意味着将字段 n 移动到字段 mustBeClosed 之前。

    2) 在构造函数中而不是在字段初始值设定项中处理资源构造,因此您可以捕获任何后续异常并在重新抛出异常之前再次释放资源,如您的替代解决方案所示。
    但是,您不必在 close() 方法中进行 null 检查,因为如果对象构造成功,mustBeClosed 将始终为非 null,而如果对象构造失败,则无法调用 close()

    【讨论】:

      【解决方案2】:

      使用包装器方法关闭所有Closeable 实例优雅地

      closeGraceFully(Closeable c) { // call this guy for all instances of closeable
         try{
             c.close();
         } catch(IOException ex) {
            // nothing can be done here, frankly.
        }
      }
      

      然后调用这个包装方法。不要直接打电话给close()。不要使用finalizers 他们是邪恶的,会减慢你的应用程序。

      【讨论】:

        猜你喜欢
        • 2013-02-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多