For example
public void doSomething() {
Dog smallDog = new Dog();
smallDog.bark();
}
will the dog object be collected after this method is run?
It can become eligible to be collected when the method returns. When garbage collection actually happens is some unknown time in the future.
It is impossible to tell for sure without seeing the implementation of bark().
If this is your bark:
public void bark() {
BarkListeners.callBack(this);
}
public class BarkListeners {
private static final List<Dog> barkers = new ArrayList<Dog>();
public static void callBack(Dog dog) {
barkers.add(dog);
}
}
Then no, it won't be getting garbage collected!
Simply no. I mean, the timing does not have to be like that.
All Java Objects are allocated in the heap and collected by the GarbageCollector. And GarbageCollector runs in background, with almost no constraint on when to perform actual garbage collection.
Technically, it isn't possible to give and answer because we haven't seen the implementation for Dog#bark().
Generally, the answer is YES, the Dog instance will be collected AFTER the method is run, it just isn't possible to know exactly when. The reason for this is that unless the bark method shares the reference to the Dog object with another object, the particular instance of Dog will no longer be reachable. The next time the Garbage Collector runs, it will determine that Dog is not reachable and collect the heap space that was used to keep it.
It depend on reach ability of the object. If object is not reachable then it is eligilble for GC. When to GC is dependent on JVM implementation. Truth About Garbage Collection
This blog post provides a good explanation on how the garbage collection process works. To summarize:
An Object becomes eligible for Garbage collection if its not reachable from any live threads or any static refrences. It (the Garbage Collector) will only trigger if JVM thinks it needs a garbage collection based on Java heap size.
Therefore you shouldn't make assumptions on when any object will be garbage collected.
Related
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.
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.
Suppose you have an instance a of Class A. Is it possible to create an instance b of class B, such that when a is garbage collected b will be garbage collected?
I know can cheat and create a reference to a in b, so a has to wait for b or something. What I want is for instance b to be deleted when a would naturally be deleted.
No. You can never force any object to be garbage collected. That's rather the point of garbage collection.
However, if the only reference to b is from a, then it is very likely that when the collector collects a, it will also collect b.
But to be honest, if you're worrying about when objects will be collected, the chances are you've doing it wrong. There should be no difference between dead and deleted objects as far as your program is concerned. Do you have a specific use for this that you would like to discuss?
As you might know, we cannot force GC to work according to our wish.
But the first thought which can to mind was if A contains the instance of B, then naturally when a is GCed, b will be, too. This is just one scenario which came to my mind. I don't how you actually want to do it.
You can also use weak references.
Usually, you can't even be sure when a object is collected (even System.gc() does not ensure that all unreferenced objects are collected) it is up to the garbage collection algorithm to decide if an unreferenced object is collected.
There are several GC strategies (you can set it when starting the JVM), your only option is to chose one that is exhaustive so it ensures that all unreferenced objects are collected(*). Then you'll have to be sure that both a and b get unreferenced at the same time (and that the gc is not called in between -I do not know of any way to ensure that-).
(*) Don't know if such algorithm does even exist. But if it does I am pretty sure it will have a heavy impact in performance.
Yes it is possible, if the instance of B is inside class A, it will get garbage collected automatically when A is destroyed. This example can be implemented this way:
public class A {
` B b;
public A(B b) {
this.b =b;
}
}
public class Test() {
public static void main(String [] args) {
A a = new A();
}
}
When a goes out of scope, both a and b will get garbage collected(object b inside a will be garbage collected first).
I don't think you can call garbage collector for an specific object, it works automatically as needed(You cant force that). You can try to invoke it this way:
Runtime r = Runtime.getRuntime();
r.gc();
It is not guaranted that the objects will be garbage callected when you execute the above code(Maybe the garbage collector is bussy)
There are no events fired when an object is finalized, except a (non-guaranteed) call to obj.finalize().
You may place some code to finalize() of A. If you can somehow deduct the object B based on object A data (but not keeping an actual reference), you may at this point remove B from a global static Set, making it eligible for GC (not necessary at the same GC run though).