How Does Java Garbage Collector Handle Self-Reference

How does Java Garbage collector handle self-reference?

Garbage collectors which rely solely on reference counting are generally vulnerable to failing to collection self-referential structures such as this. These GCs rely on a count of the number of references to the object in order to calculate whether a given object is reachable.

Non-reference counting approaches apply a more comprehensive reachability test to determine whether an object is eligible to be collected. These systems define an object (or set of objects) which are always assumed to be reachable. Any object for which references are available from this object graph is considered ineligible for collection. Any object not directly accessible from this object is not. Thus, cycles do not end up affecting reachability, and can be collected.

See also, the Wikipedia page on tracing garbage collectors.

How does Java Garbage Collection work with Circular References?

Java's GC considers objects "garbage" if they aren't reachable through a chain starting at a garbage collection root, so these objects will be collected. Even though objects may point to each other to form a cycle, they're still garbage if they're cut off from the root.

See the section on unreachable objects in Appendix A: The Truth About Garbage Collection in Java Platform Performance: Strategies and Tactics for the gory details.

Garbage collection behavior with isolated cyclic references?

Yes, they are. Basically the GC walks from "known roots" (static variables, local variables from all stack frames in alll threads) to find objects which can't be garbage collected. If there's no way of getting to an object from a root, it's eligible for collection.

EDIT: Tom pointed this out, which I thought was worth lifting into the answer itself:

Technically, static variables are not
roots - they are referenced by classes
which are referenced by class loaders
which are referenced by classes which
are referenced by object which are
referenced by root references.

The difference is likely to be irrelevant most of the time, but it's good to know :)

Object deletes reference to self

No, there isn't any such race condition. You are clearing the reference, so the ref count drops to 1 and the object will be cleaned up once you delete the method reference.

The the_deletion_func reference points to a method, which points to the instance (as well as the class), so there is still a reference there.

Currently executing methods have a local variable self, which is a reference to the instance as well, but mostly it's the method wrapper that provides that reference.

Question about Garbage Collection in Java

No, you don't. The Java GC handles cyclic references just fine.

Conceptually, each time the GC runs, it looks at all the "live" root references in the system:

  • Local variables in every stack frame
  • "this" references in every instance method stack frame
  • Effectively, all static variables (In fact these are really referenced by Class objects, which are in turn referenced by ClassLoaders, but lets ignore that for the moment.)

With those "known live" objects, it examines the fields within them, adding to the list. It recurses down into those referenced objects, and so on, until it's found every live object in the system. It then garbage collects everything that it hasn't deemed to be live.

Your cyclically referenced nodes refer to each other, but no live object refers to them, so they're eligible for garbage collection.

Note that this is a grossly simplified summary of how a garbage collector conceptually works. In reality they're hugely complicated, with generations, compaction, concurrency issues and the like.

Eligibility of an Object for GC

Yes. Garbage collection of objects in Java can occur if the objects are not reachable. It isn't affected by circular references.

One definition of reachability is provided by the package documentation for java.lang.ref:

Going from strongest to weakest, the different levels of reachability reflect the life cycle of an object. They are operationally defined as follows:

  • An object is strongly reachable if it can be reached by some thread without traversing any reference objects. A newly-created object is strongly reachable by the thread that created it.
    An object is softly reachable if it is not strongly reachable but can be reached by traversing a soft reference.
  • An object is weakly reachable if it is neither strongly nor softly reachable but can be reached by traversing a weak reference. When the weak references to a weakly-reachable object are cleared, the object becomes eligible for finalization.
  • An object is phantom reachable if it is neither strongly, softly, nor weakly reachable, it has been finalized, and some phantom reference refers to it.
  • Finally, an object is unreachable, and therefore eligible for reclamation, when it is not reachable in any of the above ways.

How to prevent an object from getting garbage collected?

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.
}

How does Garbage Collector works for Primitive Data type in Java?

Primitive data types are either fields in objects or used in arrays which themselves are objects. For the garbage collector these fields are not relevant, because they do not contain pointers. They can be perfectly ignored and will be freed together with the object/array once it gets garbage collected.



Related Topics



Leave a reply



Submit