Skip to main content

19. Garbage Collection

 

Garbage Collection

  • When the garbage collector runs, its purpose is to find and delete objects that cannot be reached by the running Java program.
  • When it runs, it looks for those discarded objects and deletes them from memory so that the cycle of using memory and releasing it can continue.

When does the Garbage Collector Run?

  • The grabage collector is under the control of the JVM. The JVM decides when to run the garbage collector.
  • Experience indicates that when our Java program makes a request for garbage collection, the JVM will usually grant our request in short order, but there are no guarantees.
  • Left to its own devices, the JVM will typically run the garbage collector when it senses that memory is running low.

How does the Garbage Collector Work?

  • The Java specification doesn't guarantee any particular implementation.
  • An object is eligible for garbage collection when no live thread can access it.
  • If our Java program has a reference variable that refers to an object, and that reference variable is available to a live thread, then that object is considered reachable.
  • Garbage collection cannot ensure that there is enough memory, only that the memory that is available will be managed as efficiently as possible.

Nulling a Reference

The first way to remove a reference to an object is to set the reference variable that refers to the object to null.

class ShellClass {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("DCSharma");
        // The StringBuffer object is not eligible for collection
        sb = null;
        // The StringBuffer object is eligible for collection
    }
}

Reassigning a Reference Variable

We can also dcouple a reference variable from an object by setting the refernece variable to refer to another object.

class ShellClass {
    public static void main(String[] args) {
        StringBuffer sb1 = new StringBuffer("Hello by DCSharma");
        StringBuffer sb2 = new StringBuffer("Bye by DCSharma");
        // StringBuffer "Hello by DCSharma" is not eligible for collection
        sb1 = sb2; // Redirects sb1 to refer to the "Bye by DCSharma" object
        // Now the StringBuffer "Hello by DCSharma" is eligible for collection
    }
}

Once the a has returned, the objects created in the method are eligible for garbage collection. If an object is returned from the method, its reference might be assigned to a reference variable in the method that called it; hence, it will not be eligible for collection.

Isolating a Reference

There is another way in which objects can become eligible for garbage collection, even if they still have valid references! We call this scenario "islands of isolation".

Imagine some instance variables exist and they refer to each other. If all other references to these objects are removed, then even though each object still has a valid reference, there will be no way for any live thread to access either object.

class ShellClass {
    ShellClass shellVariable;

    public static void main(String[] args) {
        ShellClass sc1 = new ShellClass();
        ShellClass sc2 = new ShellClass();
        ShellClass sc3 = new ShellClass();

        sc1.shellVariable = sc2;
        sc2.shellVariable = sc3;
        sc3.shellVariable = sc1;

        sc1 = null;
        sc2 = null;
        sc3 = null;

        // Now objects that were referred by sc1, sc2 and sc3 are eligible for garbage collection
    }
}

Requesting Garbage Collection

  • There are no guarantees the JVM will actually remove all of the unused objects from memory (even if garbage collection is run).
  • The garbage collection routines that Java provides are members of the Runtime class.
  • The Runtime class is a special class that has a single object (a Singleton) for each main program. The Runtime object provides a mechanism for communicating directly with the virtual machine.
  • To get the Runtime instance, we can use the method Runtime.getRuntime(), which returns the Singleton. Once we have the Singleton, we can invoke the garbage collector using the gc() method.
  • class ShellClass {
        public static void main(String[] args) {
            Runtime rt = Runtime.getRuntime();
            rt.gc();
        }
    }
  • Alternatively, we can call the same method on the System class, which has static methods that can do the work of obtaining the Singleton for us.
  • class ShellClass {
        public static void main(String[] args) {
            System.gc();
        }
    }
  • The behaviour when gc() is called may be different for different JVMs, so there is no guarantee that the unused objects will be removed from memory.
  • About the only thing we can guarantee os that if we are running very low on memory, the garbage collector will run before it throws an OutOfMemoryException.

The finalize() Method

  • Java provides us a mechanism to run some code just before our object is deleted by the garbage collector. This code iis located in a method named finalize() that all classes inherit from class Object.
  • Any code that we put into our class's overridden finalize() method is not guaranteed to run, so don't put any essential code into the finalize() method.
  • For any given object, finalize() will be called only once (at most) by the garbage collector.
  • We can uneligibilize an object for garbage collection from within finalize().
Prev Next

Comments