How to prevent an object from getting garbage collected?
Are there any approaches by finalize or phantom reference or any other approaches?
I was asked this
If there is still a reference to the object, it won't get garbage collected. If there aren't any references to it, you shouldn't care.
In other words - the garbage collector only collects garbage. Let it do its job.
I wonder if what they're going for is the pattern with resource pools (e.g. for network/db connections, or threads) where you use finalize to return a resource to the pool so that the actual object holding the resource isn't GC'ed.
Stupid example, in Java-like pseudocode and missing any kind of synchronization:
class SlowResourceInternal {
private final SlowResourcePool parent;
<some instance data>
returnToPool() {
parent.add(this);
}
}
class SlowResourceHolder {
private final SlowResourceInternal impl;
<delegate actual stuff to the internal object>
finalize() {
if (impl != null) impl.returnToPool();
}
}
Hold a reference. If your object is getting collected prematurely, it is a symptom that you have a bug in the design of your application.
The garbage collector collects only objects to which there is no reference in your application. If there is no object that would naturally reference the collected object, ask yourself why it should be kept alive.
One usecase in which you typically have no references, but want to keep an object is a singleton. In this case, you could use a static variable. One possible implementation of a singleton would look like this:
public class Singleton {
private static Singleton uniqueInstance;
private Singleton() {
}
public static synchronized Singleton getInstance() {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqInstance;
}
}
Edit: Technically, you can store a reference somewhere in your finalizer. This will prevent the object from being collected until the collector determines again that there are no more references. The finalizer will only be called at most once, however, so you must ensure that your object (including its superclasses) need not be finalized after the first collection. I would advise you, however, not to use this technique in actual programs. (It will leave colleagues like me yelling WTF!? ;)
protected void finalize() throws Throwable {
MyObjectStore.getInstance().store(this);
super.finalize(); // questionable, but you should ensure calling it somewhere.
}
I suspect what you might be referring to is if your finalize
method stashes away a reference to the object being finalized. In this case (if my reading of the Java Language Spec is correct) the finalize
method will never be re-run, but the object will not yet be garbage collected.
This is not the sort of thing one does in real life, except possibly by accident!
We have three ways to achieve same - 1) Increasing the Heap -Eden space size . 2) Create Singleton class with Static reference . 3) Override finalize() method and never let that object dereference.
The key point is if we set the real reference variable pointing to the object null,although we have instance variables of that class pointing to that object not set to null. The object is automatically eligible for garbage collection.if save the object to GC, use this code...
public class GcTest {
public int id;
public String name;
private static GcTest gcTest=null;
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("In finalize method.");
System.out.println("In finalize :ID :"+this.id);
System.out.println("In finalize :ID :"+this.name);
gcTest=this;
}
public static void main(String[] args) {
GcTest myGcTest=new GcTest();
myGcTest.id=1001;
myGcTest.name="Praveen";
myGcTest=null;
// requesting Garbage Collector to execute.
// internally GC uses Mark and Sweep algorithm to clear heap memory.
// gc() is a native method in RunTime class.
System.gc(); // or Runtime.getRuntime().gc();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("\n------- After called GC () ---------\n");
System.out.println("Id :"+gcTest.id);
System.out.println("Name :"+gcTest.name);
}
}
Output :
In finalize method.
In finalize :ID :1001
In finalize :ID :Praveen
------- After called GC () --------
Id :1001
Name :Praveen