Garbage Collection and Java
The Java runtime relies on garbage collection to identify and reclaim
objects no longer in use automatically. Garbage collection doesn't
alter the behavior of an application written in Java, with the
exception of classes that declare a finalizer method.
Finalizers are executed right before objects found to be garbage are
discarded, giving the developer a chance to explicitly release
non-memory resources the class uses. Tricky finalizers may
resuscitate an object by installing a new reference to it, but
finalizers are executed only once. This guarantees that objects may
be brought back to life only once. Beginning with JDK 1.1, data
belonging to classes is also garbage collected, allowing unused
classes to be automatically discarded (this happens whenever their
class load gets recycled.) Note that system classes are never garbage
collected.
The initial set of roots of a Java runtime are the live thread
objects, the system classes (for instance java.lang.String),
the local variables and operands on the JVM stack, the references from
the JNI, the pending exceptions and the references from the native
stack. Stemming from these roots, all three types of Java entities
feature reachable components that will be examined by the collector.
Objects have instance fields and class that are reclaimable, arrays
have element objects and class that can be garbage collected and
classes feature a set of components that can be recycled: super class,
interfaces, linked classes, string literals, static fields, class
loader, signers, and protection domains.
Up to JDK 1.1.4, Sun uses a partially conservative compacting mark and
sweep algorithm, which makes a conservative assumption when the native
stack is scanned, but allows the Java heap and stack to be scanned in
a non-conservative way. The algorithm compacts the heap,
substantially reducing its fragmentation.
Sun's implementation relies on an implementation detail to keep the
cost of objects' relocation low. The reference to an object (by which
an object is know to exists to other objects and the VM) is implemented
as a non-moving handle pointing to the actual object's data. Once the
actual object's rellocation performed, simply updating its handle
allows the object to be accessed at its new location.
The garbage collection code is executed in a separate thread when the
system runs out of memory or when System.gc is explicitly
invoked. The collector may also run asynchronously when it detects
that the system is idle, but this may require some support from the
native thread package. In any cases, execution of the garbage
collector halts all other application threads and scans the entire
heap.
|