Scrigroup - Documente si articole

     

HomeDocumenteUploadResurseAlte limbi doc
AccessAdobe photoshopAlgoritmiAutocadBaze de dateCC sharp
CalculatoareCorel drawDot netExcelFox proFrontpageHardware
HtmlInternetJavaLinuxMatlabMs dosPascal
PhpPower pointRetele calculatoareSqlTutorialsWebdesignWindows
WordXml

AspAutocadCDot netExcelFox proHtmlJava
LinuxMathcadPhotoshopPhpSqlVisual studioWindowsXml

What is finalize( ) for

java



+ Font mai mare | - Font mai mic



What is finalize( ) for?

You might believe at this point that you should not use finalize( ) as a general-purpose cleanup method. What good is it?



A third point to remember is:

Garbage collection is only about memory.

That is, the sole reason for the existence of the garbage collector is to recover memory that your program is no longer using. So any activity that is associated with garbage collection, most notably your finalize( ) method, must also be only about memory and its deallocation.

Does this mean that if your object contains other objects finalize( ) should explicitly release those objects? Well, no - the garbage collector takes care of the release of all object memory regardless of how the object is created. It turns out that the need for finalize( ) is limited to special cases, in which your object can allocate some storage in some way other than creating an object. But, you might observe, everything in Java is an object so how can this be?

It would seem that finalize( ) is in place because of the possibility that you'll do something C-like by allocating memory using a mechanism other than the normal one in Java. This can happen primarily through native methods, which are a way to call non-Java code from Java. (Native methods are discussed in Appendix A.) C and C++ are the only languages currently supported by native methods, but since they can call subprograms in other languages, you can effectively call anything. Inside the non-Java code, C's malloc( ) family of functions might be called to allocate storage, and unless you call free( ) that storage will not be released, causing a memory leak. Of course, free( ) is a C and C++ function, so you'd need call it in a native method inside your finalize( ).

After reading this, you probably get the idea that you won't use finalize( ) much. You're correct; it is not the appropriate place for normal cleanup to occur. So where should normal cleanup be performed?

You must perform cleanup

To clean up an object, the user of that object must call a cleanup method at the point the cleanup is desired. This sounds pretty straightforward, but it collides a bit with the C++ concept of the destructor. In C++, all objects are destroyed. Or rather, all objects should be destroyed. If the C++ object is created as a local, i.e. on the stack (not possible in Java), then the destruction happens at the closing curly brace of the scope in which the object was created. If the object was created using new (like in Java) the destructor is called when the programmer calls the C++ operator delete (which doesn't exist in Java). If the programmer forgets, the destructor is never called and you have a memory leak, plus the other parts of the object never get cleaned up.

In contrast, Java doesn't allow you to create local objects - you must always use new. But in Java, there's no "delete" to call for releasing the object since the garbage collector releases the storage for you. So from a simplistic standpoint you could say that because of garbage collection, Java has no destructor. You'll see as this book progresses, however, that the presence of a garbage collector does not remove the need or utility of destructors. (And you should never call finalize( ) directly, so that's not an appropriate avenue for a solution.) If you want some kind of cleanup performed other than storage release you must still call a method in Java, which is the equivalent of a C++ destructor without the convenience.

One of the things finalize( ) can be useful for is observing the process of garbage collection. The following example shows you what's going on and summarizes the previous descriptions of garbage collection:

//: Garbage.java

// Demonstration of the garbage

// collector and finalization

class Chair

protected void finalize()

if(i == 47)

finalized++;

if(finalized >= created)

System.out.println(

'All ' + finalized + ' finalized');

}

public class Garbage

while(!Chair.f)

System.out.println(

'After all Chairs have been created:n' +

'total created = ' + Chair.created +

', total finalized = ' + Chair.finalized);

if(args[0].equals('before'))

System.out.println('bye!');

if(args[0].equals('after'))

System.runFinalizersOnExit(true);

}

The above program creates many Chair objects, and at some point after the garbage collector begins running, the program stops creating Chairs. Since the garbage collector can run at any time, you don't know exactly when it will start up, so there's a flag called gcrun to indicate whether the garbage collector has started running yet. A second flag f is a way for Chair to tell the main( ) loop that it should stop making objects. Both of these flags are set within finalize( ), which is called during garbage collection.

Two other static variables, created and finalized, keep track of the number of objs created versus the number that get finalized by the garbage collector. Finally, each Chair has its own (non-static) int i so it can keep track of what number it is. When Chair number 47 is finalized, the flag is set to true to bring the process of Chair creation to a stop.

All this happens in main( ), in the loop

while(!Chair.f)

You might wonder how this loop could ever finish, since there's nothing inside that changes the value of Chair.f. However, the finalize( ) process will, eventually, when it finalizes number 47.

The creation of a String object during each iteration is simply extra garbage being created to encourage the garbage collector to kick in, which it will do when it starts to get nervous about the amount of memory available.

When you run the program, you provide a command-line argument of "before" or "after." The "before" argument will call the System.gc( ) method (to force execution of the garbage collector) along with the System.runFinalization( ) method to run the finalizers. These methods were available in Java 1.0, but the runFinalizersOnExit( ) method that is invoked by using the "after" argument is available only in Java 1.1 and beyond. (Note you can call this method any time during program execution, and the execution of the finalizers is independent of whether the garbage collector runs).

The preceding program shows that, in Java 1.1, the promise that finalizers will always be run holds true, but only if you explicitly force it to happen yourself. If you use an argument that isn't "before" or "after" (such as "none"), then neither finalization process will occur, and you'll get an output like this:

Created 47

Beginning to finalize after 8694 Chairs have been created

Finalizing Chair #47, Setting flag to stop Chair creation

After all Chairs have been created:

total created = 9834, total finalized = 108

bye!

Thus, not all finalizers get called by the time the program completes. To force finalization to happen, you can call System.gc( ) followed by System.runFinalization( ). This will destroy all the objects that are no longer in use up to that point. The odd thing about this is that you call gc( ) before you call runFinalization( ), which seems to contradict the Sun documentation, which claims that finalizers are run first, and then the storage is released. However, if you call runFinalization( ) first, and then gc( ), the finalizers will not be executed.

One reason that Java 1.1 might default to skipping finalization for all objects is because it seems to be expensive. When you use either of the approaches that force garbage collection you might notice longer delays than you would without the extra finalization.



Unfortunately, the implementations of the garbage collector in Java 1.0 would never call finalize( ) correctly. As a result, finalize( ) methods that were essential (such as those to close a file) often didn't get called. The documentation claimed that all finalizers would be called at the exit of a program, even if the garbage collector hadn't been run on those objects by the time the program terminated. This wasn't true, so as a result you couldn't reliably expect finalize( ) to be called for all objects. Effectively, finalize( ) was useless in Java 1.0.

By the time you read this, some Java Virtual Machines may show different behavior.



Politica de confidentialitate | Termeni si conditii de utilizare



DISTRIBUIE DOCUMENTUL

Comentarii


Vizualizari: 536
Importanta: rank

Comenteaza documentul:

Te rugam sa te autentifici sau sa iti faci cont pentru a putea comenta

Creaza cont nou

Termeni si conditii de utilizare | Contact
© SCRIGROUP 2024 . All rights reserved