user3645667
user3645667

Reputation: 73

try-with-resources statement in Java

In this Java program example:

package test;

import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.Statement;

public class Test
{
    private static void example(){
        String url = "jdbc:oracle:thin:@//localhost:7856/xe";
        String user = "user";
        String password = "pass";
        try(Connection con = DriverManager.getConnection(url, user, password);
            Statement stmt = con.createStatement()){
            throw new OutOfMemoryError("Error");
        }catch (SQLException e){
            System.err.println("SQLException");
        }
    }

    public static void main(String [] args){
        try{
            example();
        }catch (OutOfMemoryError e){
            System.err.println("OutOfMemoryError");
        }
        // Rest of code here...
    }
}

When, in the body of the static method example(), the OutOfMemoryError error is thrown, Are Connection "con" and Statement "stmt" automatically closed before terminating the static method example() despite there is not any "catch" that catches these error so in the rest of code in main() is sure that these two objects are closed ?

Thanks.

Upvotes: 3

Views: 551

Answers (1)

yshavit
yshavit

Reputation: 43456

Yes; the try-with-resources construct always closes the resource, even if it's an unchecked throwable (like OutOfMemoryError).

This is specified in JLS 14.20.3, which starts with a pretty generic statement that the resources are "closed automatically," but then goes into various examples of times when a resource is closed. Basically, any non-null resource is always closed, as if the close had been in the finally clause of a try-finally created just for that one resource. This is the case even if there are multiple resources in the try, as in your case ("An exception from the closing of one resource does not prevent the closing of other resources").

Simple class to demonstrate it:

public class Twr {
  private static class TwrCloseable implements AutoCloseable {
    private final String id;

    TwrCloseable(String id) {
      this.id = id;
    }

    @Override
    public void close() {
      System.out.println("closing " + id);
    }
  }

  public static void main(String[] args) {
    try (TwrCloseable closeable1 = new TwrCloseable("first");
         TwrCloseable closeable2 = new TwrCloseable("second")) {
      throw new OutOfMemoryError();
    }
  }
}

Output:

closing second
closing first
Exception in thread "main" java.lang.OutOfMemoryError
    at Twr.main(Twr.java:19)

Note that they're closed in reverse order; "second" is closed before "first." In your example, this means that the Statement is closed before the Connection, which is exactly what you want.

Upvotes: 5

Related Questions