Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Manual closing inside try-with-resource

Let's say I'm using a poorly documented third party library, one for which no source code is available. One of the library's methods accepts an InputStream to load various data.

Due to the lack of documentation, it's not clear whether or not the method closes the stream once it's done with it, so one possible solution might be to wrap the call in a try-with-resource, just to be on the safe side.

Unfortunately, the Java specification makes (as far as I can tell) no mention of what happens if a resource is manually closed inside a try-with-resource. Does anyone happen to know?

like image 578
BambooleanLogic Avatar asked Jan 21 '14 09:01

BambooleanLogic


3 Answers

It will entirely depend on the implementation of the resource itself. The try-with-resource statement is "just" syntactic sugar (but oh so sweet) for calling close() within a finally block (and preserving exceptions etc).

So long as the stream supports close() being called twice - which I expect most implementations do, and the contract of InputStream requires - it will be absolutely fine.

Note that you'd be in exactly the same situation with the familiar wrapping of one resource within another, e.g.

try (InputStream input = new FileInputStream(...)) {
   try (Reader reader = new InputStreamReader(input, ...)) {
       ...
   }
}

Or with a single try-with-resources statement:

try (InputStream input = new FileInputStream(...);
     Reader reader = new InputStreamReader(input, ...)) {
   ...
}

In both cases there will be two finally blocks, so that first reader.close() is called, then input.close() - but reader.close() will close input anyway.

like image 170
Jon Skeet Avatar answered Nov 12 '22 18:11

Jon Skeet


Method close() of Closeable (and thus, of InputStream) is required to be idempotent:

If the stream is already closed then invoking this method has no effect.

Therefore it's safe to close InputStream more than once.

However, more generic AutoCloseable interface does not require its close() method to idempotent, therefore it may be unsafe to do the same for resources other than Closeable:

Note that unlike the close method of Closeable, this close method is not required to be idempotent. In other words, calling this close method more than once may have some visible side effect, unlike Closeable.close which is required to have no effect if called more than once. However, implementers of this interface are strongly encouraged to make their close methods idempotent.

like image 27
axtavt Avatar answered Nov 12 '22 19:11

axtavt


The specification does say everything it can: if resource.close() throws an exception, that exception will be thrown from the construct.

The specification cannot know whether any particular close method will throw an exception, of course. To find that out you must test your particular resource.

like image 38
Marko Topolnik Avatar answered Nov 12 '22 17:11

Marko Topolnik