Garbage collection when final variables used in anonymous classes - java

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.

Related

Java WeakReference is still holding valid reference when referent is no longer valid

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.

Does JVM garbage collect objects being referenced by local variables which are no longer used? [duplicate]

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.

When does this object become eligible for garbage collection?

I have this piece of code, and I am confused about when the Object o becomes eligible for garbage collection in Java.
public class JustSo
{
public static void main(String[] args)
{
for(int i=0;i<4;i++)
{
Object o=new Object();
//o.doSomething();
}
System.out.println("DONE");
}
}
Since it is inside a loop(or any block for that matter), it will become eligible at the end of the loop right?
But I found an answer on a reliable developer site(Don't want to disclose where) that says the earliest the object becomes eligible is at the print statement.
Please clarify.
When it becomes out of scope, so after each iteration of the for loop. An object is eligible for garbage collection when it is no longer reachable, this occurs in 2 situations.
The object no longer has any references point to it.
All references to the object have gone out of scope.
The latter is the situation for the object in question, and it the object's reference is out of scope after the for loop. Prior to the print statement.
As the oracle documentation about the garbagecollector says:
Automatic garbage collection is the process of looking at heap memory, identifying which objects are in use and which are not, and deleting the unused objects. An in use object, or a referenced object, means that some part of your program still maintains a pointer to that object. An unused object, or unreferenced object, is no longer referenced by any part of your program. So the memory used by an unreferenced object can be reclaimed.
This means as soon as an Object isn't referenced from any other Object or is out of scope, it will be marked for deletion. In this case, the reference is out of scope, each time the loop starts again (just before every increment). Thus each object will be marked for deletion at the end of the loop (before the next loop-repetition).
Since you are not saving the reference into some outer-scope variable,and creating new instance each time as soon as single iteration complete, its eligible for garbage collection.
So when you came out of loop, all the objects created inside eligible for GC.
May be you confused with author wording here. Consider below code
for(int i=0;i<4;i++)
{
Object o=new Object();
//o.doSomething();
} -----> objects ready for GC here.
// some other code
// some other code
System.out.println("DONE");
Each time around the loop, around the time when i++ happens, the object will become eligible for GC.

this code could garbage collecting?

I have some question about Java garbage collection.
Below is the code of some test class
public class ChildMaker{
public Child createChild(){
Child c = new Child();
return c;
}
}
And the actual test I'm performing
public class TestChildMaker{
public getChild(){
ChildMaker maker = new ChildMaker();
Child c = maker.createChild();
....
}
}
I wonder if the ChildMakerinstance can be garbage collected. Can it ?
The Java garbage collector is sophisticated, and likes to work fairly autonomously. You can't force it to garbage collect anything, and you can only give it an indication of when it might like to garbage collect.
Any object to which a reference is still held in your program (strictly: by any thread that could still run) cannot be garbage collected. Anything else could be.
I think you're asking whether the ChildMaker instance can be garbage collected while the Child is still referenced. Strictly speaking such a position does not exist in the code that you provided. The answer is yes; if the ChildMaker is unreferenced then it can be garbage collected even if the Child is still referenced, because the Child does not hold a reference to the ChildMaker.
The answer depends on what happens
public getChild(){
ChildMaker maker = new ChildMaker();
Child c = maker.createChild();
.... // here <--------
}
If the variable maker is reused, the object it references is reachable and can therefore not be garbage collected. If maker is not reused, then the object is no longer reachable and can therefore be garbage collected.
The Java Language Specification states
A reachable object is any object that can be accessed in any potential
continuing computation from any live thread.

In Java, when does an object become unreachable?

In Java, what is an unreachable object? When does the object become unreachable? While studying garbage collection I was not able to understand this concept.
Can anyone give any ideas with examples?
When there are no longer any reference variables referring to it, OR when it is orphaned in an island.
An island being an object that has a reference variable pointing to it, however that object has no reference variables pointing to it.
class A { int i = 5; }
class B { A a = new A(); }
class C {
B b;
public static void main(String args[]) {
C c = new C();
c.b = new B();
// instance of A, B, and C created
c.b = null;
// instance of B and A eligible to be garbage collected.
}
EDIT: Just want to point out that even though the instance of A has a reference, it is on an island now because the instance of B does not have a reference to it. The A instance is eligible for garbage collection.
An object is unrechable when there are no more references to it, or those references are themselves from unrechable objects.
Integer i = new Integer(4);
// the new Integer object is reachable via the reference in 'i'
i = null;
// the Integer object is no longer reachable.
in the object graph when one is not linked to it, then the reference become unreachable. then then the garbage collector scans for these dangling orphan objects and swipe out regaining allocated memory.
java.lang.ref.{Phantom,Soft,Weak} Reference Enqueues unreachable objects.
If the finalizer is run, the GC already knows its unreachable.
read about finalization- http://java.sun.com/developer/technicalArticles/javase/finalization/
In a language which has only strong references, heap objects can either be reachable or unreachable from the
program. The set of reachable objects is determined by the set of class variables and method variables in the program
pointing to heap objects. This set is usually referred to as the root set of the program. An object pointed by a variable
in the root set of the program is reachable. In addition, an object might be indirectly reachable. That is, an object is
reachable if there is another reachable object pointing to it. Such chain of references from the root set of the program
to a heap object is called reachability path. An object may have more than one reachability path to it as well as have
no reachability paths at all. If the object has no reachability paths it is deemed garbage and can be immediately
collected by the garbage collector.
An object enters an unreachable state when no more strong references to it exist. When an object is unreachable, it is a candidate for collection. Note the wording: Just because an object is a candidate for collection doesn't mean it will be immediately collected. The JVM is free to delay collection until there is an immediate need for the memory being consumed by the object.
It's important to note that not just any strong reference will hold an object in memory. These must be references that chain from a garbage collection root. GC roots are a special class of variable that includes
Temporary variables on the stack (of any thread)
Static variables (from any class)
Special references from JNI native code
more if you like to http://java.sun.com/docs/books/performance/1st_edition/html/JPAppGC.fm.html
An unreachable object, is an object that doesn't have a "reachable" reference to it.
In other words, no references to it.

Categories

Resources