...
Since JDK 1.2, the new generational garbage collector has eased out memory allocation related costs to minimal levels, even lesser than C/C++. Deallocation has also become cheaper wherein the cost of garbage collection has become is commensurate with the number of live objects in the younger generation and not the total number of objects allocated since the last run. 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.
That said, with 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 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.
...
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.
Do not use direct buffers for short lived, infrequently used objects
The new IO classes (NIO) in java.nio
allow the creation and use of direct buffers. These buffers tremendously increase throughput for repeated IO activities, however, their creation and reclamation for one-time use is more expensive than heap based non-direct buffers. This is because OS specific native code is used to manage them. An OutOfMemoryError
may result if large objects are allocated frequently using this technique. Direct buffers are also not subject to Java's garbage collector which may cause memory leaks.
Noncompliant Code Example
This noncompliant code example uses a short-lived local object buffer
. The buffer
is allocated in non-heap memory and is not garbage collected.
Code Block | ||
---|---|---|
| ||
ByteBuffer buffer = ByteBuffer.allocateDirect(8192);
// use buffer once
|
Compliant Solution
This compliant solution uses an indirect buffer to allocate the short-lived, infrequently used object.
Code Block | ||
---|---|---|
| ||
ByteBuffer buffer = ByteBuffer.allocate(8192);
// use buffer once
|
Nulling References
Noncompliant Code Example
Reference nulling to "help the garbage collector" is not necessary at all. In fact, it just adds clutter to the code and may introduce more 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, thereby befriending a huge performance hit.
Code Block | ||
---|---|---|
| ||
int[] buffer = new int[100]; doSomething(buffer); buffer = null // no need for explicitly assigning null |
Compliant Solution
Wiki Markup |
---|
The code snippet shown below improves on the discouraged practice by narrowing down the scope of the variable {{buffer}} so that the garbage collector collects the object as soon as it goes out of scope. \[[Bloch 08|AA. Java References#Bloch 08]\] |
...