1.5 Garbage Collection

Each object consumes some memory, of which there is a limited amount. Eventually, the memory allocated to these objects must be reclaimed when they aren't used any more. The Java virtual machine reclaims these objects automatically through a process called garbage collection.

An object is ready to be garbage collected when it is no longer "alive." The rules for determining if an object is alive follow.

  • If there's a reference to the object on the stack, then it's alive.

  • If there's a reference to the object in a local variable, on the stack, or in a static field, then it's alive.

  • If a field of an alive object contains a reference to the object, then it's alive.

  • The JVM may internally keep references to certain objects, for example, to support native methods. These objects are alive.

Any object that isn't alive is dead. As an example, suppose that you have two classes, A and B, like this:

 class A {     B b;                   // A field pointing to an object                            // of type B } class B {     A a;                   // A field pointing to an object                            // of type A } 

Suppose you have this code:

 A foo = new A();          // Create an object of class A                           // called foo foo.b = new B();          // Create an object of class B                           // and put a reference to it                           // in the b field of foo 

The code creates two objects, one of class A and one of class B (we'll call these A and B). There is a reference to A in the local variable foo (which is stored in local variable array slot 0) and a reference to B in the b field of A. The a field of B points to null, which is no object at all. Memory now looks like Figure 1.7. In this figure, both A and B are alive. A is alive because it is referenced by the local variable 0. B is alive because it is referenced in a field of A.

Figure 1.7. Two live objects

graphics/01fig07.gif

Suppose we break the link like this:

 foo.b = null; 

This sets the b field to point to no object at all. Now memory looks like Figure 1.8. Now B doesn't meet any of the four conditions for aliveness; there are no arrows pointing to it at all. This means that B is now dead, and it can be garbage collected. A is still alive, so it must not be garbage collected.

Figure 1.8. The object on the right is dead

graphics/01fig08.gif

One thing can be a little confusing about the third rule: only a reference from a live object counts, not a reference from a dead one. Suppose there are objects like Figure 1.9. Even though these objects point to each other, neither is alive because one isn't alive. An object is dead unless it can prove that it's alive. Since the only claim that each has on life is the other one, they're both dead.

Figure 1.9. These objects are both dead

graphics/01fig09.gif

1.5.1 Finalization

In some cases, it is helpful to know when an object is no longer used so that you can do some final cleaning up. For example, if you write a class where each instance represents a connection to a database, a database connection object that is no longer used can inform the database that the connection is no longer necessary.

To handle this, provide a method called finalize in your class. This method is called when the garbage collector notices that the object is dead. The finalize method is defined in the class java.lang.Object to do nothing. You may override this method to do any last-minute chores your object should do before it is garbage collected.

To close the database connection, you might provide this method:

 public void finalize() {     this.close();              // Close the connection } 

When this object becomes dead, the finalize method will be called and it will close the connection.

Note that you can't be sure when the connection will be closed, because the garbage collector may take some time before it notices that the object is dead. In fact, the garbage collector may never notice that the object is dead, or finalization may never occur for other reasons. Therefore, anybody using the connection should explicitly close the connection, not depend on finalize. The finalize method can be used as a backup, but in that case there is still the possibility that the connection will never be closed.

One trick you can play is to "resurrect" your object. The finalize method was called because there was no way to reach the object, but in the body of the finalize method there is a way to reach the object: it's available through this.

You can store the value of this into a field, like this:

 static Vector resurrected_objects = new Vector(); void finalize() {     resurrected_objects.addElement(this); } 

This resurrects the object because now there is a way to get to it: it is stored in resurrected_objects, which maintains a reference to the object. The garbage collector will notice this, and the object is not reclaimed. The body of finalize may resurrect other objects that were presumed dead, or it may eliminate the last link to an object so that it is now dead. The garbage collector has to be very smart to correctly handle all these cases. You can be sure that an object will never be garbage collected until there is absolutely no way to resurrect it.

At some point in the future, the object may become dead again. The object will be garbage collected, but finalize will not run again. If you depend on finalize to clean things up, you must be very careful if you choose to resurrect the object during finalization: you get only one shot at it.

1.5.2 Timing of Garbage Collection

You shouldn't design your system to depend on finalization or garbage collection to run at any particular time or in any particular order. In fact, there is no guarantee that finalization will ever occur. Therefore, you should never write your programs to depend on finalization for correctness.

The garbage collector may run when you get low on memory. It may also run when the system is otherwise idle and the JVM decides to use the free time to tidy itself up. It may also run at the user's explicit command by calling the gc method in the class java.lang.System.

The garbage collector may be run automatically by the system at any time. The system can also undertake garbage collection at the explicit request of a program. Even if you knew when it was going to run, you couldn't be sure that it would collect all dead objects. Some garbage collectors take a quick-and-dirty look at the system to collect obviously dead objects and delay collection of objects that have been around for a long time until it has time to do a thorough examination of the state of memory.



Programming for the Java Virtual Machine
Programming for the Javaв„ў Virtual Machine
ISBN: 0201309726
EAN: 2147483647
Year: 1998
Pages: 158
Authors: Joshua Engel

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net