Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: added nce/cs: direct buffers are not subject to GC

...

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
bgColor#FFCCCC

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
bgColor#ccccff

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
bgColor#FFCCCC
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]\]

...