0

Given the following code, how many objects are created within main() and after the execution of line 15, how many objects are eligible for garbage collection?

class Test
{
    int[] dz = {1, 2, 3, 4, 5};
}

public class MarksDriver
{
    public static void main(String[] args)
    {
        Test[] da = new Test[3];
        da[0] = new Test();
        Test d = new Test();
        da[1] = d;
        d = null;
        da[1] = null;   //line 15
        //some code
    }
}
  1. 3 created, 0 eligible
  2. 4 created, 1 eligible
  3. 5 created, 2 eligible
  4. 3 created, 2 eligible
  5. None of the above

Ok first of all, Please don't mark it as Homework. This is a question from a test at my college. According to me there should be 2 objects those are created and 1 is eligible for garbage collection after line 15. It's because there are only two new operators used for creating objects and the object that 'd' was referring to at the beginning is lost after line 15 so it will be freed of memory. So I marked the last option that is none of the above. But my Teacher marked it wrong and said the answer is 5,2. She gave some explanation that I didn't get a hint of.

So can anyone explain this?

sanyam
  • 25
  • 4
  • "But my Teacher marked it wrong and said the answer is 5,2" - invite her/him in here. cause he/her does not really know the answer either. – Eugene Jul 01 '21 at 16:09
  • @Eugene Array (da), 2x Test, each containing 1 array = 5. The `da` array is still referenced, as is the value at `da[0]`, leaving only 2 objects eligible for GC - the instance initially assigned to `Test d`, and it's member array. So the answer is correct. – Michael Jul 01 '21 at 16:13
  • 2
    @Michael if you do not use anything after `//some code`, then _everything_ is eligible for GC. This kind of questions make zero sense – Eugene Jul 01 '21 at 16:14
  • @Michael But creating an array of objects don't actually create objects, right? It create object references. And the objects must be created manually. – sanyam Jul 01 '21 at 16:16
  • @xanyamm Creating an array doesn't create objects, correct. But the array is itself an object. – Michael Jul 01 '21 at 16:17
  • @Eugene The example is a bit contrived, and they manipulate references in an intentionally confusing way, but the question makes sense. Substitute `//some code` for any valid statement, put a breakpoint on that statement, run it, and list which objects are still referenced when it stops. Makes perfect sense to me. – Michael Jul 01 '21 at 16:20
  • @Michael Ok I got that but then, wouldn't the member arrays be initialised with a null reference by the default constructor? – sanyam Jul 01 '21 at 16:21
  • @xanyamm No. There are multiple ways to initialize a field. The way your example does it is at the point of declaration. So each instance of `Test` starts with a field called `dz` initialized to a new array containing the numbers 1 to 5. The numbers in the array are primitive types so they don't count to the number of objects. See https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html – Michael Jul 01 '21 at 16:24
  • @Michael it's your take on it and I respect it, sure. The way this code is and the question : "how many objects are eligible for GC after line 15", the answer is : all of them. – Eugene Jul 01 '21 at 16:26
  • 1
    @Michael adding a debugger that can inspect objects means altering the execution environment. The reason, the objects don't get collected then, is that the debugger holds references to these objects on its own. The normal situation has been described in [Can java finalize an object when it is still in scope?](https://stackoverflow.com/a/24380219/2711488) – Holger Jul 01 '21 at 17:41
  • 1
    It's strange to present answers numbered from one to five and the saying the answer is "five comma two". Took me a while to understand what this is supposed to mean. To address your confusion, the field declaration `int[] dz = {1, 2, 3, 4, 5};` in class `Test` is not different to having a field declaration `int[] dz;` and a constructor `Test() { dz = new int[] {1, 2, 3, 4, 5}; }` which also is just a short-hand for `dz = new int[5]; dz[0] = 1; dz[1] = 2; dz[2] = 3; dz[3] = 3; dz[4] = 5;`. The compiled code will be (almost) the same for all three variants. – Holger Jul 01 '21 at 17:53
  • @Eugene re "The way this code is and the question : "how many objects are eligible for GC after line 15", the answer is : all of them." ... The comment after line 15 is there importantly to show that da [0] can't be deleted because code after line 15 might use it. – Alan Jul 01 '21 at 19:14
  • @Holger Fine, then replace the debugger in my example with a magic stopwatch that halts execution. Can we agree the question is perfectly straightforward, or shall we now debate the existence of such a magic stopwatch? – Michael Jul 01 '21 at 20:11
  • @Alan first of all a java garbage collector doesn't "delete" anything, it might zero things out (even that is not correct since it does not do that); then if your point is correct, then that should be an invariant of the question. I can say the same thing : "nothing is there after the comment. nothing.", as such everything is eligible for GC. For a student, the professor gave a dumb question. – Eugene Jul 03 '21 at 00:35
  • @Eugene Yes, I know it is not automatically zeroed out, nor do the memory cells drop off the face of the earth. Their addresses are deleted from lists of memory to keep around and moved to lists of available memory, etc. The point is that if there is remaining code in that method, it could easily access `da [0]`, therefore `da [0]` can't be eligible for garbage collection until that is known and it won't be for the purposes of the question. But other things are nulled and are eligible. But NOT all of them. To be eligible you have to be certain they aren't accessed any further. – Alan Jul 03 '21 at 03:05
  • @Eugene, even Oracle uses the word "delete" when talking about garbage collection: https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html It is a common expression as a short-hand for the more complicated machinery behind it. They write: "Automatic garbage collection is the process of looking at heap memory, identifying which objects are in use and which are not, and deleting the unused objects." – Alan Jul 03 '21 at 03:19
  • 1
    @Michael no, it’s not straight-forward. I already gave you [this link](https://stackoverflow.com/a/24380219/2711488) in [this comment](https://stackoverflow.com/questions/68213545/?noredirect=1#comment120560805_68213545). The linked answer provides an actual example code that demonstrates that objects referenced by local variables in scope can get garbage collected in real life. So these objects are formally eligible for gc *and* they may get collected in practice, but you say that a “magic stopwatch” has more relevance than specification *and* real life together? – Holger Jul 05 '21 at 08:47
  • 2
    @Alan a college test that expects to make guesswork about what “some code” not shown in the task will do, is fundamentally flawed. Besides that, as discussed in [finalize() called on strongly reachable objects in Java 8](https://stackoverflow.com/q/26642153/2711488), even using an object does not necessarily prevent the garbage collection of that object; it may even get collected (and in turn finalized) while a method invocation on that object is still ongoing. All that matters, is whether the JVM can prove that the *object’s memory* is not needed anymore. In the actual, JIT-optimized code. – Holger Jul 05 '21 at 10:26
  • @Holger Thanks for the clear explanation and the interesting link. – Alan Jul 05 '21 at 10:34

2 Answers2

0

When we write

 Test d = new Test();

2 objects are created one is d other one is member array dz

same way with

da[0] = new Test();

2 objects are created one is stored in da[0] other one is member array dz

and one more object is created by

Test[] da = new Test[3];

so total 5 objects created

with these 2 lines of code there is no reference for one object of class test created at line 13 which makes it eligible for garbage collection which in turn also makes the member array dz eligible for garbage collection, so 2 objects become eligible for garbage collection after line 15

    d = null;
    da[1] = null;
anish sharma
  • 568
  • 3
  • 5
0

5 created, 2 deletable

Two Test objects are created. But each contains an array object so that is a total of four objects.

Additionally the array da is created. That is 5 objects.

When d is nulled, then two objects can be garbage collected: the array that d contains and d itself.

...

Perhaps teacher is wrong and "none of the above" is right because the underlying true answer is 6 and 2 because surely a sixth object is created: the MarksDriver object!

Alan
  • 716
  • 5
  • 15
  • Calling MarksDriver.main() does not instantiate the MarksDriver class. The JVM invokes the main method with a non-null args array, even if empty. However, if we count args, we should also count Test.class, MarksDriver.class and any number of hidden JVM objects. I think 5 *user* objects were created, of which 2 are deletable is a reasonable answer. – ehecatl Jul 01 '21 at 19:30
  • @ehecatl Is that because `MarksDemo` has no instance/static variables? If it did (say a primitive int), then would that mean that it is actually instantiated because a variable needs to be contained? – Alan Jul 01 '21 at 19:33
  • 2
    An instance is created when the program code contains `new MarksDriver(…)`. Otherwise, no instance of that class is created, regardless of what variables you declare in that class. – Holger Jul 05 '21 at 08:59
  • @Holger That makes good sense. A good way to remember it too. Yes, it would be access. Thanks. And then by that reasoning I think the static variables would be held on the heap as needed and manipulated at the class level. – Alan Jul 05 '21 at 10:22