简体   繁体   English

try-with-resources 调用 close() 失败

[英]try-with-resources fails to call close()

I am using the handy try-with-resources statement to close connections.我正在使用方便的 try-with-resources 语句来关闭连接。 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. sapApi 对象为非空,该方法返回 true,但从未调用 sapApi 的 close() 方法。 I now resorted to use a finally block which works fine.我现在求助于使用一个工作正常的 finally 块。 But this is quite puzzling.但这很令人费解。 The Java byte code also contains a call to close. Java 字节码还包含对 close 的调用。 Has anyone seen this behavior before?有没有人见过这种行为?

Edit to clarify the situation:编辑以澄清情况:

This is the SapApi, it implements AutoCloseable, of course.这是 SapApi,当然,它实现了 AutoCloseable。

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(..).下面是与 testConnection(..) 同一个类中的另一个方法。 Here SapApi.close() is called before returning.这里 SapApi.close() 在返回之前被调用。

@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():编辑2:这是 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. SapApi 没有子类。 There is just one implementation with the close method as above.上面的 close 方法只有一种实现。 In particular, there is no empty close().特别是,没有空的 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.为了调用 close(),SapApi 必须实现 AutoCloseable 接口,但既然我们在谈论连接,那么您 SapApi 将实现抛出 IOException 的 Closable 接口更为合适。

Read this: http://tutorials.jenkov.com/java-exception-handling/try-with-resources.html阅读: 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 1 在 try-with-resources 中使用时,通常SapApi是关闭的

or或者

2 That it normally works for resources other than SapApi 2 它通常适用于SapApi以外的资源

I am answering on the assumption of number 2.我是根据数字 2 的假设来回答的。

Try-with-resources will only work in Java 7 for resources that implement the AutoCloseable interface. Try-with-resources 只能在 Java 7 中用于实现AutoCloseable接口的资源。 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.所以我的第一个建议是让您检查SapConnectSapApi (无论它们是什么)的 API,以确定是否是这种情况。

One guess: maybe connect returns a child or proxy class of SapApi.一种猜测:也许connect返回 SapApi 的子类或代理类。 With close overridden to do nothing if no change was made, only otherwise call super.close() .如果没有进行任何更改,则close不执行任何操作,否则只能调用super.close()

I'll give it as an answer, as AutoCloseable works even if no method is called.我会把它作为答案,因为即使没有调用任何方法,AutoCloseable 也能工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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