Which is a better way to force GC on ThreadLocal instance?
Simple answer: you can't force the GC in java. Some may posts tricks but all in all you simply can't.
Well, in fact you can. With exit!
The simple and ugly answer:
System.gc();
This does not guarantee garbage collection of a specific object, but it will tell the VM to make an effort to perform general garbage collection.
Specifically, for a ThreadLocal variable, the contained instance of the variable will not be GC'd until the thread dies or the ThreadLocal instance is no longer accessible. So, you will need to kill the associated thread, or you will need to discard your references to the ThreadLocal variable in order for the System.gc() to have any effect.
However, the very fact that you are calling this points to a larger problem in your code. If you want to get rid of an object, simply having no references to it should be sufficient. The VM will come along some time later and clean up your mess.
To repeat: There is no reason that clean code should be explicitly calling GC.
You can't force GC and in many cases when you run in a container even calling System.gc() won't help since the JVM usually set with -XX:+DisableExplicitGC. The JVM will ignore your explicit calls.
The jlibs library has a good utility class for garbage collection. You can force garbage collection using a nifty little trick with WeakReference objects.
RuntimeUtil.gc() from the jlibs:
/**
* This method guarantees that garbage collection is
* done unlike <code>{#link System#gc()}</code>
*/
public static void gc() {
Object obj = new Object();
WeakReference ref = new WeakReference<Object>(obj);
obj = null;
while(ref.get() != null) {
System.gc();
}
}
A ThreadLocal<Object> is just a key. The actual values are stored in eachThread’s threadLocals weak hash map, which maps weak ThreadLocal to strong Object.
Assume that nobody else holds a reference to the Object in a ThreadLocal. Then there are two ways for the value of a ThreadLocal value to be garbage collected. First, there’s the easy way:
The thread finishes (internally setting its threadLocals map to null).
The garbage collector runs, deleting the Thread’s ThreadLocalMap and all unreachable Objects within it.
But if the thread is still running, then this sequence must happen before your Object can be garbage collected:
You lose all references to the ThreadLocal.
The garbage collector deletes the ThreadLocal.
You set() some number of other ThreadLocals within that thread, and the ThreadLocalMap removes the stale entry from the map. The number needed is nondeterministic because unlike a standard WeakHashMap, the ThreadLocalMap only expunges a few stale entries at a time, and only on set(), not get().
The garbage collector finally deletes the Object.
To mitigate the problem of slow garbage collection, you can call ThreadLocal.remove() from each Thread if that thread doesn’t need the object anymore.
Related
Just trying to understand something from GC viewpoint
public Set<Something> returnFromDb(String id) {
LookupService service = fromSomewhere();
Map<String,Object> where = new WeakHashMap<>() {}
where.put("id",id);
return service.doLookupByKVPair(where); // where doesn't need to be serializable
}
what I understand is that once this method call leaves the stack, there is no reference to where regardless of using HashMap or WeakHashMap - but since weak reference is weakly reachable wouldn't this be GCd faster? But if the method call leaves the stack, then there is no reachable reference anyway.
I guess the real question that I have is - "Would using WeakHashMap<> here actually matters at all" - I think it's a "No, because the impact is insignificant" - but a second answer wouldn't hurt my knowledge.
When you use a statement like where.put("id",id); you’re associating a value with a String instance created from a literal, permanently referenced by the code containing it. So the weak semantic of the association is pointless, as long as the code is reachable, this specific key object will never get garbage collected.
When the entire WeakHashMap becomes unreachable, the weak nature of the references has no impact on the garbage collection, as unreachable objects have in general. As discussed in this answer, the garbage collection performance mainly depends on the reachable objects, not the unreachable ones.
Keep in mind the documentation:
The relationship between a registered reference object and its queue is one-sided. That is, a queue does not keep track of the references that are registered with it. If a registered reference becomes unreachable itself, then it will never be enqueued. It is the responsibility of the program using reference objects to ensure that the objects remain reachable for as long as the program is interested in their referents.
In other words, a WeakReference has no impact when it is unreachable, as it will be treated like any other garbage, i.e. not treated at all.
When you have a strong reference to a WeakHashMap while a garbage collection is in progress, it will reduce the performance, as the garbage collector has to keep track of the encountered reachable WeakReference instances, to clear and enqueue them if their referent has not been encountered and marked as strongly reachable. This additional effort is the price you have to pay for allowing the earlier collection of the keys and the subsequent cleanup, which is needed to remove the strongly referenced value.
As said, when, like in your example, the key will never become garbage collected, this additional effort is wasted. But if no garbage collection happens while the WeakHashMap is used, there will be no impact, as said, as the collection of an entire object graph happens at once, regardless of what kind of objects are in the garbage.
ReferenceQueue q = new ReferenceQueue();
Reference r = q.remove();
r.clear();
I see that the java doc says that the clear method clears this reference object. I don't understand the meaning of this. Does this clear from the memory and thus in other words the object has been garbage collected?
java.lang.Reference is a base class for few special references which are treated in special way by garbage collection.
Under certain circumstances garbage collector may push reference object in it's reference queue (reference may be queued only once in a lifetime).
clear() method can be used to suppress special handling (and thus additional work for garbage collector). If reference object is already in queue it doesn't make sense to clear it, it is already cleared by garbage collector.
This project on github has an implementation of resource management using PhantomReferences made for educational purpose. clear() is used if resource is disposed explicitly to avoid extra work for GC in that case.
clear() simply sets the internal reference to null. Since references are automatically cleared when being enqueued by the garbage collector (with the exception of phantom references, but this oddity can be ignored, it will be eliminated in Java 9), there is usually no need to call clear() on a reference received via ReferenceQueue.remove().
In principle, there is the possibility to enqueue references manually via enqueue() without clearing them, but there is little sense in that, as the primary purpose of the reference queue is to learn about references being enqueued by the garbage collector which will be cleared.
When you call clear() on a Reference object that has not been enqueued yet, it may allow the referent to get collected without enqueuing the Reference object. On the other hand, when you don’t need the Reference object anymore, you can let the JVM collect it like an ordinary object, together with the referent if there are no other references left, as in that case, it won’t get enqueued as well, making clear() unnecessary.
In this query remove() method has following implementation.
/**
* remove() removes "node" from this DList. If "node" is null, do nothing.
* Performance: runs in O(1) time.
*/
public void remove(DListNode node) {
if((node != null) && (node.listp == this)){
node.prev.next = node.next;
node.next.prev = node.prev;
}
this.size--;
}
After the execution of this remove() method, There would not be any inward pointer pointing to object unless the user of DList class still points to this node using some reference variable.
My question:
When and How does garbage collector trash this object after none of the reference pointers point to this object? Because How can GC get control of that object without any reference to it?
An object may be GC'ed/reclaimed at any point after it is no longer strongly reachable. An object is strongly reachable if and only if it can be reached (via strong references) from a GC root. That is, the GC reclaiming an object - if and when it chooses to do so - is merely a consequence of not being able to access said object.
Now, the one thing that Java guarantees is that it will try it's best (which may involve doing nothing) to free memory before throwing an OOM.
Even though there are no strong references from the code doesn't mean that the JVM isn't tracking the object or that it has vanished! The object still exists - even though it is not strongly reachable (read: not accessible) from user code - until/when such is actually GC'ed.
This allows for some interesting cases, eg.
A finalizer has a this - access to the object to be GC'ed! - and can "relife" (or "resurrect") objects, which is bad. Note: while a finalizer being called roughly implies the object is finally going to be GC'ed; a finalizer is not guaranteed to be called, ever, etc.
ReferenceQueues and the *Reference types can be used to track objects that are no longer strongly reachable and thus are elligble to be GC'ed even though a strong reference may still be obtainable - and obtaining such would remove the reclaimable status.
It is undefined. It could happen the next time the garbage collector runs (it can ONLY happy when the garbage collector runs), but that is not guarenteed - Not all garbage is necessarily cleaned with each gc run
Java's GC does not trash an object as soon as it's not used anymore. Instead, GC runs from time to time, checking objects' usage and emptying memory.
You cannot tell GC to run arbitrarily, but you can request it to run by calling System.gc(). However, calling gc() does not run GC AT THIS TIME... it will only request the System to run it.
I have some objects in my code which are not invoked in everyloop,But they are useful in future when some forced termination from loop,unpredictable error etc happens, So how to make sure that this objects are not ever collected by garbage collector.
For example : I have one class so I dont want GC to perform any Garbage collection on this class
If the objects are valuable and expensive to create, you should hang on to them in a field in your class. You could create a Map that would act sort of like a cache and grab them out of the Map when you're ready to use them again.
If they are useful in the future you have a reference to these objects somewhere. This is enough to ensure that they will never be garbage collected.
Keep a strong reference to the object, Doing this will always ensure that your object will not be GCed. I would also leave such things to the Garbage collector which I think is smarter than us(with all due respect) when it comes to memory management
You should have a look at the scope of your variables. as long as they are in scope they should not be garbage collected.
Garbage Collector Simply Avoids The Object Which Have Any Reference In The Code Further. So If You Want Any Object To Never Get Collected By G.C. Until The Execution Of Your Code. Just Have A Global Reference To That Object.
I am confuse in between system.gc() and finalize() method of java.
We can't force to collect garbage object to JVM. We are allow to write both methods in our java code then if both are used for garbage collection, then what is point in providing two methods for garbage collection by java?
Please tell me the exact working of both methods and internally how it works?
System.gc() kindly asks the sytem to perform a garbage collection. Javadoc says:
Runs the garbage collector.
You can not control how "hard" the garbage collector will work. How the garbage collector work internally is VM-specific and a research topic on its own. But there are usually "full" garbage collection and some smaller "incremental" collection going on. So consider System.gc as a request, but there's not guaranteed that garbage collection of your object will happen.
Object.finalize() can be overriden to specify what to do when a given object is garbage collected (actually what to do just before it is garbage collected). Javadoc says:
Called by the garbage collector on an object when garbage collection
determines that there are no more references to the object.
Classical use of finalizer are to de-allocate system resources when an object is garbage collected, e.g. release file handles, temporary files, etc.
Do not use finalizer to perform actions when the JVM exits. For this purpose use a shutdown hook that you register with Runtime.getRuntime().addShutdownHook(Thread).
System.gc() forces the garbage collector to run, while the Finalize() method of your object defines what garbage collector should do when collecting this specific object.
Roughly speaking, it is like this:
class MyClass {
public UnmanagedResource resource;
void Finalize() {
FreeUnmanagedResource(resource);
}
}
MyClass[] data = new MyClass[1000];
for(int i=0; i<1000; i++) {
data[i] = new MyClass();
}
//do some work
data = null;
System.gc(); //Note that it doesn't guarantee you that all MyClass instances will be actually collected at this point.
system.gc() method notifies the JVM that the garbage collector can run now to clear the memory by deleting unused objects. As per the java doc:
Calling the gc method suggests that the Java Virtual Machine expend effort toward recycling unused objects in order to make the memory they currently occupy available for quick reuse. When control returns from the method call, the Java Virtual Machine has made a best effort to reclaim space from all discarded objects.
finalize() method will not trigger garbage collector instead it will be called while the garbage collector about the destroy the object. It provides the instructions to clear the object properly.
The answers here are great, just wanted to elaborate small point about the finalize() method: you should never use it.
It's execution is not guaranteed at all and eventually the usage of finalize() adds performance penalty.
As written in Effective Java by Joshua Bloch:
Finalizers are unpredictable, often dangerous, and generally
unnecessary. never do anything time-critical in a finalizer. never
depend on a finalizer to update critical persistent state.
And:
Oh, and one more thing: there is a severe performance penalty for
using finalizers. On my machine, the time to create and destroy a
simple object is about 5.6 ns. Adding a finalizer increases the time
to 2,400 ns. In other words, it is about 430 times slower to create
and destroy objects with finalizers.
Prefer using the following resource terminating try-finally pattern, which are guaranteed to run:
Bar bar = new Bar(...);
try {
// Your code here
} finally {
bar.releaseResource(); // You implementation. For example close connection
}
The System.gc() method garbage collects the objects that are created by a new keyword, whereas the finalize() method is used when we want to garbage collect the objects that are not created using a new keyword. So, I guess this ans. your Q
Garbage collection is used to reclaim the allocated memory of object and Finalize() is called by garbage collector before reclaiming the memory Finalize() method mostly used to do some operation before deleting the object
Garbage collector is invoked by calling the System.gc() method on any class. But it does not guarantees that all the nullified objects will be garbage collected before jvm shuts down. So basically gc() method is garbage collecting only those objects which are created using new keyword. Objects are created by any other logic than this will be garbage collected by explicitly calling finalize() method before gc calls the garbage collector.
There are many classes that contain the finalize() method, I'll assume you mean the one in the Object class. System.gc() is what you call when you want Java's garbage compiler to run. It will run by itself every few minutes, but you can ask it to go whenever you want. When the garbage collector runs, it calls the finalize() method on each object that has no more reference. Basically, System.gc() cleans up memory and uses finalize() to get rid of the individual objects.