In object-oriented programming languages that use garbage collection, a finalizer is a special method that is executed when an object is garbage collected. It is similar in function to a destructor. In less technical terms, a finalizer is a piece of code that ensures that certain necessary actions are taken when an acquired resource (such as a file or access to a hardware device) is no longer being used. This could be closing the file or signalling to the operating system that the hardware device is no longer needed. However, as noted below, finalizers are not the preferred way to accomplish this and for the most part are fail-safe.
Unlike destructors, finalizers are usually not deterministic. A destructor is run when the program explicitly frees an object. In contrast, a finalizer is executed when the internal garbage collection system frees the object. Depending on the garbage collection method used, this may happen at an arbitrary moment after the object is freed, possibly never.
Due to the lack of programmer control over their execution, it is usually recommended to avoid finalizers for any but the most trivial operations. In particular, operations often performed in destructors are not usually appropriate for finalizers. For example, destructors are often used to free expensive resources such as files or network handles. If placed in a finalizer, the resources may remain in use for long periods of time after the program is finished with them. Instead, most languages encourage the dispose pattern whereby the object has a method to clean up the object's resources, leaving the finalizer fail-safe in the case where the dispose method doesn't get called. C#, Java, and Python include syntactic constructs to aid use of the dispose pattern.
Languages with finalizers must also address the problem of object resurrection. Resurrection occurs when an object's finalizer causes the object to become reachable (that is, not garbage). The garbage collector must determine if the object has been resurrected by the finalizer or risk creating a dangling reference. Languages have adopted several different solutions. For example, Java will not free the object until it has proven that the object is once again unreachable, but will not run the finalizer more than once. Objective-C 2.0 will put resurrected objects into a "zombie" state, where they log all messages sent to them, but do nothing else.
Object resurrection is useful to handle a pool of commonly used objects, but it obscures code and makes it more confusing. It should be used only for objects that may be frequently used and where the construction/destruction of it is time-consuming. An example could be an array of random numbers, where a large number of them is created and destroyed in a short time, but where actually only a small number is in use at the same time. With object resurrection, a pooling technique would reduce the unnecessary overhead of creation and destruction. Here, a pool manager would get onto its object stack information in the form of a reference to the object, if it is currently to be destructed. The pool manager will keep the object for reuse later.
- Garbage collection, specifically the section on Determinism
- Object lifetime
- Initialization Process & related Initializer Pattern
- "What is resurrection (in garbage collection)?". http://www.xyzws.com/: XYZWS. Retrieved 2011-08-01. "An object that has been eligible for garbage collection may stop being eligible and return to normal life. Within a finalize() method, you can assign this to a reference variable and prevent that object's collection, an act many developers call resurrection. /The finalize() method is never called more than once by the JVM for any given object. The JVM will not invoke finalize() method again after resurrection (as the finalize() method already ran for that object)."
- "Object resurrection". http://www.hesab.net/: Hesab.net. Retrieved 2011-08-01. "Object resurrection is an advanced technique that’s likely to be useful only in unusual scenarios, such as when you’re implementing a pool of objects whose creation and destruction is time-consuming. ... The ObjectPool demo application shows that an object pool manager can improve performance when many objects are frequently created and destroyed. Assume that you have a RandomArray class, which encapsulates an array of random numbers. The main program creates and destroys thousands of RandomArray objects, even though only a few objects are alive at a given moment. Because the class creates the random array in its constructor method (a timeconsuming operation), this situation is ideal for a pooling technique. ... The crucial point in the pooling technique is that the PoolManager class contains a reference to unused objects in the pool (in the PooledObjects Stack object), but not to objects being used by the main program. In fact, the latter objects are kept alive only by references in the main program. When the main program sets a RandomArray object to Nothing (or lets it go out of scope) and a garbage collection occurs, the garbage collector invokes the object’s Finalize method. The code inside the RandomArray’s Finalize method has therefore an occasion to resurrect itself by storing a reference to itself in the PoolManager’s PooledObjects structure. So when the NewRandomArray function is called again, the PoolManager object can return a pooled object to the client without going through the time-consuming process of creating a new one."