Recovering resources

Expensive resources should be reclaimed as soon as possible, by an explict call to a clean up method defined for this purpose. If this is not done, then system performance can degrade. In the worst cases, the system can even fail entirely.

Resources include :

Resources which are created locally within a method must be cleaned up within the same method, by calling a method appropriate to the resource itself, such as close or dispose. This is usually done in a finally clause. If JDK 7 is available, then its try-with-resources feature should be used instead. A try-with-resources automatically closes items, and doesn't require a finally clause.

For the case of a resource which is a field, however, there is more work to do :

This example shows a class which retains a database connection during its lifetime. (This example is artificial. Actually writing such a class would not seem necessary in practice, since connection pools already perform such clean up in the background.)

import java.sql.*;
import java.text.*;
import java.util.*;

/**
* This class has an enforced life cycle: after destroy is
* called, no useful method can be called on this object
* without throwing an IllegalStateException.
*/
public final class DbConnection {

  public DbConnection () {
    //build a connection and assign it to a field
    //elided.. fConnection = ConnectionPool.getInstance().getConnection();
  }

  /**
  * Ensure the resources of this object are cleaned up in an orderly manner.
  *
  * The user of this class must call destroy when finished with
  * the object. Calling destroy a second time is permitted, but is
  * a no-operation.
  */
  public void destroy() throws SQLException {
    if (fIsDestroyed) {
       return;
    }
    else{
      if (fConnection != null) fConnection.close();
      fConnection = null;
      //flag that destory has been called, and that
      //no further calls on this object are valid
      fIsDestroyed = true;
    }
  }

  /**
  * Fetches something from the db.
  *
  * This is an example of a non-private method which must ensure that
  * <code>destroy</code> has not yet been called
  * before proceeding with execution.
  */
  synchronized public Object fetchBlah (String aId) throws SQLException {
    validatePlaceInLifeCycle();
    //..elided
    return null;
  }

  /**
  * If the user fails to call <code>destroy</code>, then implementing
  * finalize will act as a safety net, but this is not foolproof.
  */
  protected void finalize() throws Throwable{
    try{
      destroy();
    }
    finally{
      super.finalize();
    }
  }

  /**
  * Allow the user to determine if <code>destroy</code> has been called.
  */
  public boolean isDestoyed() {
    return fIsDestroyed;
  }

  // PRIVATE //

  /**
  * Connection which is constructed and managed by this object.
  * The user of this class must call destroy in order to release this
  * Connection resource.
  */
  private Connection fConnection;

  /**
  * This object has a specific "life cycle", such that methods must be called
  * in the order: others + destroy. fIsDestroyed keeps track of the lifecycle,
  * and non-private methods must check this value at the start of execution.
  * If destroy is called more than once, a no-operation occurs.
  */
  private boolean fIsDestroyed;

  /**
  * Once <code>destroy</code> has been called, the services of this class
  * are no longer available.
  *
  * @throws IllegalStateException if <code>destroy</code> has
  * already been called.
  */
  private void validatePlaceInLifeCycle(){
    if ( fIsDestroyed ) {
      String message = "Method cannot be called after destroy has been called.";
      throw new IllegalStateException(message);
    }
  }
} 



See Also :
Always close streams
Never rely on finalize
Finally and catch
Get database connection
Always shut down an ExecutorService
Would you use this technique?
Yes   No   Undecided   
© 2013 Hirondelle Systems | Source Code | Contact | License | RSS
Individual code snippets can be used under this BSD license - Last updated on August 30, 2012.
Over 2,400,000 unique IPs last year - Built with WEB4J.
- In Memoriam : Bill Dirani -