Maksim Dmitriev
Maksim Dmitriev

Reputation: 6209

Java job interview. How many objects are eligible for garbage collection?

Here is a typical Java job interview question. How many objects will be garbage collected by System.gc();?

I will use the following designations in the code:

Used class.

package com.mock;

public class GCTest {

    static class A {

        private String myName;

        public A(String myName) {
            this.myName = myName;
        }
    }
}

Usage.

package com.mock;

import com.mock.GCTest.A;

import java.util.ArrayList;

public class Main {

    public static void main(String[] args) {
        A a1 = new A("a1"); // A ref to A1. 1 ref in all.
        A a2 = new A("a2"); // A ref to A2. 2 refs in all.
        ArrayList<A> list = new ArrayList<A>(); // A ref to the empty ArrayList. 3 refs in all.
        list.add(a1); // The list has a1 holding a ref to A1 
        A[] mas = new A[2]; // A ref to an array; it has nulls in it. 4 refs in all.
        mas[0] = a2; // Now mas holds the ref to A2.
        a2 = a1; // a2 holds the ref to A1 
        clear(mas); // Nothing changed because methods deals with copies of parameters rather than with parameters themselves. 
        a1 = null; // a1 no longer holds the ref to A1
        a2 = null; // a2 no longer holds the ref to A1
        System.gc(); // Nothing should be garbage collected
    }

    private static void clear(A[] mas) {
        mas = null;
    }

}

Upvotes: 3

Views: 1216

Answers (2)

Maksim Dmitriev
Maksim Dmitriev

Reputation: 6209

My answer is 0 because both list and the mas have elements holding references to A1 (list) and to A2 (mas).

I created three charts in order to simplify my answer. Rectangles correspond to the chunks in memory; circles correspond to objects. The gray arrows correspond to the references that no longer exist.

Before a1 = a2.

enter image description here

After a1 = a2.

enter image description here

Neither a1 nor a2 hold references

enter image description here

I could override finilize() for the class A to see what is eligible for gabage collection.

@Override
protected void finalize() throws Throwable {
    // TODO Auto-generated method stub
    System.out.println("finalize: " + myName);
    super.finalize();
}

Although I saw logs while I was testing the code, there is no 100% guarantee that memory is clear after calling System.gc()

Runs the garbage collector.

Calling the gc method suggests that the Java Virtual Machine expend effort toward recycling unused objects in order to make the memory they currently occupy available for quick reuse. When control returns from the method call, the Java Virtual Machine has made a best effort to reclaim space from all discarded objects.

Upvotes: 3

skiwi
skiwi

Reputation: 69409

This may very well be a trick question.

What System.gc() does is dependend on the underlying garbage collector.

gc

public static void gc()

Runs the garbage collector.

Calling the gc method suggests that the Java Virtual Machine expend effort toward recycling unused objects in order to make the memory they currently occupy available for quick reuse. When control returns from the method call, the Java Virtual Machine has made a best effort to reclaim space from all discarded objects.

The call System.gc() is effectively equivalent to the call:

     Runtime.getRuntime().gc()


See Also:
    Runtime.gc()

What you do know is that:

  • Between 0 and "the number of Objects in your program" Objects will be garbage collected.
  • There is a very high likelyhood that it will be between 0 and "the number of Objects that should be garbage collected".
  • There is a relatively high likelyhood that it will garbage collect exactly "the number of Objects that should be garbage collected".

Upvotes: 3

Related Questions