Chapter 3: Garbage Collection-
Philip Heller Notes
Overview
You should be conversant with the mechanisms of the garbage collection system and with the ways your programming interacts with it.
Garbage collection simplifies the programmer’s job enormously. Memory management is susceptible to two types of error—memory can be used simultaneously for two purposes, or it can remain unavailable for reuse after it is no longer needed. Both of these errors can cause major problems for any program. An automatic garbage collection system such as Java provides prevents the first of these problems and reduces but does not eliminate the second.
State the behavior that is guaranteed by the garbage collection system and write code that explicitly makes objects eligible for collection.
This objective is intended to ensure you have a clear grasp of the responsibilities that rest with you as the programmer. It also ensures you understand the control—and lack of control—you have over the allocation and deallocation of memory. Proper handing of available memory is a crucial concern for anyone writing commercial grade applications, because memory is a finite resource in any computer system and forcing a program to resort to virtual memory will slow it down dramatically.
Critical Information
Two types of errors can occur in memory management in general programming: Memory can be made available for reuse while it is actually still in use, and memory that is no longer in use can remain allocated and unavailable for reuse.
Java’s garbage collection system entirely prevents accidental releasing of memory: As long as an object is accessible from any live thread, the object will remain valid, and the memory associated with it will not be reused. The garbage collector guarantees that it will not reclaim memory that is still in use or is potentially still usable.
There are two types of memory leak, which we shall call hard leaks and soft leaks. They are similar, but Java’s memory management system only helps with the hard leak. A hard leak occurs in languages without a garbage collection system, when there are no references to an area of memory, but that area of memory has not been released. The area of memory is then permanently lost from the program. This type of leak cannot occur with Java, since the scenario described, having zero references to an area of memory, is the definition of how the garbage collector decides the area is eligible for collection.
The second type of leak, a soft leak, occurs when a program has areas of memory that the program will never again use but that have not been, and will not be, released. Java’s garbage collection cannot protect against soft leaks because to do so would require semantic understanding of the meaning and operation of the algorithms that are being coded, and that represents artificial intelligence at a level beyond the skills of modern programming.
To avoid soft memory leaks with Java, simply write null into any reference that will not be used again. The object will become eligible for garbage collection as soon as all references to it are either set to null or become inaccessible.
When a local variable goes out of scope, it becomes inaccessible and therefore is no longer a valid reference to an object. Thus, it doesn’t explicitly require setting to null.
Limitations of the Garbage Collector
When the garbage collector runs, it consumes a certain amount of CPU time. Depending upon the particular garbage collection algorithm used in any given JVM, the rest of the JVM might be frozen while the collection proceeds.
The garbage collection system runs in a thread of its own. Since the thread scheduling algorithm is not specified by Java, you cannot know when, or if, the thread will run. Generally, of course, in the absence of high priority runnable threads, the garbage collector will get its turn. However, the uncertainty surrounding thread scheduling is one of the main reasons there are no guarantees about when, or even if, the garbage collector will reclaim memory. Even calling System.gc() or Runtime.gc() does not force the garbage collector to run.
If the JVM starts to run short of memory, the garbage collector will be set running before an out-of-memory error occurs. This does not happen if the system is running short of system resources, such as file handles, network sockets, or windows. This is the purpose of the dispose() method of the Window class and the close() method of the stream classes.
In general, the limitations of the garbage collector can be summed up as follows: No promises are made regarding when, how fast, or even if the garbage collector will recover a given unreferenced object from memory.
Exam Essentials
Understand memory reclamation and the circumstances under which memory will be reclaimed. If an object is still accessible to any live thread, that object will certainly not be collected. This is true even if the program will never access the object again—the logic is simple and cannot make inferences about the semantics of the code. No guarantees are made about reclaiming available memory or the timing of reclamation if it does occur. In a standard JVM, there is no entirely reliable, platform- independent way to force garbage collection.
Understand System.gc() and Runtime.gc() and their effects on garbage collection. The gc() methods in the System and Runtime classes make it more likely that garbage collection will run but do not guarantee it; for example, other threads might retain the CPU.
Recognize the significance of writing null into a variable. Simply abandoning a variable and allowing it to retain its reference value is likely to cause wasted memory, since any valid reference prevents an object from being garbage collected. To indicate to the runtime system that a reference is no longer in use, thereby making it possible for an unused object to be collected, assign null into a variable to delete the old reference. Of course, writing null does not of itself make the object collectable; that occurs only when no more accessible references exist.
Key Terms and Concepts
Live reference A reference that is accessible to a live thread.
Live thread A thread that has been started but has not yet died.
Memory leak An area of memory that will not be used by the program but that will not be reclaimed for reuse. Java only partially protects against this problem. Write null into references you have finished with to help yourself.
Referenced memory Memory that is being used for storage of an object that is accessible by a live reference.
Runtime.gc() gc() is a static method in the java.lang.Runtime class. By calling the method, you request that the garbage collector run. However, calling the method does not guarantee that the garbage collector will run, nor does it guarantee any limiting timescale in which the garbage collector might run.
System.gc() Another way to request garbage collection, with the same limitations as Runtime.gc().
Unreferenced memory Memory that is not being used for storage of any object accessible by a live reference.
Sample Questions
1. Which memory management problems are addressed by garbage collection?
A. Accidental deallocation of memory that is still in use
B. Failure to reclaim all unneeded memory
C. Failure to reclaim inaccessible memory
D. Insufficient physical memory
E. Insufficient virtual memory
2. Which is true?
A. Calling System.gc() causes garbage collection to occur, but the time for the process to complete is unspecified.
B. Calling Runtime.gc() causes garbage collection to occur, but the time for the process to complete is unspecified.
C. Memory leaks are impossible in Java.
D. Memory is used more efficiently in Java.
E. Memory corruption due to double use of memory is impossible in Java.
3. What is the effect of calling System.gc()?
A. Garbage collection occurs immediately.
B. Garbage collection occurs but not necessarily immediately.
C. Garbage collection might occur soon, if other system behavior permits.
4. In the following program, which of the objects can be released at point X on line 10 (assuming there is further behavior between line 10 and the program’s exit)?
1. public class Test {
2. private Object o = new Object();
3. private static final Object p = new Object();
4.
5. public static void main(String [] args) {
6. Test t = new Test();
7. Test u = new Test();
8. t.o = null;
9. method(u);
10. // point X, other behavior follows
11. }
12.
13. public static void method(Object u) {
14. Object q = new Object();
15. u = null;
16. }
17. }
A. Variable o in Test object t
B. Variable p in the Test class
C. Variable o in Test object u
D. Variable q in the method method()
E. Variable t in the method main()
F. Variable u in the method main()
Answers
1. A, C. Memory cannot be accidentally deallocated; any live reference prevents this. Inaccessible memory is precisely what the garbage collector looks for, so C is true. However, unneeded memory that is still accessible by a live reference will not be collected and will waste space, so B is false. Similarly, if there is insufficient memory, either physical or virtual, the garbage collector cannot help. Either the program will fail due to insufficient virtual memory, or the virtual memory system will thrash if there is insufficient physical memory.
2. E. Calling gc() in either of its guises does not guarantee that the garbage collector will run, so A and B are false. Memory leaks can happen if you fail to null out accessible references to unneeded memory. Memory is not used any more efficiently, so D is false. However, double use of memory is impossible, since accessible memory is never returned to the heap for reuse, so it cannot be accidentally reallocated.
3. C. As the documentation notes, calling the gc() method "suggests" that the system expend effort to run the garbage collection system. So, only C is true.
4. A, D. Because line 8 writes null into the member variable t.o, and t.o was the only reference to that object, it becomes collectible immediately after line 8, making A true. Variable p is static and final, so as long as the class is loaded, the target of the reference cannot be collected. In the code, variable u at line 7 is left unchanged, as is member o. Therefore, C is false since the object remains accessible at least until line 10. At line 16, when the method method() returns, the local variable q goes out of scope, and the object it refers to becomes unreferenced. Therefore, D is true. Although member t.o is set to null at line 8, the variable t is not nulled out; therefore the object it refers to cannot be collected, and E is false. In lines 13 and 15, a local variable called u is declared and nulled out; however, this is a second reference to the object that variable u declared at line 7. Therefore, even though it is set to null at line 15, a live accessible reference remains at line 10, making F false.
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment