In other words, while an object is referenced by such a variable,it is guaranteed to not be considered unreachable,and the variable itself is considered alive for the entire durationof its scope, even after it is last referenced.
Without this marker interface on the variable's type, a variable'svalue might be garbage collected before the surrounding scope hasbeen completely executed, as long as the variable is definitely notreferenced again. That can, in turn, trigger a NativeFinalizerto perform a callback. When the variable's type includes Finalizable,The NativeFinalizer callback is prevented from running untilthe current code using that variable is complete.
If a closure is created inside the block scope declaring the variable, andthat closure contains any reference to the variable, the variable staysalive as long as the closure object does, or as long as the body of such aclosure is executing.
The behavior of Finalizable variables applies to asynchronousfunctions too. Such variables are kept alive as long as anycode may still execute inside the scope that declared the variable,or in a closure capturing the variable,even if there are asynchronous delays during that execution.
Also in asynchronous code it's likely an error if a resource extracted froma finalizable object escapes the scope of the finalizable variable it'staken from. If you have to extract a resource from a Finalizable, youshould ensure the scope in which Finalizable is defined outlives theresource by awaiting any asynchronous code that uses the resource.
It is possible for an asynchronous function to stall at anawait, such that the runtime system can see that there is no possibleway for that await to complete. In that case, no code after theawait will ever execute, including finally blocks, and thevariable may be considered dead along with everything else.
For example, finalizable is not kept alive by myFunction after it hasrun to the end of its scope, while someAsyncCall could still continueexecution. However, finalizable is kept alive by someAsyncCall itself:
Finalize methods are called at the completion of a garbage collection on objects that the GC has determined to be garbage. This means that the memory for these objects cannot be reclaimed right away because the Finalize method might execute code that accesses a field. Because a finalizable object must survive the collection, it gets promoted to another generation, forcing the object to live much longer than it should
It misled me a little bit. Why cannot finalizable object be reclaimed right away? I cannot understand argument that finalize method might execute code that accesses a field. What is problem? Moreover, I cannot understand why finalizable object should be moved to older generation and stored in separated queue (to be processed in other finalizer thread).
The two points add up together to the fact that when gc is happening, it cannot execute the Finalize() method right away (All threads are paused during gc!!), while Finalize is expected to be invoked before object being collected.
All these above leads to the fact that garbage collection cannot kill the object immediately before its Finalize() method is invoked. So gc takes the object out from the "death list" (the object is now said to be resurrected), and put it to a queue called "Freachable" ("F" stands for finalization, "reachable" means all objects in it cannot be garbage collected now since gc only collects objects unreachable from roots).
After the gc finished, a special dedicated thread with high priority will take out each entry from the "Freachable" queue and invoke Finalize() method on it, which makes that object finally "garbage collectable", but of course, since the first gc has already ended before this Finalize() calling process, all the objects poped out from "Freachable" can now only be scheduled to next garbage collection.
To understand this, you need to first know the concept of the generation gc model. After objects are popped out from the "Freachable" queue and are again ready for garbage collection, they have been moved to older generation owing to the fact that they survive the previous one.
My logical argument is that when we override finalize method, the runtime will have to register this object with the garbage-collector (so that GC can call finalize of this object, which makes me think that GC will have reference to all the finalizable objects). And for this, GC will have to keep a strong reference to the finalizable object. If that is the case then how this object became a candidate for reclamation by GC in the first place? I reach a contradiction by this theory.
You are right in that the garbage collector needs a reference to finalizable objects. Of course, this particular reference must not be considered when deciding whether the object is still reachable before the finalization. This implies special knowledge about the nature of this reference to the garbage collector.
Though you got your answer (which is absolutely correct), I want to add a small-ish addendum here. In general, references are of two types : strong and weak. Weak References are WeakReference/SoftReference/PhantomReference and Finalizer(s).
When a certain GC cycle traverses the heap graph and sees one of these weak references, it treats it in a special way. When it first encounters a dead finalizer reference (let's consider this being the first GC cycle), it has to resurrect the instance. finalize is an instance method, and it needs an actual instance to be invoked. So a GC first saw that this Object is dead, only to revive it moments later, to be able to call finalize on it. Once it calls that method on it, it marks the fact that it has already been called; so when the next cycle happens, it can be actually be GC-ed.
An unfinalized object has never had its finalizer automatically invoked; a finalized object has had its finalizer automatically invoked. A finalizable object has never had its finalizer automatically invoked, but the Java virtual machine may eventually automatically invoke its finalizer.
So what is the formal difference between an unfinalized and a finalizable object ? From the quote it seems that if unfinalized and finalizable are to be different, then for an unfinalized object it must be the case that it is not true that the JVM may eventually invoke its finalizer. A little confusing or I still have some English semantics to study ;)
Unfinalized objects are not eligible for finalization yet. They are reachable. Finalizable objects are eligible to be finalized, so the JVM may do that when it chooses. In other words, "may" in the sense of "has permission to" not just in the sense of "it might happen."
The difference between an unfinalized and a finalizable object is that the finalizer on the second one could be automatically invoked at any time in the future, while the finalizer on the unfinalized object can't be automatically invoked, unless the object first becomes finalizable.
When an object no longer has a strong reference to it, it can be garbage collected. Some time later a GC can be performed and the object is added to a finalization queue to have its finalize() method called. Once the method has been called it can be removed if there still is not strong reference to it.
I need to optimize my application in memory usage. so I used .net performance profiler...but some references in my application are still alive and are never collected by GC even if I force it to collect.
As you observed, the profiler is telling you that the referenced object is of type "Finalization Handle". What that means is that it is coming from the finalizer queue. The finalizer queue is what the .NET garbage collector uses to hold all objects that implement a finalizer method. The finalizer is the mechanism used to ensure that unmanaged resources are properly released during garbage collection. An object that contains unmanaged resources implements the IDisposable pattern, including the Finalize method, which is where the unmanaged resources are released. When the garbage collector processes "finalizable" objects (as indicated by the value of a bit in the object's header), it moves them into the finalizer queue. During collection, the GC iterates through the finalizer queue and calls the Finalize method on each of those objects.
What the author of the library evidently failed to do is to call GC.SuppressFinalize() from within the Dispose method. This normally removes the object from the finalizer queue by clearing the "finalizable" bit in the object's header, and indicates that the Finalize method does not need to be called.
In general, you should not rely on the finalizer to release unmanaged resources. All objects that implement IDisposable should be explicitly disposed of by your code, either by manually calling the Dispose method or, preferably, by wrapping their creation in a using block that will automatically call Dispose when the block's scope is exited.
Finalization is a feature of the Java programming language that allows you to perform postmortem cleanup on objects that the garbage collector has found to be unreachable. It is typically used to reclaim native resources associated with an object. Here's a simple finalization example:
Sometime after an Image1 instance has become unreachable, the Java Virtual Machine (JVM) * will call its finalize() method to ensure that the native resource that holds the image data -- pointed to by the integer nativeImg in the example -- has been reclaimed.
Notice, however, that the finalize() method, despite its special treatment by the JVM, is an arbitrary method that contains arbitrary code. In particular, it can access any field in the object -- pos and dim in the example. Surprisingly, it can also make the object reachable again by, say, making it reachable from a static field, for example, randomImg = this;. The latter programming practice is not recommended, but unfortunately the Java programming language allows it.
c80f0f1006