Types for Automatic Resource Management

The purpose of this collaborative document is to provide a central spot for recording commonly used types (JDK or other libraries) that would benefit from automatic resource management.  The two main criteria are:

  1. Best practice demands that the resource typically has a "lexically scoped lifetime"  (i.e., its close/dispose method should be called when execution exits the scope in which they were acquired).
  2. The type is widely used in practice.  (Roughly speaking, at least thousands of programmers use it on a daily basis.)

For each type that satisfies these criteria, the document should indicate whether it is possible to retrofit the type to implement this interface:

package java.lang;

public interface AutoCloseable {

    void close() throws Exception;

}

The notations [1], [2], [1,2] indicate that the type in question doesn't satisfy the indicated criteria. If a number if followed by a question mark, it means that I don't know if the type satisfies the criterion, and I would appreciate input from an expert in the area.  For example, I'd appreciate input from a AWT/Swing expert on whether java.awt.graphics satisfies Criterion 1, and from an SWT expert on whether org.eclipse.swt.graphic.Resource satisfies Criterion 1.  (Presumably both satisfy Criterion 2.)

Note that criterion [2] is specifically aimed at improving things for APIs that exist today.  This language construct is not so much designed to make possible new APIs previously impractical except to the extent that those new APIs can be made to resemble the patterns of code of existing APIs (i.e. which are practical today).

The notation [R] indicates that an instance may be used after it is closed/disposed by a thread.

The notation [C] indicates that the API cannot easily be retrofitted to use the proposed mechanism in its current form.

java.io.Closeable

For starters, the interface  java.io.Closeable is a fine candidates for automatic resource management.  Retrofitting this interface would automatically retrofits these subinterfaces: ByteChannel, Channel, GatheringByteChannel, InterruptibleChannel, JavaFileManager, JMXConnector, ReadableByteChannel, RMIConnection, ScatteringByteChannel, StandardJavaFileManager, WritableByteChannel, and these classes: AbstractInterruptibleChannel, AbstractSelectableChannel, AudioInputStream, BufferedInputStream, BufferedOutputStream, BufferedReader, BufferedWriter, ByteArrayInputStream, ByteArrayOutputStream, CharArrayReader, CharArrayWriter, CheckedInputStream, CheckedOutputStream, CipherInputStream, CipherOutputStream, DatagramChannel, DataInputStream, DataOutputStream, DeflaterInputStream, DeflaterOutputStream, DigestInputStream, DigestOutputStream, FileChannel, FileInputStream, FileOutputStream, FileReader, FileWriter, FilterInputStream, FilterOutputStream, FilterReader, FilterWriter, Formatter, ForwardingJavaFileManager, GZIPInputStream, GZIPOutputStream, InflaterInputStream, InflaterOutputStream, InputStream, InputStream, InputStream, InputStreamReader, JarInputStream, JarOutputStream, LineNumberInputStream, LineNumberReader, LogStream, ObjectInputStream, ObjectOutputStream, OutputStream, OutputStream, OutputStream, OutputStreamWriter, Pipe.SinkChannel, Pipe.SourceChannel, PipedInputStream, PipedOutputStream, PipedReader, PipedWriter, PrintStream, PrintWriter, ProgressMonitorInputStream, PushbackInputStream, PushbackReader, RandomAccessFile, Reader, RMIConnectionImpl, RMIConnectionImpl_Stub, RMIConnector, RMIIIOPServerImpl, RMIJRMPServerImpl, RMIServerImpl, SelectableChannel, SequenceInputStream, ServerSocketChannel, SocketChannel, StringBufferInputStream, StringReader, StringWriter, Writer, ZipInputStream, ZipOutputStream.  Most of these types satisfy Criterion 1, and many satisfy Criterion 2.

The java.io.Closeable interface can easily be retrofitted to implement the autocloseable interface.

java.sql.Connection, Statement, PreparedStatement, ResultSet

These types satisfy Criteria 1 and 2, and can be retrofitted to implement AutoCloseable.

java.sql.Arrayjava.sql.Blobjava.sql.Clobjava.sql.SQLXML [C]

 JDBC 4.0 (Java 6) added a free() method to each of these interfaces (SQLXML is completely new in fact). The specification says '(these) objects remain valid for at least the duration of the transaction in which they are created. This could potentially result in an application running out of resources during a long running transaction. Applications may release (these) resources by invoking their free method'. It also seems to note that some JDBC drivers will not automatically release these resources when the transaction terminates. These types certainly meet criterion [1] and if they don't meet criterion [2] yet, they surely will in due course

java.awt.Graphics

Satisfies criteria 1 and 2.  Can be retrofitted by adding a close method that invokes dispose.

The javadoc for VolatileImage contains an example using Graphics2D which seems to fit criterion [1].  Ditto for java.awt.image.BufferStrategy, but using Graphics.

The Compositing Graphics page of the Java Tutorials appears to get it wrong in paintComponent() here as it doesn't dispose the created Graphics2D.

java.awt.image.VolatileImage [1]

Probably not used in a single lexical scope between declaration and disposal.

I (mm) agree, although this type is used in concert with java.awt.Graphics, which is allocated and disposed in a single lexical scope.

org.eclipse.swt.graphic.Resource [C]

and its subclasses Color, Cursor, Font, GC, Image, Path, Pattern, Region, TextLayout, and Transform.  We probably can't retrofit Path because it has an existing close() method, and therefore we can't retrofit its superclass, Resource, either.  But we probably can retrofit Color, Cursor, Font, GC, Image, Pattern, Region, TextLayout, and Transform.  The nonuniformity of support might be confusing to SWT programmers.

Since SWT's Resource types represent finite system resources, it is considered bad practice to hold them for longer than necessary. They are commonly created and disposed inside event listener methods (i.e. in a manner consistent with criterion [1]), to provide custom rendering of a component for example. For some types of Resource, this is probably the most common usage.

Examples of this are abundant in the 'SWT Snippets', a set of example code fragments used as the 'howto' for SWT, and to which programmers are often referred when asking for guidance on the mailing lists.

Although these snippets are generally (quoting from the Snippets page) 'edited for brevity' they are also 'intended to guide the reader towards the correct solution', yet none 'correctly' dispose of resources (because these two aims are currently difficult to reconcile in Java, for the exact reasons explained in the ARM proposal).

(One could probably replace all examples of resources in the ARM proposal with SWT equivalents, and the text would make just as much sense, except that the proposed interface cannot be retrofitted onto SWT's Resource class)

For longer-lived resources, SWT programmers tend to use a utility class which creates and retains a reference to the resources, and which can release them at a convenient point (e.g. when a window is closed). See the JFace ResourceRegistry for one such example.

A few examples from the SWT Snippets page:

Snippet 10: Use of resources inside a PaintListener

Snippet 280: Use of resources inside a PaintListener

Snippet 93: Creation of a GC to measure some text

Snippet 275: Similar to 93, but inside a Timer

Snippet 133: Printing via new GC, with bonus dodgy InputStream handling :)

Snippet 156: Creation of a temporary Image and GC (createSampleImage method)

java.nio.channels.FileLock

Could be retrofitted with AutoCloseable and a close() method.  They are frequently used in a scoped manner.

org.ietf.jgss.GSSCredential, org.ietf.jgss.GSSContext [C]

These are interfaces with a dispose() method, so not easily retrofitted.

javax.media.opengl.GLPbuffer [1?,2?,C]

GLPbuffer is a little awkward: it has a destroy method which seems to fit the use case, but it's an interface. GLPbuffers are created by calling GLDrawableFactory.createGLPbuffer() so perhaps it would be possible for a new AutoCloseableGLPbuffer type to be returned from this method. It does seem to be used in a lexically scoped manner in at least some cases, but I (mm) don't know if this is best practice, or common.

javax.xml.stream.XMLEventReaderjavax.xml.stream.XMLEventWriter

Also XMLStreamReader, XMLStreamWriter in the same package.  All these types have a close() method which should cause no problems when retrofitting AutoCloseable.

javax.imageio.ImageReaderjavax.imageio.ImageWriter

These classes have a dispose() method which should be called to release any resources being held.  They appear to be easy to retrofit with AutoCloseable.

javax.imageio.stream.ImageInputStream

Looks to me (mm) like it could extend java.io.Closeable, but perhaps I'm missing something.

org.apache.lucene.index.IndexWriter [C]

Lucene contains a number of types that look ideal for retrofitting with ARM, such as IndexOutput and Searchable.  Lucene has also been a pretty high-profile library over the years, so probably fits criterion [2].

However, one problematic case is IndexWriter. This class is commonly used, often in a way that satisfies criterion [1], and correct disposal is very important since (among other reasons) it creates a lock file to prevent any other IndexWriter from trying to update the same data simultaneously. This lock file is removed when the IndexWriter is closed, after which the writer should not be used, so I think IndexWriter qualifies as a resource that would be ideal for ARM to target.

IndexWriter has 3 methods that I think are relevant:

Clearly ARM cannot call close() in the generated finally block, so I think we'd want code using IndexWriter to look like this (with ARM):

        try (IndexWriter writer = ...) {

                // use the writer

                writer.commit();

   } // ARM calls writer.rollback() here

This doesn't seem to fit with AutoCloseable. However, I (mm) haven't used Lucene in a while, so I'd welcome any insights from someone with a better understanding.           

java.util.Iterator&AutoDisposable [2,C]

(This refers to any program type that extends or implements both Iterator and AutoDisposable.)

Consider an interface that extends both Iterator and AutoDisposable.  This represents a resource that, once it is acquired (by invoking iterator() on some Iterable), one can extract the elements out of (once), and must be terminated when iteration is done.  While most Iterators doesn't represent a resource, an Iterator is to be used once only, so this is a natural combination.  For example:

static LinesInAFile eachLine(File file) throws IOException { ... }

interface LinesInAFile extends Iterable<String> {

    AutoCloseableIterator<IOException,String> iterator();

}

interface AutoCloseableIterator<X,E> extends AutoCloseable, Iterator<E> {

    void close() throws X;

}

One can use this with the for-each loop:

try {

    LinesInFile lines  = eachLine(file);

    for (String line : lines) System.out.println(line);

} catch (IOException ex) {

    System.out.println("failed iterating " + lines);

}

but this is not correct, as the resource is not terminated.  One can use the proposed ARM block to terminate the resource, but then it is not possible to use the for-each loop

try {

    LinesInFile lines = eachLine(file);

    try (AutoCloseableIterator<IOException,String> it : lines.iterator()) {

            while (it.hasNext()) {

                String line = it.next();

                System.out.println(line);

            }

    }

} catch (IOException ex) {

    System.out.println("failed iterating " + lines);

}

Problem is, the two language support interfaces Iterable and AutoCloseable don't compose very well.  Consequently, the two language features - the for-each loop and the proposed ARM statement - do not compose well in the current specification.

We can learn from C# here, and avoid the same mistake that C# avoided.  The simple solution is to make the for-each loop dispose the iterator if it implements AutoDisposable, as C# does. The point, in part, is to make the proposed construct not just useful in code that already exists (criterion [2]), but useful in code yet to be written.

javax.naming.Context

Yet another widely-used type which is allocated and disposed in a lexically scoped manner, sometimes.  Should be trivial to retrofit with AutoCloseable as it already has a close() method for disposal purposes.

javax.rules.RuleSession StatefulRuleSession StatelessRuleSession [C]

JSR 94 (the Java Rule Engine API) defines a RuleSession interface, and its subtypes StatefulRuleSession and StatelessRuleSession, to allow client code to request that a RuleExecutionSet be executed by the rule engine. The API documentation says:

         'Note: the release method must be called to clean up all resources used by the RuleSession.'

Unfortunately, all three types are interfaces, so cannot be retrofitted with AutoCloseable.

JSR 94 is implemented by numerous proprietary and open-source products, from Oracle, JBoss, OpenRules and others.

Examples of creating and disposing a RuleSession in the same lexical scope:

java.beans.XMLEncoderXMLDecoder

These appear appropriate for use with ARM.  Their constructors take an Input/OutputStream, and close it when their close() method is invoked.  Should be easy to retrofit with AutoCloseable.

com.sleepycat.db.TransactionCursor

Berkeley DB is a widely used embedded database, which has its own API for database transactions, queries etc.  Berkeley DB Java Edition is a separate, pure-Java embedded database, with a very similar API to Berkeley DB. These comments largely apply to both APIs:

Transactions are modeled in a way that's almost compatible with ARM.  Each transaction is represented by a distinct object, and may not be reused once either commit()ed or abort()ed.

With ARM, use of a transaction might look like:

        try (Transaction txn = ...) {

                // use the txn

                txn.commit();

        } // ARM calls txn.abort()

At present, a call to commit() followed by abort() will throw an exception, leading to some awkward coding patterns in existing code. However this has been changed for the next release (of JE at least), specifically 'to make error handling easier'.

It does seem feasible to retrofit Transaction with AutoCloseable, and arrange for the close() method to call abort(). The main issue would be that, on the Berkeley DB version of Transaction, there would then be close(), discard() and abort(), which is bound to cause some confusion.

Cursor, another commonly used type which requires correct disposal, should be easy to retrofit with AutoCloseable as it already has a close() method.

java.util.concurrent.locks.Lock [R,C]

A lock represents a resource that, once it is acquired (locked) must be terminated (unlocked) before the resource is usable again.  Locks are most frequently used in a block structured way (released in the same scope in which it was acquired).  Unlike many other resource types, locks do not follow the RAII pattern: there is no object/value representing the fact that the lock is held.  Because they are interfaces, locks can't be directly retrofitted to AutoCloseable.

org.apache.commons.net.SocketClient [1,2,R]

Subclasses of the apache commons SocketClient class provide various socket-oriented functions, such as transferring files to an FTP server, or sending an email via an SMTP server. They are sometimes allocated and released in the same scope. The usage is similar to Lock, in that the SocketClient must connect(), perform its operations, then disconnect() (see javadoc). They can also be reused after disconnection. As such, they do not fit well with ARM, which seems a pity since they'd be easy to retrofit with AutoCloseable.