Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using "try with resources" for resources created without any reference

Consider the following situation :

try (ResultSet resultSet = DriverManager.getConnection("jdbc:...", "user", "pass")
                                      .createStatement().executeQuery(sql)) {    
                    .
                    .
                    .
}

This is a situation where three resources have been created inside try resources: a Connection, a Statement, and a ResultSet.

What will happen to these three resources after the try block ends? Will they all be closed, even if they haven't any reference to them, or will only the resultSet be closed?

Is this safe to declare AutoCloseable resources without any reference to them in try with resource blocks?

like image 324
Mohsen R. Agdam Avatar asked Nov 29 '20 12:11

Mohsen R. Agdam


People also ask

Can we use try with resources without catch?

Yes, It is possible to have a try block without a catch block by using a final block. As we know, a final block will always execute even there is an exception occurred in a try block, except System.

What is the use of try with resources?

The try -with-resources statement is a try statement that declares one or more resources. A resource is an object that must be closed after the program is finished with it. The try -with-resources statement ensures that each resource is closed at the end of the statement. Any object that implements java.

Should I use try with resources?

The try-with-resources statement ensures that each resource is closed at the end of the statement execution. If we don't close the resources, it may constitute a resource leak and also the program could exhaust the resources available to it. You can pass any object as a resource that implements java.

Does try with resources automatically close?

The Java try with resources construct, AKA Java try-with-resources, is an exception handling mechanism that can automatically close resources like a Java InputStream or a JDBC Connection when you are done with them.


2 Answers

Only the ResultSet will be closed. If you want multiple resources to be closed, you need to declare them separately:

try (Connection conn  = DriverManager.getConnection("jdbc:...", "user", "pass");
     Statement stmt = conn.createStatement();
     ResultSet resultSet = stmt.executeQuery(sql)) {    

     // do stuff...
}
like image 175
Mureinik Avatar answered Oct 06 '22 15:10

Mureinik


Is this safe to declare AutoCloseable resources without any reference to them in try with resource blocks?

Yes and no. Those resources that were not assigned to resource variables won't be auto-closed by this code. Therefore:

  • "Yes" those resources will still be "safe" to use via operations on the ResultSet within the try block.
  • "No" those resources will leak, and that is liable to cause problems later on.

Since I interpret "safe" to mean both of those things, my considered answer is "No" it is not safe.

The only resources that will be auto-closed by the try-with-resources are the ones that are assigned to the resource variables. So the correct way to write that would be:

try (Connection connection = DriverManager.getConnection(...);
     Statement statement = connection.createStatement();
     ResultSet resultSet = statement.executeQuery(sql)) {
    // ...   
}

Note that the resource variables are auto-closed in the reverse order that they are declared.


Note that you can often get away with it. For example:

try (BufferedWriter bw = new BufferedWriter(new FileWriter(...)) {
    // ...   
}

is likely to be OK except under extremely unusual circumstances. When bw is auto-closed, its close() method calls close() on the FileWriter. The only case where this might leak a resource is when the BufferedWriter creation / construction fails. I think that is only possible if you are unlucky enough to get an OOME at that point. (And the OOME may well trigger a full garbage collection which will find and close the dropped resource anyway ...)

like image 7
Stephen C Avatar answered Oct 06 '22 13:10

Stephen C