Instance Pools and finalize() method in Java

Well, I'm writing this assuming you have a basic knowledge about instance pool pattern. If you don't, here is a creative description of instance pool pattern: http://sourcemaking.com/design_patterns/object_pool
Now, let's assume we need to use a factory class called CarFactory to create cars (http://en.wikipedia.org/wiki/Factory_pattern). CarFactory uses an internal instance pool, so it does not have any public constructors to enforce the usage of it's static getInstance method.


package com.blogspot.denizacay.pool;
import java.util.Stack;
public class CarFactory {
   // Create an empty static stack for storing instances
   private static Stack instancePool = new Stack();
   // Might define custom creating logic here instead of empty constructor
   private CarFactory() { };
   public static getInstance() {
   // Use a synchronization block so that concurrent access is safe
   synchronized(instancePool) {
      if(instancePool.isEmpty())
         return new CarFactory();
      else
         return instancePool.pop();
   }
}


As you can see, we implemented "Object pool" pattern using a static field of type Stack. When a user calls getInstance() method, implementation checks for any available instances in the instancePool field; if pool is empty a new instance is returned, otherwise an available instance will be returned so we don't need to create a new object. But this code has one problem: what will happen when we are done with CarFactory instance we used? Generally, we can define a method called free() to return an instance to the pool.


package com.blogspot.denizacay.pool;
import java.util.Stack;
public class CarFactory {











   // Create an empty static stack for storing instances


   private static Stack instancePool = new Stack();
   // Might define custom creating logic here instead of empty constructor
   private CarFactory() { };
   public static getInstance() {
   // Use a synchronization block so that concurrent access won't be a problem
   synchronized(instancePool) {
      if(instancePool.isEmpty())
         return new CarFactory();
      else
         return instancePool.pop();
   }
   public void free() {
      synchronized(instancePool) {
         // Add current instance to the pool
         instancePool.push(this);
      }
   }}




This is the simplest solution, but this approach assumes that the developer will responsibly call free() method to send an unused instance to the pool. Well, it is always a good idea to code "defensively", which means you should write your code so that you don't expect a developer to do something, instead you force her/him. We know that when an object has no reference to itself, it will be garbage collected by the JVM. Java gives us a mechanism to free any allocated resources (like file IO, database connections, etc.) by overriding the finalize() method of the Object class. JVM ensures that before an object is deallocated finalize() method will always be called. So we can actually override finalize() method so that when an CarFactory instance is no longer used, it will be sent to the pool automatically. Here's the final code of the CarFactory class:
package com.blogspot.denizacay.pool;












import java.util.Stack;


public class CarFactory {

   // Create an empty static stack for storing instances
   private static Stack instancePool = new Stack();

   // Might define custom creating logic here instead of empty constructor
   private CarFactory() { };

   public static getInstance() {
   // Use a synchronization block so that concurrent access won't be a problem
   synchronized(instancePool) {
      if(instancePool.isEmpty())
         return new CarFactory();
      else
         return instancePool.pop();
   }
   
   @Override
   protected void finalize() {
      synchronized(instancePool) {
         // Add current instance to the pool
         instancePool.push(this);
      }

   }
}
Let's write a JUnit case to test this:

package com.blogspot.denizacay.pool;
import static org.junit.Assert.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class CarFactoryTest {
private CarlFactory factory;
 @Before
public void setUp() throws Exception {
factory = CarFactory.getInstance();
}


 @After
public void tearDown() throws Exception {
}

 @Test

public final void testFinalize() {
// Create a local instance
CarFactory dummy = CarFactory.getInstance();
// Get pool size
int size1 = dummy.getPoolSize();
// Print initial pool size of CarFactory instance pool
System.out.println("Initial instance pool size of CarFactory class: " + dummy.getPoolSize());
// Assign dummy pointer to null, so we don't have any reachable
  // reference to it
dummy = null;
// Force garbage collection and finalization
System.gc();
System.runFinalization();
// Get new pool size
int size2 = factory.getPoolSize();
System.out.println("Later instance pool size of CarFactory class: " + factory.getPoolSize());
// Check whether pool size is incremented by one
assertTrue(size2 - size1 == 1);
}

Here's the output in my environment:

Initial instance pool size of ModelFactory class: 0

Later instance pool size of ModelFactory class: 1

Test was successful and we can see that finalized instance is returned to the instance pool. If we call getInstance() again in the end of the test method, an instance from the pool will be returned and pool will be empty. I think this is a good approach to object pooling. On the other hand, due to istances will never be successfully finalized until CarFactory class is unloaded by the JVM, we could have a cleaning mechanism but it's out of the scope of this text. If you want to delve more into the OO design patterns, here's a list of valuable books:


Design Patterns: Elements of Reusable Object-Oriented SoftwareObject-Oriented Design and PatternsDesign Patterns Explained: A New Perspective on Object-Oriented Design (2nd Edition)

Comments

Popular Posts