Java - Eligibility For Garbage Collection

[Updated: Dec 29, 2017, Created: Dec 28, 2017]

Automatic garbage collection is the process of deleting the unused objects by a dedicated thread usually called garbage collector. An in use object, or a referenced object, means that some part of the active program still maintains a pointer to that object. An unused object, or unreferenced object, is no longer referenced by any part of the program.

A common misconception about garbage collection is that an object which holds external references will not be garbage collected unless all its internal references are gone or are manually removed. That is not correct. An object which internally has references of other active objects can still be eligible for garbage collections if that object's references are not used by any other active part program externally.

Example

In following example, MyClassB object is going to hold a reference of an external object MyClassA which lives till the end of the program but still MyClassB objects are garaged collected.

public class GcTest {

    public static void main(String[] args) {
        MyClassA myClassA = new MyClassA();
        for (int i = 0; i < 1000; i++) {
            MyClassB myClassB = new MyClassB(i, myClassA);
            System.gc();
        }
        System.out.println(" -- end --");
    }

    private static final class MyClassA {}

    private static final class MyClassB {
        double[] d = new double[1000000];
        private int name;
        MyClassA myClassA;

        public MyClassB(int name, MyClassA myClassA) {
            this.name = name;
            this.myClassA = myClassA;
        }

        @Override
        protected void finalize() throws Throwable {
            System.out.println("finalized: "+name);
        }
    }
}
finalized: 0
finalized: 1
finalized: 2
finalized: 3
finalized: 4
finalized: 5
finalized: 6
finalized: 7
finalized: 8
finalized: 9
............
finalized: 997
finalized: 998
 -- end --

Note that if you have OutOfMemoryError exception then probably your system doesn't have enough memory and you have to decrease the size MyClassB.d array.

An object will not be eligible for the garbage collection if its references are held externally:

public class GcTest2 {

    public static void main(String[] args) {
        MyClassA myClassA = new MyClassA();
        for (int i = 0; i < 1000; i++) {
            MyClassB myClassB = new MyClassB(i);
            myClassA.list.add(myClassB);
            System.gc();
        }
    }

    private static final class MyClassA {
        List<MyClassB> list = new ArrayList<>();
    }

    private static final class MyClassB {
        double[] d = new double[1000000];
        private int name;

        public MyClassB(int name) {
            this.name = name;
        }

        @Override
        protected void finalize() throws Throwable {
            System.out.println("finalized: "+name);
        }
    }
}
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
	at com.logicbig.example.GcTest2$MyClassB.<init>(GcTest2.java:22)
	at com.logicbig.example.GcTest2.main(GcTest2.java:11)

That shows that no objects were garbage collected and the program is ended up with no memory available.

Example Project

Dependencies and Technologies Used :

  • JDK 1.8
  • Maven 3.3.9

GC Eligibility Test Select All Download
  • java-gc-eligibility-test
    • src
      • main
        • java
          • com
            • logicbig
              • example

See Also