BambooleanLogic
BambooleanLogic

Reputation: 8171

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?

Upvotes: 6

Views: 3399

Answers (4)

Jon Skeet
Jon Skeet

Reputation: 1503429

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.

Upvotes: 11

axtavt
axtavt

Reputation: 242786

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.

Upvotes: 8

Alexander_Winter
Alexander_Winter

Reputation: 314

You can try to close it in the finally-statement.

InputStream stream = null;
try {
  stream = new InputStream();
  yourMethod(stream);
} catch (...) {

} finally {
  try {
    stream.close()
  } catch (IOException ioe) {
    // can throw IOException while closing closed stream
  }
}

Upvotes: 0

Marko Topolnik
Marko Topolnik

Reputation: 200296

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.

Upvotes: 2

Related Questions