11.9 OBJECT DESTRUCTION IN JAVA


11.9 OBJECT DESTRUCTION IN JAVA

Unlike what's achieved by a destructor in C++, Java does not provide a way to destroy an object at will. While you are allowed to recommend to Java runtime that unreferenced objects (referred to as garbage) be destroyed and the memory occupied by them reclaimed, you cannot destroy a particular object at a specific moment during the execution of a Java program.

Memory occupied by unreferenced objects in Java is automatically reclaimed by a low-priority garbage collection thread that runs continuously in the background while your application program is being executed. However, before actually destroying an unreferenced object, the garbage collector invokes the class's finalize method for the object. Every class inherits a do-nothing finalize from the root class Object, but you can provide an override definition for your own class. An override definition is needed if an object appropriates non-Java resources, such as open files, I/O connections, and so on, that the object must either close or free up before the object is permanently discarded. When an object's finalize method is invoked, the object is said to be finalized.

The garbage collection process in Java carries no guarantees as to the order in which the unreferenced objects will be finalized and the memory occupied by them reclaimed. There are even no guarantees that the garbage collection will be invoked on all the unreferenced objects, or, for that matter, on any unreferenced objects at all. The application program may exit before the garbage collector can do its thing, which would cause the underlying system to free up all of the memory occupied by the application program anyway-but without the finalization of the objects destroyed without the benefit of the garbage collector. For most applications this will not cause a problem because, as the Java Virtual Machine exits, it will automatically close all open files and sockets.

The following program is a simple demonstration of the fact that the unreferenced objects may be finalized and destroyed in an order that cannot be predicted beforehand and that not all unreferenced objects may get finalized before the Java Virtual Machine exits.

The class X in the program has a data member id that serves as a serial number for the object. The first object of type X will have a value of 1 for value of id, the second object a value of 2, and so on. In the main of Test, we construct an array of 10,000 objects of type X in line (C) through (E); their id numbers will range from 1 through 10,000. After creating the array, we suddenly set the array reference to null in line (F), causing the entire array object to become unreferenced. This causes all the objects whose references are held in the elements of the array to also become unreferenced, and to thus become candidates for garbage collection. We then ask the garbage collector in line (G) to try to reclaim the memory occupied by the unreferenced objects by invoking

     System.gc(); 

If we did not explicitly request the garbage collector to make a fresh sweep of the allocated memory, it is possible that the application would exit before any of the objects is finalized. When control returns from a call to System.gc(), this means that the Java Virtual Machine has made a best effort to reclaim space from all unreferenced objects.

In the code below, note that the finalize method in line (A) prints out a message if the id of the object involved is a multiple of 1000.

 
//GC.java class X { int id; static int nextId = 1; //constructor: public X() { id = nextId++; } protected void finalize() throws Throwable { //(A) if ( id%1000 == 0 ) System.out.println("Finalization of X object, id = " + id); super.finalize(); //(B) } } class Test { public static void main( String[] args ) { X[] xarray = newX[ 10000 ]; //(C) for (int i = 0; i < 10000; i++) //(D) xarray[i] = new X(); //(E) xarray = null; //(F) System.gc(); //(G) } }

Shown below is the output from five different runs of the program. As is clear from the output, the unreferenced objects may be finalized and discarded in virtually any order.

 First run:           Finalization of X object, id = 10000     Finalization of X object, id = 8000     Finalization of X object, id = 5000     Finalization of X object, id = 1000     Finalization of X object, id = 2000     Finalization of X object, id = 3000     Finalization of X object, id = 4000 Second run:     Finalization of X object, id = 3000     Finalization of X object, id = 1000     Finalization of X object, id = 2000 Third run:     Finalization of X object, id = 5000     Finalization of X object, id = 1000     Finalization of X object, id = 2000     Finalization of X object, id = 3000     Finalization of X object, id = 4000 Fourth run:     Finalization of X object, id = 8000     Finalization of X object, id = 9000     Finalization of X object, id = 1000     Finalization of X object, id = 2000     Finalization of X object, id = 3000     Finalization of X object, id = 4000     Finalization of X object, id = 5000     Finalization of X object, id = 6000 Fifth run:     Finalization of X object, id = 1000     Finalization of X object, id = 2000     Finalization of X object, id = 3000     Finalization of X object, id = 4000     Finalization of X object, id = 5000     Finalization of X object, id = 6000     Finalization of X object, id = 7000 

Obviously, the garbage collector is not able to finalize all the objects before the Java Virtual Machine quits. For the second run, fewer than half of the 10,000 objects are getting finalized and garbage collected.

Note that the override definition of finalize in line (A) invokes super.finalize in line (B). As recommended by Arnold and Gosling [2, p. 49], it is a good practice to always remember to invoke super.finalize in the code for finalize. Failure to do so may result in the superclass part of the object to not get finalized.

As the following "pathological" variation on the above program shows, it is possible to resurrect an object that is being finalized. Even when there are no further references to an object (which causes the garbage collector to invoke its finalize), for obvious reasons the object has to be accessible inside its own finalize method. This fact can be used to resurrect the object, preventing its destruction-at least until what was resurrected becomes unreferenced or goes out of scope. In the following program, as each X object is being finalized, it is resurrected by

     X resurrect = this; 

in line (B) of the program. This step creates a new reference to the object, which is then put away in line (C) in a static array that was defined earlier in line (A). This causes the object in question to not get destroyed until the Java Virtual Machine exits. It is interesting to know that finalize will not be invoked again on resurrected objects. The garbage collector invokes finalize exactly once for each object.

 
//GC_Resurrect.java class X { int id; static int nextId = 1; static X[] staticArr = new X[10000]; //(A) //constructor: public X() { id = nextId++; } protected void finalize() throws Throwable { if ( id%1000 == 0 ) System.out.println("Finalization of X object, id = " + id); super.finalize(); X resurrect = this; //(B) putItAway(resurrect); //(C) } public void putItAway(X xobj) { staticArr[ id ] = this; } } class Test { public static void main( String[] args ) { X[] xarray = new X[ 10000 ]; for ( int i = 0; i < 10000; i++ ) xarray[i] = new X(); xarray = null; System.gc(); } }

What if the finalize method for a class throws an exception? The exception is ignored and finalization of the object terminated.

It is also possible to call the gc method through the Runtime class by invoking

     Runtime.getRuntime().gc() 

This is equivalent to the System.gc() call.




Programming With Objects[c] A Comparative Presentation of Object-Oriented Programming With C++ and Java
Programming with Objects: A Comparative Presentation of Object Oriented Programming with C++ and Java
ISBN: 0471268526
EAN: 2147483647
Year: 2005
Pages: 273
Authors: Avinash Kak

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