Previous | Table of Contents | Next |
14.3.5.1. Garbage Collection
The technique Java uses to get rid of objects once they are no longer needed is called garbage collection. It is a technique that has been around for years in languages such as Lisp. The Java interpreter knows what objects it has allocated. It can also figure out which variables refer to which objects, and which objects refer to which other objects. Thus, it can figure out when an allocated object is no longer referred to by any other object or variable. When it finds such an object, it knows that it can destroy it safely, and does so. The garbage collector can also detect and destroy cycles of objects that refer to each other, but are not referred to by any other objects.
The Java garbage collector runs as a low-priority thread, and does most of its work when nothing else is going on. Generally, it runs during idle time while waiting for user input in the form of keystrokes or mouse events. The only time the garbage collector must run while something high-priority is going on (i.e., the only time it will actually slow down the system) is when the interpreter has run out of memory. This doesnt happen often because there is that low-priority thread cleaning things up in the background.
This scheme may sound extremely slow and wasteful of memory. Actually though, good garbage collectors can be surprisingly efficient. No, garbage collection will never be as efficient as explicit, well-written memory allocation and deallocation. But it does make programming a lot easier and less prone to bugs. And for most real-world programs, rapid development, lack of bugs, and easy maintenance are more important features than raw speed or memory efficiency.
14.3.5.2. Putting the Trash Out
What garbage collection means for your programs is that when you are done with an object, you can just forget about itthe garbage collector finds it and takes care of it. Example 14.13 shows an example.
EXAMPLE 14.13. Leaving an object out for garbage collection.
String processString(String s) { // Create a StringBuffer object to process the string in. StringBuffer b = new StringBuffer(s); // Process it somehow... // Return it as a String. Just forget about the StringBuffer // object: it will be automatically garbage collected. return b.toString(); }
If youre a C or C++ programmer, conditioned to allocating and deallocating your own dynamic memory, you may at first feel a nagging sense of misgiving when you write procedures that allocate and then forget objects. Youll get used to it, though, and even learn to love it!
There is an instance where you may want to take some action to help the garbage collection process along by forgetting quickly. Example 14.14 explains.
EXAMPLE 14.14. Forced forgetting of an object.
public static void main(String argv[]) { int big_array[] = new int[100000]; // Do some computations with big_array and get a result. int result = compute(big_array); // We no longer need big_array. // It will get garbage collected when // there are no more references. // Since big_array is a local variable, // it refers to the array until this method returns. // But this method doesnt return. So weve got to // get rid of the reference // ourselves, just to help out the garbage collector. big_array = null; // Loop forever, handling the users input. for(;;) handle_input(); }
14.3.5.3. Object Finalization
Just as a constructor method performs initialization for an object, a Java finalizer method performs finalization for an object.
Garbage collection automatically frees up the memory resources used by objects. But objects may hold other kinds of resources, such as file descriptors or sockets, as well. The garbage collector cant free these resources up for you, so you should write a finalizer method that takes care of things like closing open files, terminating network connections, and so on.
Example 14.15 shows the finalizer method from the Java FileOutputStream class.
Note that a finalizer is an instance method (i.e., non-static), takes no arguments, returns no value (i.e., void), and must be named finalize().18
18C++ programmers, take note! Although Java constructor methods are named like C++ constructors, Java finalization methods are not named like C++ destructor methods.
EXAMPLE 14.15. A finalizer method.
/** * Closes the stream when garbage is collected. * Checks the file descriptor to make sure it is not already closed. */ protected void finalize() throws IOException { if (fd != null) close(); }
There are some additional things to be aware of about finalizers:
Previous | Table of Contents | Next |