Read an Excerpt
Chapter 5: Memory and Garbage Collection
Objectives for This Chapter- Identify when an object referred to by a local variable becomes eligible to be garbage collected (in the absence of compiler optimization).
- Describe how finalization works and the behavior Java guarantees regarding finalization.
- Distinguish between modifying variables containing primitive data types and object references, and modifying the objects themselves.
- Identify the results of Java's pass-by-value approach when passing parameters to methods.
- Freeing memory too soon (resulting in a dangling pointer)
- Not freeing memory soon enough or at all (resulting in a memory leak)
- Accessing memory beyond the bounds of the allocated memory (resulting in using uninitialized values)
Objects are allocated from a garbage-collected heap. You cannot directly alter the memory in this heap. You can only get at the objects in this heap by using object refer-ences. Since Java manages the heap, and since you cannot manipulate object references, you must trust the Java Virtual Machine (JVM) to do what's right: free memory when it should, allocate the correct amount of memory when needed, and so on. But don't worry; the JVM is very good at its job—much better than any of us error-prone humans.
Garbage Collection
For the exam, you'll need to be able to identify when an object referred to by a local vari-able becomes eligible to be garbage collected (in the absence of compiler optimization). Since Java manages the garbage-collected heap, which is where all your objects live, you've got to trust Java to manage the memory for you. This includes believing that the JVM really will free memory that you no longer need when it runs low.
When Does an Object Become
Eligible for Garbage Collection?
An object becomes a candidate for garbage collection when your program can no
longer reference it. Here is an example. Let's say you allocate an object and only assign
it to a method variable. When that method returns, you have no way to ever refer to that
method variable again. Therefore, the object is lost forever. That means that when the
method returns, the object is a candidate for garbage collection.As another example, you might create an object, assign this object to an object reference, and then set this object reference to null. As soon as you lose the reference to the object, that object becomes a candidate for garbage collection.
Just because your program might lose a reference to an object does not mean that the JVM will reclaim that object's memory right away, or even at all. The JVM will only perform garbage collection if it needs more memory to continue executing. For almost all simple programs, including the ones you've seen so far, the JVM doesn't even come close to running out of memory.
CAUTION: The reason the garbage collector does not reclaim memory as soon as it is available is that garbage collection takes time. If the garbage collector were continuously expunging allocated memory that you could no longer access, it would seriously slow your program's execution. It is not guaranteed that the garbage collector will reclaim objects in a certain order. This allows the garbage collector to run as efficiently as possible.
Even though a new keyword exists, notice that you do not explicitly indicate how much memory to set aside. The JVM determines this for itself. The JVM determines the memory your object requires based on
- The amount of memory needed to maintain instance variables for the object
- A standard overhead required by all objects
Invoking the Garbage Collector
Even though you cannot free objects explicitly, you can directly invoke the garbage collector. This will make the garbage collector run, which will reclaim candidates for garbage collection.They way you run the garbage collector is to perform two steps:
- Get an object that represents the current runtime.
- Invoke that object's gc() method.
Runtime rt = Runtime.getRuntime(); rt.gc();
Exercise 5-2 asks you to work through an example of this.
Finalization
For the exam, you'll need to know when finalization takes place. In most situations, you'll never know when garbage collection has occurred. Java runs the garbage-collecting process as a low-priority background thread. The garbage collector will run whenever memory gets low.However, you can get into the act of garbage collection. If you want to perform some task when your object is about to go away, you can override a method called finalize().
Java will invoke the finalize() method exactly once for every object in your program. finalize() is declared as protected, does not return a value, and throws a Throwable object.
Java invokes the finalize() method just before an object is about to be garbage collected. You might take advantage of this notification to clean up any resources that have been allocated outside this object. A classic example is a file that an object has opened that might still be open. The object can check to see if the file has been closed in finalize() and, if not, it will close the file....