简体   繁体   中英

try-with-resources fails to call close()

I am using the handy try-with-resources statement to close connections. This works great in most cases but only in one utterly simple method it does not work properly. Namely, here:

public boolean testConnection(SapConnection connection) {
  SapConnect connect = createConnection(connection);
  try ( SapApi sapApi = connect.connect() ) {
    return ( sapApi != null );
  } catch (JCoException e) {
    throw new UncheckedConnectionException("...", e);
  }
}

The sapApi object is non-null, the method returns true, but the close() method of sapApi is never called. I now resorted to use a finally block which works fine. But this is quite puzzling. The Java byte code also contains a call to close. Has anyone seen this behavior before?

Edit to clarify the situation:

This is the SapApi, it implements AutoCloseable, of course.

class SapApi implements AutoCloseable {

  @Override
  public void close() throws JCoException {
    connection.close(); // this line is not hit when leaving testConnection(..)
  }
..
}

The following is another method in the same class as testConnection(..). Here SapApi.close() is called before returning.

@Override
public List<Characteristic> selectCharacteristics(SapConnect aConnection,   InfoProvider aInfoProvider) {
  try (SapApi sapi = aConnection.connect()) {
    return sapi.getCharacteristics(aInfoProvider);
  } catch ( Exception e ) {
    throw new UncheckedConnectionException(e.getMessage(), e);
  }
}

Edit 2: This is SapConnect.connect():

SapApi connect() {
  try {
    ... // some setup of the connection
    return new SapApi(this); // single return statement
  } catch (Exception e) {
    throw new RuntimeException(e);
  }
}

SapApi has no subclasses. There is just one implementation with the close method as above. In particular, there is no empty close().

In order for close() to be called, SapApi must implement AutoCloseable interface, but since we are talking about connection, it is more appropriate that you SapApi will implement Closable interface which throws IOException.

Read this: http://tutorials.jenkov.com/java-exception-handling/try-with-resources.html

I do not know what you mean by

This works great in most cases

1 That normally the SapApi is closed when used in try-with-resources

or

2 That it normally works for resources other than SapApi

I am answering on the assumption of number 2.

Try-with-resources will only work in Java 7 for resources that implement the AutoCloseable interface. So my first advice would be to for you to check the API for SapConnect and SapApi (whatever they are) to determine if that is the case.

One guess: maybe connect returns a child or proxy class of SapApi. With close overridden to do nothing if no change was made, only otherwise call super.close() .

I'll give it as an answer, as AutoCloseable works even if no method is called.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM