Automatic Resource Management, V.2

Joshua Bloch jjb at google.com
Mon Apr 20 09:19:47 PDT 2009


Neal,


> I am disappointed to see that this revision addresses none of the ergonomic
> issues reported earlier, not even those that were identified in the previous
> ARM proposal years ago and for which a solution was promised in the
> revision.
>


I am sorry you're disappointed. I do believe I addressed all the substantive
issues that you raised:

(1) "try" is not a natural keyword for the intended semantics.


You didn't really back this one up.  Other people have commented on what a
great fit they think it is.  So we'll just have to consider it an issue of
taste, on which reasonable men may disagree.


> (2) Checked exceptions from close() should be discarded for some clients.


The revision says this:

*5. Some failures of the **close** method can be safely ignored (e.g.,
closing a file that was open for read). Does the construct provide for this?
*

No. While this functionality seems attractive, it is not clear that it's
worth the added complexity. As a practical matter these “harmless
exceptions” rarely if ever occur, so a program will be no more robust if
these exceptions are ignored. If you feel you must ignore them, there is a
workaround, but it isn't pretty:

    static void copy(String src, String dest) throws IOException {
        boolean done = false;
        try (InputStream in = new FileInputStream(src)) {
            try(OutputStream out = new FileOutputStream(dest)) {
                byte[] buf = new byte[8192];
                int n;
                while ((n = in.read(buf)) >= 0)
                    out.write(buf, 0, n);
            }
            done = true;
        } catch(IOException e) {
            if (!done)
                throw e;
        }
    }



>
> (3) The nesting of new behavior with old behavior in the try statement
> is a poor fit for many clients. [Discussion of LineNumberReader snipped]


The revision says this:

2. Does the construct allow access to resources after an exception is thrown
from within the block, but before the resource is closed?

Not directly. The need for this functionality is rare. The workaround is to
nest a try-catch block inside the automatic resource management statement:

    try (LineNumberReader reader = getInput()) {
        try {
            parseInput(reader);
        } catch (CharacterCodingException ex) {
            report("Char encoding error at line " + reader.getLineNumber());
            throw ex;  // Rethrow the exception
        }
    }




>
> (4) The proposed construct doesn't retrofit onto many APIs in the
> profile of use-cases for which it was designed.


The revision says this:

* 4. Does the construct support resource types whose termination method has
a name other than **close**?*

Not directly. There are two obvious ways in which the construct could have
supported this functionality. One is to designate the termination method
with an annotation. But this violates the rule that annotations cannot
change the semantics of a program (JLS §9.7). The other is to use an actual
modifier to denote the termination method (the finally keyword has been
proposed for this purpose). This would, however, require a class file format
change, and a mandate changes to tools such as JavaDoc. The resulting
construct would be more “magical,” and wouldn't mesh as well with Java’s
type system.

The proposed construct is an “80-20” solution. It is aimed squarely at
solving the serious problem of Closeables. Most resources can be retrofitted
to implement AutoCloseable, but a few can't (e.g., interface types that do
not already contain a parameterless close method and class types that
contain a parameterless close method with the wrong return type or
semantics). For such resources, we recommend the use of an adapter, such as
AutoLock above. The exact form of the adapter will differ depending on the
details of the resource.


      Regards,

      Josh



More information about the coin-dev mailing list