How to avoid object collection by garbage collector - java

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.

Related

Java - HashMap and WeakHashMap references used in Application

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.

Delete complex objects at runtime in Java

In Java, at some point in code I want to free memory taken by a huge HashMap<Integer, ArrayList<Integer>> object. Is it enough to point it to null like below:
Map<Integer, ArrayList<Integer>> complexObject = new HashMap<Integer, ArrayList<Integer>>(1000000);
...
complexObject = null;
?
You cannot explicitly de-allocate Java objects. But you can do the following:
Remove all references to the item you no longer need. You can do this by setting your only reference to an object to null.
Call System.gc() to "suggest" to the JVM to run the garbage collector, which deallocates no-longer used objects, although it's not guaranteed that calling this method will actually run the garbage collector.
Setting its reference to null will mark it available to the garbage collector next time it decides to run if there are indeed no more references to said object laying around anywhere. When the GC decides to run however, is not set in stone.
This is a big point where Java is different from C, but don't worry. 99.9% of the time you can trust the GC has your back.
There is no guarantee of freeing memory. GC will run and pickup nulls so that's all you can do yes.
I just read this article, there is something about freeing memory in it, too.
Check it out, nulling does not always help you.

What if a finalizer makes an object reachable?

In Java, finalize is called on an object (that overrides it) when it's about to be garbage collectioned, so when it's unreachable. But what if the finalizer makes the object reachable again, what happens then?
Then the object doesn't get garbage collected, basically. This is called object resurrection. Perform a search for that term, and you should get a bunch of interesting articles. As Jim mentioned, one important point is that the finalizer will only be run once.
The object will not be collected until it gets unreachable again.
According to the JavaDoc, finalize() will not be called again.
If you read the API description carefully, you'll see that the finalizer can make the object reachable again. The object won't be discarded until it is unreachable (again), but finalize() won't be called more than once.
Yeah, this is why you don't use finalizers (Well, one of the many reasons).
There is a reference collection that is made to do this stuff. I'll look it up and post it here in a sec, but I think it's PhantomReference.
Yep, PhantomReference:
Phantom reference objects, which are enqueued after the collector determines that their referents may otherwise be reclaimed. Phantom references are most often used for scheduling pre-mortem cleanup actions in a more flexible way than is possible with the Java finalization mechanism.
It actually does another pass to check and make sure there are no more references to the object. Since it will fail that test on its second pass, you'll end up not freeing the memory for the object.
Because finalize is only called a single time for any given object, the next time through when it has no references, it will just free the memory without calling finalize. Some good information here on finalization.

ways of making an object to explicitly garbage collected

I have read about making an object explicitly garbage collected, that in many ways. So i wanted to know some of the methods of making it explicitly garbage collected
There is no way for explicit garbage collection.
You can "politely ask" the virtual machine to do garbage collection by calling:
System.gc();
but it is not guaranteed it will.
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.
and "best effort" might be to postpone the garbage collection.
For how to make objects elligible for garbage collection read Effective Java, Chapter 2
You can explicitly make an object eligible for garbage collection by setting all references to it to null.
This won't call the garbage collector itself, but when the collection does start, it will collect this object.
You're best off letting the Java garbage collector doing it all automatically by itself. It has been optimized to the point where it'll be better and more efficient than anything you'd ever want to probably do.
System.gc is to tell the JVM to execute the garbage collector explicitly.
But as for as some methods which i know to make an object explicitly garbage collected are:
Assigning its reference to point to null
EX: Animal a = new Animal();
a = null
Assigning its reference to point to another object.
EX: Animal a1 = new Animal();
a1 = new Animal();
You shouldn't worry about forcing a GC unless you're writing, say, a tool like VisualVM yourself.
NetBeans, IntelliJ, VisualVM, and a great many others can all force a GC, not hint, but really force. Using JVMTI you can force a GC.
BUT once again you probably do NOT want to do that.
You force a GC (not hint) using JVMTI's ForceGarbageCollection.
That said, you probably really DO NOT want to do that (it really bares repeating).
Authoritative info on the subject if you really want to know (but you probably don't) how to force, for a fact, a GC:
http://java.sun.com/javase/6/docs/platform/jvmti/jvmti.html#ForceGarbageCollection

Which is a better way to force GC on ThreadLocal instance?

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.

Categories