Summary
A key feature of Java is its
garbage-collected heap, which takes care of freeing dynamically
allocated memory that is no longer referenced. Because the heap
is garbage-collected, Java programmers don't have to explicitly
free allocated memory. Here's a hands-on introduction to Java's
garbage-collected heap.

Welcome
to another installment of "Under The
Hood." This column gives Java developers a glimpse of what is going
on underneath their running Java programs. This month's article takes a
look at the garbage-collected heap of the Java virtual machine (JVM).

The JVM's heap stores all objects created by an executing Java program.
Objects are created by Java's "new" operator, and memory for
new objects is allocated on the heap at run time. Garbage collection is
the process of automatically freeing objects that are no longer referenced
by the program. This frees the programmer from having to keep track of
when to free allocated memory, thereby preventing many potential bugs and
headaches.

The name "garbage collection" implies that objects that are
no longer needed by the program are "garbage" and can be thrown
away. A more accurate and up-to-date metaphor might be "memory recycling."
When an object is no longer referenced by the program, the heap space it
occupies must be recycled so that the space is available for subsequent
new objects. The garbage collector must somehow determine which objects
are no longer referenced by the program and make available the heap space
occupied by such unreferenced objects. In the process of freeing unreferenced
objects, the garbage collector must run any finalizers of objects being
freed.

In addition to freeing unreferenced objects, a garbage collector may
also combat heap fragmentation. Heap fragmentation occurs through the course
of normal program execution. New objects are allocated, and unreferenced
objects are freed such that free blocks of heap memory are left in between
blocks occupied by live objects. Requests to allocate new objects may have
to be filled by extending the size of the heap even though there is enough
total unused space in the existing heap. This will happen if there is not
enough contiguous free heap space available into which the new object will
fit. On a virtual memory system, the extra paging required to service an
ever growing heap can degrade the performance of the executing program.

This article does not describe an official Java garbage-collected heap,
because none exists. The JVM specification says only that the heap
of the Java virtual machine must be garbage collected. The specification
does not define how the garbage collector must work. The designer of
each JVM must decide how to implement the garbage-collected heap. This
article describes various garbage collection techniques that have been
developed and demonstrates a particular garbage collection technique in
an applet.

Why garbage collection?
Garbage collection relieves programmers from the burden of
freeing allocated memory. Knowing when to explicitly free allocated
memory can be very tricky. Giving this job to the JVM has several
advantages. First, it can make programmers more productive. When
programming in non-garbage-collected languages the programmer can spend
many late hours (or days or weeks) chasing down an elusive memory
problem. When programming in Java the programmer can use that time more
advantageously by getting ahead of schedule or simply going home to
have a life.

A second advantage of garbage collection is that it helps ensure program
integrity. Garbage collection is an important part of Java's security strategy.
Java programmers are unable to accidentally (or purposely) crash the JVM
by incorrectly freeing memory.

A potential disadvantage of a garbage-collected heap is that it adds
an overhead that can affect program performance. The JVM has to keep
track of which objects are being referenced by the executing program,
and finalize and free unreferenced objects on the fly. This activity
will likely require more CPU time than would have been required if the
program explicitly freed unnecessary memory. In addition, programmers
in a garbage-collected environment have less control over the
scheduling of CPU time devoted to freeing objects that are no longer
needed.

Fortunately, very good garbage collection algorithms have been
developed, and adequate performance can be achieved for all but the
most demanding of applications. Because Java's garbage collector runs
in its own thread, it will, in most cases, run transparently alongside
the execution of the program. Plus, if a programmer really wants to
explicitly request a garbage collection at some point,
System.gc() or Runtime.gc() can be invoked,
which will fire off a garbage collection at that time.

The Java programmer must keep in mind that it is the garbage collector
that runs finalizers on objects. Because it is not generally possible to
predict exactly when unreferenced objects will be garbage collected, it
is not possible to predict when object finalizers will be run. Java
programmers, therefore, should avoid writing code for which program correctness
depends upon the timely finalization of objects. For example, if a finalizer
of an unreferenced object releases a resource that is needed again later
by the program, the resource will not be made available until after the
garbage collector has run the object finalizer. If the program needs the
resource before the garbage collector has gotten around to finalizing the
unreferenced object, the program is out of luck.