4th International Conference on Principles and Practices ... - MADOC
4th International Conference on Principles and Practices ... - MADOC
4th International Conference on Principles and Practices ... - MADOC
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