0

Here is some java code.

public class SomeClass {
private Connection connection;

public SomeClass(Connection c) {
    connection = c;
}
public void someWork(){
    Connection c;
    try {
        // do something
    } catch (Exception e) {
        // some exception code
    } finally {
        if (conn != null){
            try {c.close();} catch (Exception e) {}
        }
    }
}

}

but I don't like code

if (conn != null){
        try {c.close();} catch (Exception e) {}
    }

so I think code

...catch (Exception e) {
        // some exception code
    } finally {
        c = null;
    }

but i see 'Stream object not Garbage Collected.'

I won't use try-catch statement in finally block. Please give me another way.

  • 2
    Why won't you? Seriously, I can't see a reason for arbitrarily forbidding a language construct nested inside another. – michaelb958--GoFundMonica Jun 20 '13 at 09:39
  • More importantly, why would you ignore the exception? Every time I see a try catch block that just swallows an exception I feel like crying. That's just making somebody's life hard when debugging later. – Paddy Jun 20 '13 at 09:53

7 Answers7

6

Just create a static utility method:

private static void closeQuietly(final Connection conn)
{
    if (conn == null)
        return;
    try {
        conn.close();
    } catch (WhateverException ignored) {
    }
}

Then

conn = whatever(); // create it there, not in the try block
try {
    // work
} catch (WhateverException e) {
    // whatever
} finally {
    closeQuietly(conn);
}

But eventually, you will use a try/catch in the finally block anyway.

Note that catching Exception is a bad idea. Catch exceptions which are specifically raised by conn.close() instead. Catching Exception means you also catch all RuntimeExceptions; and that is a Bad Thing(tm).

If you use Guava, you can also use Closeables.closeQuietly(), which does pretty much the same thing as the code above. You may also have a look at Closer, which is very interesting.

Finally (pun intended): if you use Java 7, use a try-with-resources statement instead (see AutoCloseable):

try (
    conn = whatever();
) {
    // ...
}
fge
  • 119,121
  • 33
  • 254
  • 329
  • thank you for information. i should write about my environment. i use jdk 6. but i really don't find any reasons why catching exception for every case. i usually use `Exception e` and `e.printStackTrace()` then it works like this `java.sql.SQLException: ORA-00936: missing expression at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:138)` really you think its a Bad way? i think i catch error what is and where is it. – user2503993 Jun 21 '13 at 02:12
  • What I say is that if you catch `Exception`, you also catch exceptions which have nothing to do with your workflow – fge Jun 21 '13 at 07:37
1

Another work around for this would be to remove the catch all together inside the method:

public void someWork() throws SQLException{
    Connection c;
    try {
        // do something
    } finally {
        if (conn != null){
            c.close();
        }
    }
}

Then you do your error checking outside the method in the main method where you invoked someWork method or you wrap it in another method where you call the someWork():

 public void callSomeWork(){
    try{
     someWork();
    }catch(SQLException ex){
    //handle SQL error here
    }
 }

This way error thrown in try or finally will declared in one SQLException.

mel3kings
  • 8,857
  • 3
  • 60
  • 68
1

You might not like that code, but in this situation it is necessary. (Though you can wrap the code in a method like @fge's closeQuietly method.)

But there is a more fundamental problem. Changing someWork to close the connection in a finally block is not sufficient to prevent a leak ... in this situation!!

Why?

Consider this:

SomeClass sc = new SomeClass(createConnection());
// do some stuff
sc.someWork();

Q1: What happens if an exception is thrown in the "do some stuff" code?

Q2: What happens if an exception is thrown while creating / constructing the SomeClass? (Note: this is possible even with the simplest of constructors. For example, an OOME could be thrown by the new operation ...)

Answer: the Connection object is leaked ... in both bases!


The fix is to allocate the resource (e.g. the Connection object) within, or immediately before the try / catch / finally; e.g.

Connection c = createConnection();
try {
    // do something
} catch (SomeException e) {
    // some exception code
} finally {
    if (c != null){
        try {c.close();} catch (SomeException e) {}
    }
}

In Java 7 you can also write it like this:

try (Connection c = createConnection()) {
    // do something
} catch (SomeException e) {
    // some exception code
}

provided that Connection implements the AutoCloseable interface. The Java 7 version is "syntactic sugar" for a more complicated implementation that takes care of checking for null, calling close() and dealing with any resulting exceptions intelligently. (The JLS gives the details of what "try with resource" actually does.)


For the record:

  • The issue is not garbage collection / collecting. The issue is that the Connection object needs to be closed.

  • Assigning null won't cause an object to be closed. It won't even cause it to be garbage collected. At best, it can make the object eligible for garbage collection ... in some future GC run.

  • Catching Exception is a really bad idea. Read this: Need authoritative source for why you shouldn't throw or catch java.lang.Exception

Community
  • 1
  • 1
Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • @user2503993 - That is unfortunate. But if you are going to use an out-of-date version of the language, you have to put up with its limitations. Learn to "like it". – Stephen C Jun 21 '13 at 04:17
  • @user2503993 - Also note (AND TELL YOUR BOSS / CLIENTS) that Java 6 has been EOLd. No more security updates ... unless he / they take out an Oracle Java support contract. http://java.com/en/download/faq/java_6.xml – Stephen C Jun 21 '13 at 05:13
0

You may be leaving a zombie connection if not closed and set to NULL.

Juned Ahsan
  • 67,789
  • 12
  • 98
  • 136
0

let someone else do the try-catch-stuff and use Apache Commons IOUtils

One of the closeQuietly()-methods (e.g. this one) should be just what you need:

Equivalent to InputStream.close(), except any exceptions will be ignored. This is typically used in finally blocks.

Marco Forberg
  • 2,634
  • 5
  • 22
  • 33
0

Since Java 7 it's suppose to be this

try (Connection conn = DriverManager.getConnection(props)) {
    ...
}

before Java 7

Connection conn = DriverManager.getConnection();
try {
  ...
} finally {
    conn.close();
}
Evgeniy Dorofeev
  • 133,369
  • 30
  • 199
  • 275
0

If you nullify and not closed,Make sure all methods always get a new open connection.

The only thing you need to know is that any time you get a connection you must close it (hence the finally block) else you may leave that connection open in your application and eventually run out of available connections.

Suresh Atta
  • 120,458
  • 37
  • 198
  • 307