15.01.2015 Views

4th International Conference on Principles and Practices ... - MADOC

4th International Conference on Principles and Practices ... - MADOC

4th International Conference on Principles and Practices ... - MADOC

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

[4]. The fact that the Java framework has no way of explicitly<br />

releasing memory 1 , but has numerous ways of closing other<br />

resources explicitly 2 , supports this view.<br />

The fact that Java’s finalizers are not guaranteed to be run in a<br />

timely fashi<strong>on</strong> would seem to limit their usefulness. Even more<br />

limiting, however, is that finalizers are in fact not guaranteed to<br />

be run at all [9][3]. An object’s finalizer is <strong>on</strong>ly guaranteed to be<br />

run if the object is garbage collected, <strong>and</strong> garbage collecti<strong>on</strong> is not<br />

guaranteed to happen [4]. It is entirely possible for a program to<br />

exit without any of its objects being garbage collected or<br />

finalized. Java does provide a way to force objects to be finalized<br />

<strong>on</strong> exit 3 , but the functi<strong>on</strong>ality has been deprecated since Java 1.2,<br />

as it has been deemed unsafe. Without any accepted way to<br />

guarantee finalizati<strong>on</strong>, exactly how finalizati<strong>on</strong> is at all useful<br />

becomes a valid questi<strong>on</strong>.<br />

Because finalizati<strong>on</strong>’s usefulness is limited, Java code must<br />

manually release all scarce resources. Java does not make this job<br />

simple. While releasing a resource typically boils down to a<br />

single method call, the exact call is not st<strong>and</strong>ardized across the<br />

Java libraries. Most resources provide a close() method,<br />

including Socket, InputStream, C<strong>on</strong>necti<strong>on</strong>, etc. However, a few<br />

resources stray from that pattern, such as the AWT Window class,<br />

which provides the dispose() method. Even those classes which<br />

do provide a close() method are not truly c<strong>on</strong>sistent, because Java<br />

does not have a single, unified interface for closing resources.<br />

The closest the library comes to a unified interface is Closeable.<br />

The Closeable interface is implemented by all resources in the<br />

java.io package. However, outside the java.io package, few<br />

resources implement the Closeable interface, <strong>and</strong> so many<br />

resources cannot be treated as instances of Closeable. The net<br />

effect of what are in fact fairly minor inc<strong>on</strong>sistencies is that there<br />

is no straightforward way to release all resources in an identical<br />

manner, which complicates any attempt at automated resource<br />

deallocati<strong>on</strong>.<br />

1.4 Releasing Resources<br />

Dependencies are inherent in the very nature of resources. A<br />

JDBC PreparedStatement object has no logical meaning in the<br />

absence of an associated C<strong>on</strong>necti<strong>on</strong> object. Similarly, the input<br />

<strong>and</strong> output streams associated with a network socket have no<br />

further meaning <strong>on</strong>ce the socket they are built up<strong>on</strong> closes. Up<strong>on</strong><br />

inspecti<strong>on</strong>, it becomes clear that there are many such<br />

dependencies, <strong>and</strong> they are applicable to all sorts of resources.<br />

While at first it might seem logical that when a resource closes,<br />

any resources which depend <strong>on</strong> that resource will also close<br />

automatically, this cannot be safely assumed in the general case.<br />

Any behavior which is not defined is undefined, axiomatically.<br />

Undefined behavior cannot be trusted to act c<strong>on</strong>sistently, <strong>and</strong> the<br />

Java documentati<strong>on</strong> is usually quiet when it comes to automatic<br />

resource closure. One might assume that when a database<br />

c<strong>on</strong>necti<strong>on</strong> closes, any statements tied to that c<strong>on</strong>necti<strong>on</strong> will also<br />

1 Java does provide a way to request that the garbage collector be<br />

immediately run, but this practice is discouraged, <strong>and</strong> is not<br />

guaranteed to free any memory, <strong>on</strong>ly to make an attempt.<br />

2 Various calls are used to close resources, including<br />

Closeable.close(), Window.dispose(), C<strong>on</strong>necti<strong>on</strong>.close(), etc.<br />

3 Runtime.runFinalizersOnExit()<br />

close. However, the Java 1.5 API documentati<strong>on</strong> makes no such<br />

claim [16]. 4 Accordingly, it falls <strong>on</strong> the programmer to explicitly<br />

close any open statements al<strong>on</strong>g with the database c<strong>on</strong>necti<strong>on</strong>.<br />

Likewise, the API documentati<strong>on</strong> does not state that closing a<br />

socket automatically closes its associated streams, which leaves<br />

this task to the programmer. In fact, the recommended method of<br />

closing multiple dependent resources is to close them manually,<br />

<strong>on</strong>e at a time [4].<br />

Whenever the documentati<strong>on</strong> is silent about whether a resource<br />

closing will cause any dependent resources to close, it is best to<br />

assume nothing, <strong>and</strong> treat the dependent resources as potentially<br />

unusable. In such a case, the <strong>on</strong>ly logical thing to do with the<br />

dependent resources is to close them as well. When a socket is<br />

closed, the programmer should immediately close the associated<br />

input <strong>and</strong> output streams. In fact, this should be d<strong>on</strong>e before the<br />

socket is closed [4]. It is interesting to note that in the Java 1.5<br />

implementati<strong>on</strong> provided by Sun, closing a stream associated with<br />

a socket actually will close the socket [10], but this behavior is<br />

unreliable. It is not guaranteed between Java versi<strong>on</strong>s – in fact it<br />

is a recent change – <strong>and</strong> it is undocumented, which means other<br />

Java implementati<strong>on</strong>s may not exhibit the same behavior.<br />

1.5 Related Work<br />

Finalizers were introduced into Java as a way to guarantee<br />

cleanup [8], but it has been shown that finalizers fail in their task.<br />

Stack-bound objects with destructors have been given thorough<br />

attenti<strong>on</strong> in C++ [15], but such approaches are not applicable to<br />

Java, due to its lack of stack-bound objects.<br />

C# <strong>and</strong> .NET introduced the IDisposable interface, which is used<br />

throughout the .NET framework. This provides the unifying<br />

interface missing from Java. C# also introduced the using<br />

keyword (coupled with the IDisposable interface) to simplify<br />

resource management [7]. The using c<strong>on</strong>struct eliminates the<br />

need for try-finally blocks when releasing resources, <strong>and</strong> even<br />

automates the resource release. One drawback to applying this<br />

technique to Java is that it requires language-level support, <strong>and</strong> so<br />

requires a language extensi<strong>on</strong>. The sec<strong>on</strong>d issue is that it requires<br />

IDisposable, or an equivalent unified interface, to work.<br />

Czajkowski provided a thorough treatment of the area of resource<br />

allocati<strong>on</strong> <strong>and</strong> usage m<strong>on</strong>itoring [6]. However, the methods<br />

presented are not applicable to releasing resources. The methods<br />

do not eliminate the need for nested try-finally blocks when<br />

releasing resources.<br />

Weimer delved deeply into the issue of releasing resources [17]<br />

using compensati<strong>on</strong>s, arbitrary pieces of code that are executed to<br />

restore invariants. The framework presented by Weimer stores<br />

these compensati<strong>on</strong>s <strong>on</strong> a stack, <strong>and</strong> the entire stack is typically<br />

executed at <strong>on</strong>ce. However, compensati<strong>on</strong>s require changes to the<br />

Java language itself, to add closures <strong>and</strong> an extended syntax.<br />

Compensati<strong>on</strong> stacks are also less flexible than the resource tree<br />

model we will introduce in the next secti<strong>on</strong>.<br />

4 The JDBC spec states that closing a C<strong>on</strong>necti<strong>on</strong> object closes<br />

the associated Statement objects, although this is not reflected in<br />

the more general Java 1.5 API documentati<strong>on</strong>. The JDBC spec<br />

states, however, that Statement <strong>and</strong> ResultSet objects should be<br />

explicitly closed as so<strong>on</strong> as possible, implying that the<br />

automatic closure is a fallback mechanism <strong>on</strong>ly.<br />

115

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!