1. Indefinite (soft, weak, phantom, and final) references alter the ordinary lifecycle
of Java objects, allowing them to be reused in ways that may be more GC-friendly
than pools or thread-local variables.
2. Weak references should be used when an application is interested in an object
only if that object is strongly referenced elsewhere in the application.
3. Soft references hold onto objects for (possibly) long periods of time, providing a
simple GC-friendly LRU cache.
4. Indefinite references consume their own memory and hold onto memory of other
objects for long periods of time; they should be used sparingly.
Fast Java programs depend crucially on memory management. Tuning GC is important, but
to obtain maximum performance, memory must be utilized effectively within applications.
Current hardware trends tend to dissuade developers from thinking about memory: if my
laptop has 16 GB of memory, how concerned need I be with an object that has an extra, un-
used 8-byte object reference? And we forget that the normal time/space trade-off of program-
ming can swing to a time/space-and-time trade-off: using too much space in the heap can
make things slower by requiring more GC. In Java, managing the heap is still important.
Much of that management centers around when and how to use special memory techniques:
object pools, thread-local variables, and indefinite references. Judicious use of these tech-
niques can vastly improve the performance of an application, but overuse of them can just as
easily degrade performance. In limited quantities—when the number of objects in question is
small and bounded—the use of these memory techniques can be quite effective.