...
That said, 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 thus 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 takes a dominant role in critical code. Exceptions to this recommendation can be made when the allocation takes longer in comparison, such as while performing multiple joins across databases or while using objects that represent scarce resources such as thread pools and database connections.
Noncompliant Code Example
Wiki Markup |
---|
The code fragment demonstrated below (adoptedbased fromon \[[Goetz 04|AA. Java References#Goetz 04]\]) shows twoa containerscontainer, {{MutableHolder}} and {{ImmutableHolder}}. In {{MutableHolder}}, the instance field {{value}} can be updated to reference a new value which makes it long-term. On the other hand, when {{value}} is assigned in {{ImmutableHolder}}'s constructor, it is a younger object that is referencing an older one ({{Object o}}). The latter case is a much better position to be in as far as the garbage collector is concerned. |
Code Block | ||
---|---|---|
| ||
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 OBJ37-J. Do not return references to private data
Compliant Solution
The highlighted container is called ImmutableHolder
. When value
is assigned in ImmutableHolder
's constructor, it is a younger object that is referencing an older one (Hashtable<Integer, String> ht
). This is a much better position to be in as far as the garbage collector is concerned. Note that a shall copy was used in this case to preserve references to the older value.
Code Block | ||
---|---|---|
| ||
Code Block | ||
public class MutableHolder { private Hashtable<Integer, ObjectString> value; public// Objectcreate getValue()defensive {copy return value; }of inputs public voidObject setValuegetValue(Object o) { value = oreturn value.clone(); } } public class ImmutableHolder// { create defensive privatecopy final Object value;while returning public ImmutableHolder(Object ovoid setValue(Hashtable<Integer, String> ht) { value = o; } public Object getValue() { return value(Hashtable<Integer, String>)ht.clone(); } } |
Avoid Large Objects
The allocation for large objects is expensive and initializing (zeroing) also takes time. Sometimes large objects of different sizes can cause fragmentation issues or non compacting collect.
...