Unnecessary object retention occurs when an object is no longer useful, but being kept alive by another object that is in use. For example, a programmer may insert objects into a global hash table. These objects cannot be garbage collected, as long as any entry in the hash table is useful and the hash table is kept alive.
An effective way to find the causes of unnecessary object retention is to analyze the heap dump. The heap dump contains information about all the garbage collection roots, all live objects, and how objects refer to each other.
Our profiling interface allows the profiler agent to request the entire heap dump, which can in turn be sent to the profiler front-end for further processing and analysis.
An alternative way to track unnecessary object retention is to provide the direct support in the profiling interface for finding all objects that refer to a given object. The advantage of this incremental approach is that it requires less temporary storage than complete heap dumps. The disadvantage is that unlike heap dumps, the incremental approach cannot present a consistent view of all heap objects that are constantly being modified during program execution.
In practice, we do not find the size of heap dumps to be a problem. Typically the majority of the heap space is occupied by primitive arrays. Because there are no internal pointers in primitive arrays, elements of primitive arrays need not be part of the heap dump.