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. (The exact name of the method is arbitrary, but it usually has those conventional names.) This is usually done automatically, using the try-with-resources feature, added in JDK 7.

If try-with-resources isn't available, then you need to clean up resources explicitly, by calling a clean-up method in a finally clause.

For the case of a resource which is a field, however, there's 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. It's used merely to demonstrate the ideas mentioned above.)

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   
© 2014 Hirondelle Systems | Source Code | Contact | License | RSS
Individual code snippets can be used under this BSD license - Last updated on September 21, 2013.
Over 2,000,000 unique IPs last year - Built with WEB4J.
- In Memoriam : Bill Dirani -