7.4 Garbage CollectionHomepage  « Java6 Certification « 7.4 Garbage Collection

For this lesson we examine the point at which an object becomes eligible for garbage collection, and determine what is and is not guaranteed by the garbage collection system and how the behaviors of System.gc and finalization impact this.

Lets take a look at the points outlined at the Oracle Website for this part of the certification.

  • Section 7: Fundamentals

    • Given a code example, recognize the point at which an obje ct becomes eligible for garbage collection, determine what is and is not guaranteed by the garbage collection system, and recognize the behaviors of the Object.finalize() method.

The Heapgo to top of page Top

The Heap is the area of memory that the JVM allocates to store our objects in. As long as we have a reference to an object then it exists on the Heap. Of course computer memory is finite and so the JVM needs to discard objects on the Heap and call the finalize() method of the Object class, when their scope ends and there are no live references to them, or they become unreachable: this is known as garbage collection (GC). Setting a reference to null will also deprogram it from any object; in fact trying to access a null pointer will cause a NullPointerException runtime error. To clarify this lets go through the creation of some objects and see what happens to them on the Heap and when they become eligible for GC. The following slide show depicts a scenario, just press the button to step through it.

java heap 1 java heap 2 java heap 3 java heap 4 java heap 5

In this slide we create 3 Cat objects and these are placed on the Heap and can be accessed through their reference variables.

In this slide we assign the reference variable tabby to reference variable tigger. This means that the Cat object that was previously referenced by tabby is now unreachable and as such is eligible for GC. tigger and tabby now refer to the same Cat object.

In this slide we assign the reference variable tigger to reference variable moggy and so moggy and tigger now refer to the same Cat object. This also means that the Cat object that was previously referenced by tigger is now only referenced by tabby.

In this slide we assign null to the reference variable moggy and so the pointer in this reference variable refers to nothing. tigger still refers to the Cat object that moggy previously did.

In this final slide we assign null to the reference variable tigger and so the pointer in this reference variable refers to nothing. This means that the Cat object that was previously referenced by tigger is now unreachable and as such is eligible for GC.

Press the button below to cycle through our Heap explanation.


Lets look at some code to illustrate the above scenario:


/*
  Test Class2 for Cat
*/ 
public class TestCat2 {

    public static void main (String[] args) {
        Cat moggy = new Cat();    // Create a Cat instance
        Cat tigger = new Cat();   // Create a Cat instance
        Cat tabby = new Cat();    // Create a Cat instance
        tabby = tigger;    
        tigger = moggy;    
        moggy = null;    
        tigger = null;    
        tabby.talk();             // execute the talk() method
        tigger.talk();            // execute the talk() method (runtime error)
    }
}

run heap

The assignments of the reference variables happen as in the slide show. tabby can talk as his reference variable still points to a Cat object on the heap. When we try and get tigger to talk we get a NullPointerException runtime error as this reference is now null.

The Stack Revisitedgo to top of page Top

In the Beginning Java6 section in the Method Scope lesson we took our first look at the Stack and used primitive local variables for our examples. Here we will look at reference variables and the Stack. The rules for local variables that are reference variables are the same as local variables that are primitives. The following slide show shows this in action, just press the button to step through it.

java stack 1 ref java stack 2 ref java stack 3 ref java stack 4 ref java stack 5 ref

Press the buttons below to cycle through our stack explanation.


So to summarize, a local variable, whether primitive or reference, is alive as long as its method exists on the Stack. You can only use a methods local variables while the method is at the top of the stack (is executing).

The System.gc() Methodgo to top of page Top

The Runtime class enables us to communicate with the JVM and 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 System.gc() method is a member of the Runtime class and by invoking the System.gc() method we force the JVM to do garbage collection. Well this is the theory of what might happen, in reality the JVM makes no guarantees that calling the System.gc() method will do this, or even that the implementation of the System.gc() method for a particular JVM, will in fact do anything. The botton line is that you can't with any certainty call the System.gc() method to free up memory and know if and when it will work.

The finalize() Methodgo to top of page Top


  • The finalize() method is only ever invoked once, for any given object, by the JVM.

The finalize() method of the Object class is called by the garbage collector on an object before that object is discarded. The finalize method in the Object class doesn't execute any specific tasks, but gives us the opportunity to override. We may want to do this to clear up any resources held by an object such as closing a file used by it.

We have no control over when the garbage collector runs as this is in the control of the JVM. The garbage collector runs its collection efficiently and this means it usually runs when there are a lot of objects to discard.

Overriding finalize()go to top of page Top

To see an overridden finalize() method in action we are going to have to instantiate a lot of objects and then make these objects eligible for garbage collection:


/*
  Class to show an overridden finalize() method in action
*/ 
public class Finalize {
    private int i;
    
    Finalize(int i) {
        this.i = i;
    }
    /*
      Instantiate a Finalize object and immediately descope it
    */ 
    public void CreateFinalize(int i) {
        Finalize f = new Finalize(i);
    }
    /*
      Overridden finalize() method
    */ 
    protected void finalize() {
        System.out.println("The finalize() method called on object: " + i);
    }
    /*
      You may need to change the iterator to get this to work!
    */ 
    public static void main (String[] args) {
        Finalize f = new Finalize(0);
        for (int i=1; i < 300000; i++) {
            f.CreateFinalize(i);
        }
    }
}

run finalize()

The above screenshot shows the output of running our Finalize class on my machine. You may have to increase the iterator within the for loop to get it to work.

Related Java6 Tutorials

Objects & Classes - Reference Variables
OO Concepts - The Object Superclass

go to home page Java6 Tutor Homepage go to home page Top