Close resource quietly using try-with-resources

Viewed 13744

Is it possible to ignore the exception thrown when a resource is closed using a try-with-resources statement?

Example:

class MyResource implements AutoCloseable{
  @Override
  public void close() throws Exception {
    throw new Exception("Could not close");
  }  
  public void read() throws Exception{      
  }
}

//this method prints an exception "Could not close"
//I want to ignore it
public static void test(){
  try(MyResource r = new MyResource()){
    r.read();
  } catch (Exception e) {
    System.out.println("Exception: " + e.getMessage());
  }
}

Or should I continue to close in a finally instead?

public static void test2(){
  MyResource r = null;
  try {
     r.read();
  }
  finally{
    if(r!=null){
      try {
        r.close();
      } catch (Exception ignore) {
      }
    }
  }
}
4 Answers

I don't actually recommend this but the only way I can imagine to do this is examining the Exception's stacktrace. Did it come from within a nearby close method?

Based on https://stackoverflow.com/a/32753924/32453 any caught exception will either be an "exception" from the main block, an exception from the close calls, or an exception from the try block with "suppressed" close calls.

So you just have to figure out if it's an exception from the close call itself, which is the line of the catch, apparently:

try (Resource myResource = new Resource()) {

} catch (IOException mightBeFromClose) {
  int currentLine = new Throwable().getStackTrace()[0].getLineNumber();
  int lineOfCatch = currentLine - 1;
  String currentFilename = new Throwable().getStackTrace()[0].getFileName();
  boolean exceptionWasFromClose = Stream.of(mightBeFromClose.getStackTrace()).anyMatch(l -> l.getFileName().equals(currentFilename) && l.getLineNumber() == lineOfCatch);
  if (exceptionWasFromClose) {
    // ...
  }
}

A few more things to consider:

In general it is not clear if you'd want to handle IOException from a close call different than one from inside the try block. What if a close call implies it didn't flush all data out to the file? You may want to handle/treat them all the same.

Another option: close the resource manually near the end of the block (with its own try-catch). Double-close is typically allowed so you could catch the close Exception there.

Another possibility: use normal try-catch-finally pattern instead, here are some ways to make it slightly less ugly: Java try-finally inside try-catch pattern might be an option if you don't have multiple resources.

Related