Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: general edit for readability

...

Use Short-lived Immutable Objects

Wiki Markup
Since JDK 1.2, the new generational garbage collector has reduced memory allocation related costs to minimal levels, even lesser than C/C++. Deallocation has also become cheaper
wherein
 such that the cost of garbage collection is commensurate with the number of _live_ objects in the _younger generation_ and not the _total_ number of objects allocated since the last run. Memory is managed in generations to optimize the collection. The younger generation consists of short-lived objects. A minor collection on the younger generation is performed when it fills up with dead objects. \[[Oracle 10a|AA. Java References#Oracle 10a]\]  

Wiki Markup
Note that objects in the _younger generation_ that persist for longer durations are _tenured_ and are moved to the _tenured generation_. Very few _younger generation_ objects continue to live through to the next garbage collection cycle; the rest become ready to be collected in the impending collection cycle. \[[Oracle 10a|AA. Java References#Oracle 10a]\]   

With generational GCs it is advantageous to use short-lived immutable objects instead of long-lived mutable objects. Object pools are examples of the latter and should as a result be avoided to increase the garbage collector's efficiency. Moreover, object pools can create synchronization problems, deallocations have to be managed explicitly leading to dangers of dangling pointers, and the size of the pool also plays a dominant role in mission critical code. Exceptions to this recommendation can be made when the allocation takes longer in comparison, such as while when performing multiple joins across databases or while when using objects that represent scarce resources such as thread pools and database connections.

...

Code Block
bgColor#FFCCCC
public class MutableHolder {
  private Hashtable<Integer, String> value; // not final

  public Object getValue() { 
    return value; 
  }

  public void setValue(Hashtable<Integer, String> ht) { 
    value = (Hashtable<Integer, String>)ht;
  }
}

This example also violates OBJ11FIO00-J. Defensively copy private mutable class members before returning their referencesmutable inputs and mutable internal components.

Compliant Solution

This compliant solution highlights a custom container called ImmutableHolder. To aid garbage collection, it is recommended that short-lived ImmutableHolder objects be created by passing Hashtable instances to the constructor. When value is assigned in ImmutableHolder's constructor during object creation, it is a younger member field (of type ImmutableHolder.Hashtable<Integer, String>) that is referencing an older object (of type Hashtable<Integer, String>). This is a much better position to be in as far as the garbage collector is concerned. Note that a shallow copy is used in this case to preserve references to the older value.

Code Block
bgColor#ccccff
public class ImmutableHolder {
  private final Hashtable<Integer, String> value;

  // create defensive copy of inputs 
  public ImmutableHolder(Hashtable<Integer, String> ht) { 
    value = (Hashtable<Integer, String>)ht.clone(); 
  }

  // create defensive copy while returning  
  public Object getValue() { 
    return value.clone(); 
  }

}

When value is assigned in ImmutableHolder's constructor during object creation, it is a younger member field (of type ImmutableHolder.Hashtable<Integer, String>) that is referencing an older object in the client code (of the same type Hashtable<Integer, String>). This is a much better position to be in as far as the garbage collector is concerned. Note that a shallow copy is used in this case to preserve references to the older value.

Avoid Large Objects

The allocation for large objects is expensive and initializing (zeroing) also takes timethe initialization cost is proportional to their size. Sometimes large objects of different sizes can cause fragmentation issues or non compacting collect.

...

Code Block
bgColor#ccccff
ByteBuffer buffer = ByteBuffer.allocate(8192);
// use buffer once
Nulling References

...

Reference nulling to "help the garbage collector" is unnecessary. In fact, it just adds clutter to the code and sometimes introduces subtle bugs. Assigning null to local variables is also not very useful as the Java Just-In-Time compiler (JIT) can equivalently do a liveness analysis. A related bad practice is to use a finalizer to null out references. This practice can cause a huge performance hit.

Noncompliant Code Example

This noncompliant code example assigns null to the buffer array.

Code Block
bgColor#FFCCCC
int[] buffer = new int[100];
doSomething(buffer);
buffer = null  // No need to explicitly assign null

...