简体   繁体   中英

Try with resources using a connection pool and single connection

During a code review I found the following code snippet:

try (
   Connection con = new SqlSessionFactoryBuilder()
    .build(configuration)
    .buildFactory()
    .openSession()
    .getConnection()
){
   // do stuff here with 'con' and not close anything   
}

Session, Connection, SqlSessionFactory are iBatis implementations, but the questions is interested in any 'stacked' implementation of the Closable interface.

I am assuming 'try with resources' closes the resource, that is instantiated - con in this case. Normally you'd close session and connection each individually. If using the above code the close() method will just be called on con object, so session is not explicitly called and will rely on the garbage collection?

Will the code be any better using:

try (
   Session session = new SqlSessionFactoryBuilder()
    .build(configuration)
    .buildFactory()
    .openSession(); 
   Connection con = session.getConnection();
){
   // do stuff here with 'con' and not close anything
}

The latter approach seems cleaner in my eyes as it should call close() correctly. Or is my interpretation wrong and just boilerplate code?

Your interpretation is correct, try-with-resources will close only resources explicitly declared in resources block.

However, in most cases the first approach will work as well. That is because usually when some Closeable uses another Closeable , it will try to close it inside of its close() method. This mechanism doesn't have anything to do with the garbage collector tho (which would just remove an object without releasing the resource).

Other than the situation where a Closeable wouldn't close its resources, there could be other sources of resources leak in the first approach as well. Consider a following case:

try(BufferedInputStream bufferedInput = new BufferedInputStream(
                                            new FileInputStream("file.txt"))
)

In this example, FileInputStream will be created first. Just then it will be passed into a contructor of BufferedInputStream . What would happen when an exception occurs during creation of BufferedInputStream ? FileInputStream won't ever be closed. On the other hand, when you declare those as two separate resources like so:

try(FileInputStream input = new FileInputStream("file.txt");
    BufferedInputStream bufferedInput = new BufferedInputStream(input)
)

Java itself will make sure that both of the resources will be closed. The following is stated in JSL - 14.20.3.1. Basic try-with-resources :

In a basic try-with-resources statement that manages multiple resources:

If the initialization of a resource completes abruptly because of a throw of a value V, then:

If the automatic closings of all successfully initialized resources (possibly zero) complete normally, then the try-with-resources statement completes abruptly because of a throw of the value V.

There are probably more cases that might cause resource leak as well.

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