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).
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.
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.
Upon new A(), we allocate sufficient amount of memory to hold all object that A contains.
Object A() may contain other objects like B() and C()
Question 1: When A() is no longer needed and you want to remove it from the heap, will setting it's reference to null do the trick? (If not, what would be the right way to signal the JVM to GC this object now?)
Question 2: If so, what happens with the instances pointing to B() and C()
Question 3: Is there a way this effect can be observed? (memory being deallocated to free up the object)
Setting A to null will mark A as a candidate to be freed by the GC. Instances of B and C will be marked too if the only references to those instances were from instance A.
Edit about question 3: A simple way to debug this effect is using the method finalize; When an object is GC´ed, his finalize is called .
However, be careful with this method: finalize is not guaranteed to be executed always (as the GC is not guaranteed to free an object) and should never be used for application´s general purposes.
There are better debugging tools depending on your IDE. For example, in eclipse: http://www.yourkit.com/docs/80/help/garbage_collection.jsp
If you have live reference to B and C then it won't GCed
at any point if any object doesn't have live reference to it, that object is ready to be GCed
class A{
B b = new B();
C c = new C();
}
now when you do
A a = new A();
a= null;//instance referred by a,b & c are ready to be collected in this system
Object A() may contain other objects like B() and C()
Objects only contain primitives and refrences to other objects.
Question 1: When A() is no longer needed and you want to remove it from the heap, will setting it's reference to null do the trick?
It is rarely needed but you can do this.
Question 2: If so, what happens with the instances pointing to B() and C()
Nothing, they are unrelated objects.
Question 3: Is there a way this effect can be observed? (memory being deallocated to free up the object)
You can override the finalize() method or use ReferenceQueues. This only informs you about collected object rather than discard objects. Its best to avoid needing to do this.
Objects which do not have a strong reference from root context e.g. thread stacks, can be collected. It doesn't matter how this happens. Setting a reference to null can allow this to happen, but more often allowing a variable to go out of scope is a simpler way to discard an object(s).
If you have Object B and it points to C which points to B and there are no other references to these objects, they will still be cleaned up even though there are references to those objects.
You cannot force GC to delete an object. GC will automatically delete any objects that are safe to be deleted. You can force GC to run by invoking System.gc(), which will delete any objects it can.
A = null will delete the object only if no other references to that object exists.
In general GC exists so you don't have to worry about deletion and memory collection. If a thing is safe to be deleted, it eventually will be.
B() and C() will be deleted if A stops pointing to them and A was the only thing pointing to them in the first place.
If you set it to null, then yes it is a signal to the GC to deallocate the memory when it needs the memory. But this will only happen if there are no more instances referencing that object.
If there are still instances referencing an object, it will not be GC-ed until there are completely NO instances referencing that object. So B() and C() will be GC-ed only if A() was the only one referencing them.
This effect can be easily observed by using Java to read a huge text file (about 3mb) with a Scanner, then closing and discarding the Scanner, and invoking System.gc() when you are done.
If you nullify all the references to A and if there are no other live references to B and C then those will be GCed too when the GC runs.
Invoking System.gc() does not guarantee that gc will run instantly. It may or may not run, there is no guarantee at all.
And There is no guaranteed way to force gc run immediately as you request it.
Yes, you can see the effect as gc runs freeing memory.
to see visual graphs/info ... about heap/memory usage, you can use jdk tools, find it for windows at:
JAVA_HOME\bin\jconsole.exe
Its a thumb of rule, that when an object has NO reference attached to it, its a toast for the Garbage collector to eat.
Marking A null will, make A a toast for the GC. If the reference pointing to A, was the only reference to B and C, then both of these are too the candidate for being Garbage Collected
finalize is the object class method, that is called when an object is Garbage Collected.
I have came across difficult (for me) Java interview question on finalize method. Suppose you have given finalize method as shown below:
public void finalize()
{
a.b = this;
}
Now the following object scenario is given.
How would you solve this problem? If A was not referring to B then this problem could be easier as GC will run, it will collect B and call finalize for B but here A is referring B so its difficult. How finalize will work in this scenario?
Any ideas? Thanks in advance
The easiest way to think of Java finalization is to consider it an extra 'bit' of state that every object with a finalizer has. When a new object is created, this isFinalized bit is set to false. When the garbage collector finds that an object with a finalizer is unreachable, it checks this isFinalized bit and only reclaims the object if it is true -- if it is false it instead runs the finalizer and sets the bit to true. Once set, there's no way for the bit to ever be cleared, so in any later time the garbage collector runs, if it's unreachable, it will be collected.
Very interesting question. From the JDK1.6 Doc, I find these two sentences:
1. The finalize method may take any action, including making this object available again to other threads
2. The finalize method is never invoked more than once by a Java virtual machine for any given object.
So in my opinion, for the first time, when B is collecting by GC, finalize method will be invoked if A is still available to some threads then B becomes available again, this time the GC will not collect B. But because finalize method will be invoked only once, so next time when the GC find B can't be accessed by any thread then GC will collect B.
It is not entirely clear what you are asking.
However, the JLS 12.6.2 states that the order in which objects are finalized is not specified. This means that the finalize methods for all finalizable classes should be designed to work when invoked in any order.
Note that this applies equally to unreachable and finalizer-reachable objects. In other words, the 3 objects in your diagram could be finalized in any order.
... how B will be garbage collected as A is reachable and how finalize will get called for B?
Perhaps it is a trick question. If A is reachable, then B is also reachable, so it won't be garbage collected, and its finalize method won't be called. If A becomes unreachable then so does B, and both will be finalized.
What that finalize method will actually do depends on what class it belongs to. Lets assume it is a method of the "guaranteed reachable object", and the a variable contains a reference to A:
The finalize method won't be called by the GC because the object is reachable.
Some other code could explicitly call that finalize method. If that happened, then a.b will no longer refer to B, and B will be unreachable and eligible for eventual garbage collection, finalization and (ultimately) deletion.
Sorry if I am wrong. But to me, B is a field of A, so A definitely need to keep a reference to B, and while A "always-live" object holding a reference to A, both A and B will not be GC and the problem to GC B is just not making any sense.
This is a quesiton taken from a java exam,
How many objects are eligible for gabage collection at #1 ?
public class Main {
Integer x = 32768;
public static void main(String[] args)
{
Main m = new Main();
m = null;
// #1
}
}
I thought it just collect Integer x, does GC even collect the Main object m?
Yes, it does collect Main object. Since integer is neither a separate object by itself (it's a member of Main) not a pointer it won't be collected separately but only as a part of Main.
Two objects may be deleted by the garbage collector.
The object assigned to m is not reachable any more, nor is the Integer inside Main.
Edit: You can ask yourself: "Is it possible that I access the object in some way at this point?" If the answere is "No", the garbage collector may delete it.
One bit of confusion you may be having is that the main method can be called without there even being a main object in existence. That is because it is a static method. Similarly, the "Integer x" only exists as a field in a main object. So when you create a new Main object m you also create the integer m.x as part of m. Then when you set m to null the object that was previously referred to by m is garbage and can be collected.
Now, when will it be collected is a totally different question. There are really are no guarantees; however, since its use was so localized it will almost certainly be taken care of at the next minor collection/scavenge/pick-your-favorite'-terminology.
It could. There is no reference to it anymore, so it is eligible for garbage collection.
The instance of Main is eligible for garbage collection and normally the Integer will also be eligible. But the Integer instance can also be cached by the Integer class if configured to do so (see this answer).
Normally only integers between -128 and 127 are cached when using Integer#valueOf(int) (used for autoboxing) but the upper limit can be increased by setting the system property java.lang.Integer.IntegerCache.high
My observations using a recent OpenJDK have shown that only once a method exits do any references it orphaned actually get collected. I did not expect this at all, but it's what happened. Extracting those lines of code into another method, which would then return back to main(), did allow the instance to be collected.
I think this is a dumb question. (EDIT: I mean the exam question! Not insulting the submitter!) It's all in how you define "eligible". In my case, I'd say once there were no references left, the instance was eligible to be collected, it's just that it never would actually be collected until sometime after the method returns.