How should a closed resource behave in java?
Asked Answered
V

3

7

I have a java class that holds a Closeable resource internally. This means my class also implements the Closeable interface and closes the internal resource in its own close() method.

What is the expected behavior of my class after it has been closed, and generally any closed object in Java? I see the object in a defunct state, where its internals are closed but clients still have a reference to it. IMO accessing it is a programming error, but bugs happen time to time so the behavior should be reasonable even in this case...

Should I?

  • throw an exception on all method calls like: IllegalState
  • close my eyes like nothing happened and let exceptions through from the close resource?

What is the canonical Java way?

Vancevancleave answered 15/4, 2020 at 13:9 Comment(1)
IllegalStateException is appropriate. Except, most closeable resources allow close() to be called more than once without generating an exception.Fireresistant
N
3

What is the canonical Java way?

First, let's look at the javadoc of the close() method:

Closes this stream and releases any system resources associated with it. If the stream is already closed then invoking this method has no effect.

So the answer to your options is "none of the above" for the close() method. You don't throw an exception, and you don't let exceptions through from the closed resource. If it has been closed, the call must be a NOOP.

Now, let's have a look at some of the Closeable classes:

  • FileInputStream.read()

    Throws IOException if an I/O error occurs.

    That includes "file closed".

    That goes for all the InputStream/OutputStream/Reader/Writer I/O classes.

  • FileSystem.close()

    After a file system is closed then all subsequent access to the file system, either by methods defined by this class or on objects associated with this file system, throw ClosedFileSystemException. If the file system is already closed then invoking this method has no effect.

  • Formatter.close()

    Attempting to invoke any methods except ioException() in this formatter after it has been closed will result in a FormatterClosedException.

  • URLClassLoader.findClass(name)

    Throws ClassNotFoundException if the class could not be found, or if the loader is closed.

Conclusion: All the methods (except close()) throw exceptions, though not IllegalStateException.

You can of course use IllegalStateException if you want.

Nimesh answered 15/4, 2020 at 13:55 Comment(0)
D
5

You should throw an exception when trying to access the internal resource after it has been closed, an IllegalStateException would be fine. One thing worth noting is you can use your Closeable in a try-with-resources to further ensure that once the object falls out of scope it is closed.

Drouin answered 15/4, 2020 at 13:35 Comment(0)
N
3

What is the canonical Java way?

First, let's look at the javadoc of the close() method:

Closes this stream and releases any system resources associated with it. If the stream is already closed then invoking this method has no effect.

So the answer to your options is "none of the above" for the close() method. You don't throw an exception, and you don't let exceptions through from the closed resource. If it has been closed, the call must be a NOOP.

Now, let's have a look at some of the Closeable classes:

  • FileInputStream.read()

    Throws IOException if an I/O error occurs.

    That includes "file closed".

    That goes for all the InputStream/OutputStream/Reader/Writer I/O classes.

  • FileSystem.close()

    After a file system is closed then all subsequent access to the file system, either by methods defined by this class or on objects associated with this file system, throw ClosedFileSystemException. If the file system is already closed then invoking this method has no effect.

  • Formatter.close()

    Attempting to invoke any methods except ioException() in this formatter after it has been closed will result in a FormatterClosedException.

  • URLClassLoader.findClass(name)

    Throws ClassNotFoundException if the class could not be found, or if the loader is closed.

Conclusion: All the methods (except close()) throw exceptions, though not IllegalStateException.

You can of course use IllegalStateException if you want.

Nimesh answered 15/4, 2020 at 13:55 Comment(0)
C
2

Just take a look at one of the probably most used interfaces with a close method, java.sql.Connection:

Here an exception is thrown:

SQLException if a database access error occurs or this method is called on a closed connection

This is basically what makes sense: If calling a close method, the developer willingly closes whatever the object is (Connection, Socket, Stream, ...) and therefore leaves it, as you already stated, in a defunct state. If the developer now tries to call some function on the closed object, he should get an error, thus an exception is the only proper thing to do here.

Collazo answered 15/4, 2020 at 13:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.