The following snippet from RuntimeUtil.java from jlibs guarantees GC that garbage collection is done.
Since, it also uses System.gc(), i dont understand how can they guarantee that it will happen 100% of the times.
Following is the snippet:
/**
* 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();
}
Its related with Strong Reference & Weak Reference with respect to Garbae Collection.
A strong reference is an ordinary Java reference, the kind you use every day.
If an object is reachable via a chain of strong references (strongly reachable), it is not eligible for garbage collection. As you don't want the garbage collector destroying objects you're working on, this is normally exactly what you want.
A weak reference, simply put, is a reference that isn't strong enough to force an object to remain in memory. Weak references allow you to leverage the garbage collector's ability to determine reachability
The gc() method in the pointed class works on this concept.
/**
* 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();
}
Once a WeakReference starts returning null, the object it pointed to has become garbage and the WeakReference object is pretty much useless. This generally means that some sort of cleanup is required;
That's why they guarantee that it will happen 100% of the times.
From what I can see it should work as they
1) create an object
2) get a "weak" reference to it
3) null the reference to it, in order to mark it for garbage collection
4) and wait with the while loop until it actually disappears
A single call to System.gc() does not guarantee all objects that are eligible for garbage collection are re-claimed. See How to cause soft references to be cleared in Java?
In this case, the garbage collection is run many times till a an weak object ref is returning null. I doubt efficacy of this approach. There will be many other objects that may be garbage collected. To me it (jlib) does not have any thing to learn from.
For example the code in the library written in 2009. (extracted)
/**
* This method guarantees that garbage colleciton is
* done after JVM shutdown is initialized
*/
public static void gcOnExit(){
Runtime.getRuntime().addShutdownHook(new Thread(){
#Override
public void run(){
gc();
}
});
}
Why to you need gc when shutdown is called? The library quoted in question is pure garbage.
Related
I'm confused with this program:
class Point {
private final int x;
private final int y;
}
public class App
{
WeakReference<Point> newPoint() {
Point referent = new Point();
return new WeakReference<Point>(referent); // after return, stack parameter referent is invalid.
}
public static void main( String[] args ) {
App a = new App();
WeakReference<Point> wp = a.newPoint(); // wp is hold valid or invalid reference?
System.out.println(wp.get()); // not null
}
}
I knew that if weak reference is pointing to an object that's no longer alive, its get() should return null. But in my code, seems its still alive.
Where did I get wrong?
I knew that if weak reference is pointing to an object that's no longer alive, its get() should return null. But in my code, seems its still alive.
Your understanding is imprecise, especially where it relies on the idea of aliveness. Reference objects in general and WeakReference objects in particular are not directly concerned with any of the senses of aliveness that I recognize. Rather, they are concerned with reachability.
The API docs for java.lang.Reference#get() (which is not overridden by WeakReference) say this:
Returns this reference object's referent. If this reference object has been cleared, either by the program or by the garbage collector, then this method returns null.
Note well that the condition for get() returning null is rather specific: the reference object has been cleared. This is achieved for a given instance by invoking that instance's clear() method. As the doc indicates, this may be done by the garbage collector or by the application.
Among the key differences between Reference subclasses is the conditions under which the garbage collector will perform such clearing. For WeakReferences, the API docs say:
Suppose that the garbage collector determines at a certain point in time that an object is weakly reachable. At that time it will atomically clear all weak references to that object [...].
Thus, until the garbage collector determines that a given object is (only) weakly reachable, it will not clear weak references to that object. The garbage collector probably does not run at all during the brief run of your small program, and if it did run, it would be surprising for it to be timed correctly to observe the Point in question to be weakly reachable before the reference's get() method is invoked.
You could try forcing a GC run by invoking System.gc() at the appropriate place. I anticipate that doing so will result in the weak reference being cleared. That would be for demonstrative purposes only, however. Generally speaking, you should rely on Java to perform GC when appropriate, not force it.
This question already has answers here:
Can java finalize an object when it is still in scope?
(2 answers)
Closed 3 years ago.
As far as I know, a method's local variable is located in a stack frame in an executing thread and a reference type of a local variable only has a objects' reference, not the object itself. All of objects in JVM are located in a heap space.
I want to know that objects referenced by local variables in a method being executed are never garbage collected until the end of the method execution. (without using java.lang.ref.WeakReference and SoftReference.)
Are they garbage collected? or never? Is there compiler's optimization to this type of stuff?
(If they are never garbage collected, this means it may be needed to assign null to variables no longer used when executing big methods which take long time.)
As elaborated in Can java finalize an object when it is still in scope?, local variables do not prevent the garbage collection of referenced objects. Or, as this answer puts it, scope is a only a language concept, irrelevant to the garbage collector.
I’ll cite the relevant part of the specification, JLS §12.6.1 again:
A reachable object is any object that can be accessed in any potential continuing computation from any live thread.
Further, I extended the answer’s example to
class A {
static volatile boolean finalized;
Object b = new Object() {
#Override protected void finalize() {
System.out.println(this + " was finalized!");
finalized = true;
}
#Override public String toString() {
return "B#"+Integer.toHexString(hashCode());
}
};
#Override protected void finalize() {
System.out.println(this + " was finalized!");
}
#Override public String toString() {
return super.toString() + " with "+b;
}
public static void main(String[] args) {
A a = new A();
System.out.println("Created " + a);
for(int i = 0; !finalized; i++) {
if (i % 1_000_000 == 0)
System.gc();
}
System.out.println("finalized");
}
}
Created A#59a6e353 with B#6aaa5eb0
B#6aaa5eb0 was finalized!
finalized
A#59a6e353 with B#6aaa5eb0 was finalized!
which demonstrates that even the method with the variable in scope may detect the finalization of the referenced object. Further, being referenced from a heap variable doesn’t necessarily prevent the garbage collection either, as the B object is unreachable, as no continuing computation can access it when the object containing the reference is unreachable too.
It’s worth emphasizing that even using the object does not always prevent its garbage collection. What matters, is whether the object’s memory is needed for the ongoing operation(s) and not every access to an object’s field in source code has to lead to an actual memory access at runtime. The specification states:
Optimizing transformations of a program can be designed that reduce the number of objects that are reachable to be less than those which would naively be considered reachable. […]
Another example of this occurs if the values in an object's fields are stored in registers. The program may then access the registers instead of the object, and never access the object again. This would imply that the object is garbage.
This is not only a theoretical option. As discussed in finalize() called on strongly reachable object in Java 8, it may even happen to objects while a method is invoked on them, or in other words, the this reference may get garbage collected while an instance method is still executing.
The only ways to prevent an objects garbage collection for sure, are synchronization on the object if the finalizer also does synchronization on the object or calling Reference.reachabilityFence(object), a method added in Java 9. The late addition of the fence method demonstrates the impact of the optimizers getting better from version to version on the issue of earlier-than-wanted garbage collection. Of course, the preferred solution is to write code that does not depend on the time of garbage collection at all.
It is not quite true that all of the objects are in heap space; but it is generally true. Java has been extended to have stack-local objects, provided the JVM can detect that the object will live only as long as the stack frame.
Now for the objects on the heap, which have a local reference in a method. While the method is being processed, the stack frame associated with the method run contains the local variable references. As long as the reference can be used (which includes being still in the stack frame) the object will not be garbage collected.
Once the reference has been destroyed, and the object can no longer be reached by the running program (because there's no references that can reach it), then the garbage collector will collect it.
This question already has answers here:
When is the finalize() method called in Java?
(18 answers)
Closed 8 years ago.
Why execution of finalize() isn't guaranteed at all in Java? Is finalize() method shouldn't be used???
Consider below program.
class Test{
protected void finalize()
{
System.out.println("Will i execute?");
}
public static void main(String args[])
{
Test t=new Test();
}
}
There is an empty output when this program runs. We know that finalize() is used to cleanup any external resources before the object becomes eligible for garbage collection & finalize() will be called by JVM. Inside finalize() we will specify those actions that must be performed before an object is destroyed. Is finalize() method evil??
Javadoc link, because many quotes will follow.
We know that finalize() is used to cleanup any external resources before the object becomes eligible for garbage collection
No. Once the object becomes eligible for garbage collection, then finalize() can get invoked. finalize could theoretically make the object no longer eligible for garbage collection and the garbage collector would then skip it. As stated
After the finalize method has been invoked for an object, no further
action is taken until the Java virtual machine has again determined
that there is no longer any means by which this object can be accessed
by any thread that has not yet died
Why execution of finalize() isn't guaranteed at all in Java?
It is guaranteed to run. As the Javadoc states
The general contract of finalize is that it is invoked if and when the
Java™ virtual machine has determined that there is no longer any means
by which this object can be accessed by any thread that has not yet
died, except as a result of an action taken by the finalization of
some other object or class which is ready to be finalized.
What isn't guaranteed is when or if garbage collection will occur.
Should i use finalize() or not in java?
That depends on your use case. Start by reading the javadoc and understand the implications.
finalize() is Called by the garbage collector on an object when garbage collection determines that there are no more references to the object. .
You could use System.gc() to explicitly call for garbage collection and check if your statement gets printed.
But the JVM has the liberty to ignore your request (depends on the JVM implementation actually..). Only when the JVM's internal state tells it that there is too much garbage and it needs to be collected, then it will run GC (and the line will I execute) will be printed.
If I understand your question, you can use the System.gc() to request garbage collection with something like this,
#Override
protected void finalize() {
System.out.println("I will execute.");
}
public static void main(String args[]) {
Test t = new Test();
t = null; // <-- make it eligible for gc.
System.gc(); // <-- request gc.
System.runFinalization(); // <-- run finalization(s).
System.out.println("Exit"); // <-- exit.
}
Depending on your JVM, you might find the order of output swaps if you comment out System.runFinalization(); -
public static void main(String args[]) {
Test t = new Test();
t = null; // <-- make it eligible for gc.
System.gc(); // <-- request gc.
// System.runFinalization(); // <-- run finalization(s).
System.out.println("Exit"); // <-- exit.
}
Before removing an object from memory Garbage collection thread invokes finalize () method of that object and gives an opportunity to perform any sort of cleanup operations.
Generally an object becomes eligible for garbage collection in Java on following cases:
All references of that object explicitly set to null e.g. object = null.
Object is created inside a block and reference goes out scope once control exit that block.
Parent object set to null, if an object holds reference of another object and when you set container object's reference null, child or contained object automatically becomes eligible for garbage collection.
If an object has only live references via WeakHashMap it will be eligible for garbage collection.
public Test(){
System.out.println("Object created");
}
protected void finalize(){
System.out.println("Will i execute?");
}
public static void main(String args[]){
Test test = new Test();
test = null;
new Test();
System.gc();
}
finalize() of any particular class is called by jvm just before collecting the object of that class as a garbage.
Now next question is when an object of a class is collected as garbage?
Answer is:
When there is no more objects reference to that object or simply no more object reference is pointing to that allocated memory space or an object has only live references via WeakHashMap it will be eligible for garbage collection.
Read more here.
As an option we can use System.gc() or Runtime.gc() that will give a request to jvm to consider the garbage collection. But whether your request will be listened or ignored by jvm that depends upon following factors:
Internal implementation of JVM & its Garbage Collection algorithm
Java Heap size
Free memory available in Heap
When does the object of type list, occupying memory, become eligible for garbage collection, Also where is the variable that holds reference to the list ? In the case of code below, there was no variable assigned to it.
CASE 1:
for (Integer i : returnList()) {
System.out.println(i);
}
In case of a code like:
CASE 2:
List list = returnList();
for (Integer i : list) {
System.out.println(i);
}
list = null;
We can take control of GC, Is there any ways to take care of that in the first case when no variable was assigned ?
To summarize:
What is the mechanism of referrence, without a reference variable to list is case 1?
Does list get eligible for GC'd when stack frame is popped ?
Any way to speed up the eligibility for GC'ing ?
What is the mechanism of referrence, without a reference variable to list is case 1?
There is an implicit reference to the list. This can be seen by understanding that enhanced for like that is translated into:
for(Iterator e = returnList().iterator(); e.hasNext(); ) {
Integer i = (Integer)e.Next();
System.out.println(i);
}
Here, e has a reference to an iterator on returnList, which itself has a reference to returnList. Thus, returnList is rooted as long as e is rooted which is only true while control is in the for loop. When control leaves the for body, e is eligible for collection, so returnList is eligible for collection.
Of course, all of this is assuming that
The owner of returnList isn't maintaining a reference to its return value.
The same list hasn't been returned to another caller and that other caller isn't maintaining a reference to the same list.
Does list get GC'd when stack frame is popped ?
Not necessarily. It will be eligible for collection when the JVM can determine that the referrent has no rooted references to it. Note that it does not necessarily immediately get collected.
Any way to speed up GC in case 1.
It can't be collected any sooner than control leaving the for loop. It might be collected after control leaves the for loop. Let the JVM worry about this.
Note that you can attempt a manual garbage collection via
System.gc();
but note that this might exhibit worse behavior because if it triggers a garbage collection, it might be a full garbage collection. Note that the JVM can ignore this request. You might be wasting a lot of CPU cycles here. Note that on a system with infinite memory, the garbage collector never needs to run. On such a system, requesting the garbage collector could be a complete waste of CPU cycles if the garbage collector obeys your request.
Let the JVM manage the garbage collections. The algorithms for it are highly tuned.
From SCJP page 256-257
The garbage collector does some magical, unknown operations, and when
it discovers an object that can't be reached by any live thread,it
will consider that object as eligible for deletion, and it might even
delete it at some point. (You guessed it; it also might not ever
delete it.) When we talk about reaching an object, we're really
talking about having a reachable reference variable that refers to the
object in question. If our Java program has a reference variable that
refers to an object, and that reference variable is available to a
live thread, then that object is considered reachable.
Setting an object to NULL might help to fasten when the GC deletes the object but it might as well not, you don't have control over that. The JVM will run GC when it senses that memory is running low and you can manually ask it to do so but nothing is guaranteed.
What is the mechanism of reference, without a reference variable to
list is case 1?
see next answer.
Does list get GC'd when stack frame is popped ?
The list is created on the heap - but if the only reference to it was on the stack it is eligible to be collected by GC. That doesn't mean that it'll happen any time soon though.
Any way to speed up GC in case 1.
You can't "speed up" GC, even by calling System.gc(); you're only "suggesting" that the GC can to do its work - again, it won't necessarily happen any time soon.
There's a lot of sense behind it too: say that your program has 2GB of memory to use and is currently using only 2KB - it does not justify GC stopping your program from running and clean the memory only because some objects are eligible for deletion.
You cannot take control of GC.It is managed by JVM. What you can manage is what objects should be available for garbage collection. Although , you can find out when garbage collector will run using finalize method. It is always called before an object is deleted
public class Demo{
static void create()
{
Demo o = new Demo();
}
public void finalize()
{
System.out.println("GC called");
}
public static void main (String ...ar)
{
for (long i=1;i<900000;i++) //Try changing values here
{
create();
}
}
}
Objects created inside the methods are available for GC when method is returned(just like local variables exist for duration of method).However if the method returns an object, it will not be avialble for garbage collection
public class Demo{
public void getDate()
{
Date o = new Date();
StringBuffer d = new StringBuffer(o.toString());
System.out.println(d);
return o;
}
public static void main (String ...ar)
{
Date x= getDate();
}
}
In the above code, object d is available for GC when the method returns. But object o will not be available for collection
If I have code similar to the following:
public Constructor(final Object o) {
taskSystem.add(new CycleTask(15, 15, -1) {
#Override
public void execute() throws Throwable {
//access o here every 15 cycles forever
}
});
}
When would o be garbage collected, if ever? Only when the task has been collected, or will it remain in memory forever because it's final?
o might get garbage collected once it is not reachable any longer, whether it is final or not. Obviously, as long as execute is running, if it needs to access o, it will prevent GC.
When execute is done running, and assuming you have not stored any references to o (for example in a collection), it will be flagged as ready for garbage collection.
When the anonymous class instance becomes eligible for garbage collection, if nothing else refers to the object that o referred to when the method was called, that object will become eligible for garbage collection.
There's nothing special about final variables which deters garbage collection.
'final' has no effect on GC. The object will become eligible for collection when it becomes unreachable. In this case there are at least three references, any one of which can stop that: the 'final' parameter, which disappears when the method returns; the caller's reference; and the copy of the final variable in the anonymous class instance.
There is no relationship between final keyword and the lifetime of the variable.
It will be garbage collected when not needed anymore, and since it's a parameter this can happen just outside the method (if there is no reference outside).
The final keyword is just a constraint given to the compiler to forbid any further modification of the reference o after the call of the function.