SCJP Study Guide:
Fundamentals


Printer-friendly version Printer-friendly version | Send this 
article to a friend Mail this to a friend


Previous Next vertical dots separating previous/next from contents/index/pdf Contents
XyzWs SCJP Study Guide: Garbage Collection

Garbage Collection

Garbage collection is a technique introduced in Java language that manages the no longer used memory automatically. As a Java program runs, every time a new object is created, a certain amount of memory from the heap is taken by this new object. When the objects are no longer in use or referenced, they are accumulated on the heap. Java runtime runs the garbage collector from time to time to reclaim these no-longer-used storage, and return the storage back to the heap. So that the there is more memory available to the application. The automatic garbage collection by the JVM frees the programmers from recycling the memory.

In Java, only objects that are no longer being referenced by any other objects will be collected. As long as there is at least one variable refers to the object, that object will not become a candidate for garbage collection. The object which are no longer referred by any reference MAY be collected, but as for whether or when this will happen it's not guaranteed. In other words, you can only tell when an object becomes eligible for garbage collection.

How Does Garbage Collector Work?

In Java, all unreferenced objects are indeed automatically freed by the garbage collector. The garbage collector looks for objects that are no longer needed and to remove them when they can no longer be accessed or referenced. The garbage collector starts at the root nodes, classes that persist throughout the life of a Java application, and sweeps though all of the nodes that are referenced. As it traverses the nodes, it keeps track of which objects are actively being referenced. Any classes that are no longer being referenced are then eligible to be garbage collected. The memory resources used by these objects can be returned to the Java virtual machine (JVM) when the objects are deleted.

  • Garbage collector monitors Java created objects to determine when they are unreferenced. Once all references of the object have been set to null, the object becomes eligible for garbage collection.
  • Garbage collector informs being recycled Objects that they should release any non-memory resources.
  • Garbage collector destroys objects and reclaims their memory resources.

Make Objects Eligible For Garbage Collection

An object becomes eligible for garbage collection when it becomes unreachable by any code. Two way can make this happened:

  • Explicitly set the reference variable that refers to the object to null.
  • Reassign the reference variable that points to the object to refer to other object.

For example,

class Program {
  public static void main(String[] args) {
    X x1 = new X("1");
    X x2 = new X("2");
    x1 = null;    // X("1") object is eligible for collection after this
    x2 = new Y(); // X("2") object is eligible for collection after this 
  }
}

Object Lifetime

The lifetime of an object is from the time it is created to the time it is garbage collected. A "garbage" object is one that is no longer needed, is unreachable from the root or goes out of the scope in which it is created.

Declaration Duration
static variable as long as the class is loaded
instance variable for the life of the instance
Array components as long as the array is referenced
Method parameters until method execution ends
Constructor parameters until the constructor execution ends
Exception handling parameters until the catch clause completes execution
Local variables Objects that are created and accessed by local references in a method are eligible for garbage collection when the method terminates, unless references to those objects are exported out of the method. This can occur if a reference is returned or thrown as an exception.

Island of Isolation -- Garbage Collection


An "island of isolation" describes one or more objects have NO references to them from active parts of an application. There is no way for any live thread to access them.

class MyObject {
  private MyObject other;
  public void setOther(MyObject other) {
    this.other = other;
  } 
}
class Program {
  public static void main(String[] args) {
    MyObject obj1 = new MyObject();
    MyObject obj2 = new MyObject();
    obj1.setOther(obj2);
    obj2.setOther(obj1);
    obj1 = null; //Clean up reference variables
    obj2 = null;
    doSomething();
  }
}

The obj1 and obj2 reference to each other through instance varibale other and like a ring. After set obj1 and obj2 to null, the ring becomes an island of isolated objects that are not reachable by any part of the user program. You can see that there is no way to access them again. At this point, the two objects are eligible for garbage collection.

A key point to remember is that an object that is referenced by another object can be eligible for garbage collection if the two objects form an island of isolated objects.

An object is eligible for garbage collection when you no longer have any active references to it. You might still have references to it, but if those references come from objects that have no active references to them, the object is still eligible for garbage collection. When the garbage collectors runs, it can usually find any "island of isolation" rings and remove them.

Finalization -- Cleaning Up Before Garbage Collection

The garbage collector offers an additional feature that you may want to take advantage of: finalization. Finalization allows a resource to gracefully clean up after itself when it is being collected. By using finalization, a resource representing a file or network connection is able to clean itself up properly when the garbage collector decides to free the resource's memory.

The java.lang.Object class defines finalize method. This method is automatically called by the garbage collector when garbage collection determines that there are no more references to the object:

protected void finalize() throws Throwable
			

Java does not guarantee that any particular object will be garbage collected, but guarantees that the finalize method will be run before an object is garbage collected (reclaiming the memory it occupies). There is no guarantee what so ever as to when the finalize method is called.

Class java.lang.Object is the root of the class hierarchy. Every class has java.lang.Object as a superclass. All objects, including arrays, implement the methods of this class. The finalize method of class java.lang.Object performs no special actions; it simply returns normally. A subclass may override the finalize method to dispose of system resources or to perform other cleanup.

Overriding finalize method in a class does not prioritize the object for garbage collection over any other object which do not have finalize method overridden in it's class.

The general contract of finalize is that it is invoked if and when the Java virtual machine has determined that there is no longer any means by which this object can be accessed by any thread that has not yet died, except as a result of an action taken by the finalization of some other object or class which is ready to be finalized. The finalize method may take any action, including making this object available again to other threads; the usual purpose of finalize, however, is to perform cleanup actions before the object is irrevocably discarded. For example, the finalize method for an object that represents an input/output connection might perform explicit I/O transactions to break the connection before the object is permanently discarded.

The Java programming language does not guarantee which thread will invoke the finalize method for any given object. It is guaranteed, however, that the thread that invokes finalize will not be holding any user-visible synchronization locks when finalize is invoked.

If an uncaught exception is thrown by the finalize method, the exception is ignored and finalization of that object terminates.

Unlike constructors, which are chained from the subclass to superclass, finalizers are not implicitly chained, therefore a finalizer in a subclass should explicitly call super class finalizers as its last action. It is a good programming practice to use a try-catch-finally statement and to always call the supperclass finalizer like super.finalize() in your subclass. This is a safety measure to ensure you do not inadvertently miss closing a resource used by the objects calling class

class MyObject {
  ....
  protected void finalize() throws Throwable {
    try {
      close(); //close opened resources for example opened file
    } finally {
      super.finalize();
    }
  }
}

After the finalize method has been invoked for an object, no further action is taken until the Java virtual machine has again determined that there is no longer any means by which this object can be accessed by any thread that has not yet died, including possible actions by other objects or classes which are ready to be finalized, at which point the object may be discarded.

The finalize method is never invoked more than once by a Java virtual machine for any given object in it's entire life cycle.

Any exception thrown by the finalize method causes the finalization of this object to be halted, but is not notified to the application and this object is still considered as finalized.

By default garbage collector will not execute the finalizers of any objects left on heap when the application exists. When an application terminates, some objects are still reachable and will not have their finalize method called.

There is no specific order in which the finalize method will be called. For example, let's say there is an object that contains a pointer to an inner object. The garbage collector has detected that both objects are garbage. Furthermore, say that the inner object's Finalize method gets called first. Now, the outer object's Finalize method is allowed to access the inner object and call methods on it, but the inner object has been finalized and the results may be unpredictable. For this reason, a finalize methods should not access any inner, member objects.

Forcing Garbage Collection

You CAN NOT FORCE garbage collection, but you can suggest or encourage the JVM to perform garbage collection. Java provides following two methods that allow you to request that JVM perform garbage collection. There are no guarantees the JVM will actually run and remove all of unused objects from memory.

Every Java application has a single instance of class Runtime that allows the application to interface with the environment in which the application is running. The current runtime instance can be obtained from the getRuntime method.

An application cannot create its own instance of this class.

public void runFinalization()

The above method defined in Runtime class, runs finalization methods of any objects that have not yet been finalized. Runtime.runFinalization() is no guarantee is made that finalization will actually run immediately after the call. It only suggests the JVM to run the finalize methods on the objects which have not run and in any case cannot force it. Following is from Runtime Class API:

Runs the finalization methods of any objects pending finalization. Calling this method suggests that the Java virtual machine expend effort toward running the finalize methods of objects that have been found to be discarded but whose finalize methods have not yet been run. When control returns from the method call, the virtual machine has made a best effort to complete all outstanding finalizations.

The virtual machine performs the finalization process automatically as needed, in a separate thread, if the runFinalization method is not invoked explicitly.

The method System.runFinalization() is the conventional and convenient means of invoking this method.

public void gc()

The above method is also defined in Runtime class, runs garbage collector and tries to reclaim memory from unused objects. Forcing the garbage collector to execute a finalize method can significantly hurt performance. Following is from Runtime Class API

Runs the garbage collector. Calling this method suggests that the Java virtual machine expend effort toward recycling unused objects in order to make the memory they currently occupy available for quick reuse. When control returns from the method call, the virtual machine has made its best effort to recycle all discarded objects.

The name gc stands for "garbage collector". The virtual machine performs this recycling process automatically as needed, in a separate thread, even if the gc method is not invoked explicitly.

The method System.gc() is the conventional and convenient means of invoking this method.

When garbage collector runs, you may have a short pause in the application's execution. This is the reason why you should only invoke the System.gc() method at the right time, such as before performing a huge task or when the application is idle, waiting for user's input.

Garbage Collector Guarantees

Unlink C and C++ language, Java does not have any explicit programmer controlled methods for the destruction of objects . Memory deallocation is handled by the garbage collector .

  • The garbage collector guarantees that no object will have it's memory reclaimed as long as there is at least one reference to the object in a live thread.
  • The garbage collector will run before an OutOfMemoryError error is thrown.

The programmer has NO way of explicitly controlling the garbage collector.

The garbage collector does NOT make any guarantees as to when or if it will run, other than that it will run before an OutOfMemoryError error is thrown.

The garbage collector does NOT guarantee that it will run and deallocate all unreferenced memory if the System.gc() or Runtime.gc() methods are called.

The garbage collector does NOT guarantee that an object's finalize() method will ever be called even if the System.runFinalization() method is called.

If the garbage collector does run and deallocate the memory of several objects it does NOT guarantee any particular order to the objects as they are destroyed.

The garbage collector does NOT make any guarantees as to program performance while it is running.

Does Garbage Collection A Feature of Every JVM

There is no guarantee that every implementation of Java Virtual Machine(JVM) will have a garbage collection process. It is left to the JVM designers to decide whether to provide garbage collection mechanism or not, as well as what type of algorithm to achieve it.


Previous Next vertical dots separating previous/next from contents/index/pdf Contents

  |   |