-2

Given:

class Finalizer {
    static int x = 0;
    static boolean gc = false;
    public static void main(String[] args) {
        for(x=0; x<100000; x++) {
            new Finalizer().finalize();
        }
        x = 0;
        gc = true;
        System.gc();
    }
    protected void finalize() {
        if(gc == true) x++;
        if(x % 10000 == 0)
           System.out.println(gc + " " + x);
    }
}

Which are always true? (Choose all that apply.)

A: true will never be an output
B: true will be output at least ones
C: If true and false are both output, their respective values for x can be the same.
D: If true and false are both output, their respective values for x can never be the same.

The solution says C is correct, and I do not understand why, can someone please explain what is happening here.

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • 2
    Have you tried simply running the code? What were your findings? – Jeroen Vannevel Feb 12 '14 at 18:09
  • Since you won't be able to run this code on a real exam, I'd recommend tracing through it by hand (just enough to see what it's doing, not all 100,000 iterations of that loop). This will help you see what the code is doing, and then you can see why C is correct. – forgivenson Feb 12 '14 at 18:23
  • Note that if he sees why C is true, he still has to understand why A and B are incorrect. (The exam says to choose _all_ the statements that are always true. C and D can't both be correct, since they're mutually exclusive.) – ajb Feb 12 '14 at 18:27
  • 1
    @JeroenVannevel I've tried it, and running the code does not provide enough information to explain much of anything. At least on my system. – ajb Feb 12 '14 at 18:41

1 Answers1

1

What's going on is this: finalize() overrides a method in the Object class. The javadoc explains when this is called. When an object is no longer referenced anywhere, it may then be garbage-collected; but when it's garbage-collected isn't defined by the language.

The finalize() method will be called on each Finalize object when it's garbage-collected. Of course, the code you posted also calls finalize() explicitly.

In this example, the loop will call new Finalize() 100,000 times to create new Finalize objects. Each time a new object is created, it's used to call finalize() explicitly, but then it's no longer used, so it could be garbage-collected right away. The consequence of this is that by the time we get to the System.gc() call, we don't know how many Finalize objects are still around waiting to be garbage-collected, but it could be anywhere from 0 to 100,000. (On my machine, it seems to be 1. That is, it's already garbage-collected all but one of the objects, and called finalize() on them.)

During the first loop, x will go from 0 to 999,999 (the finalize() method won't modify x), and therefore you should see false x for every x that is a multiple of 10,000. (Note that finalize() could also be called by the runtime for objects that are garbage-collected early, so in theory it's possible to see false x for the same x more than once.)

After the first loop, if N is the number of objects still to be garbage-collected, then System.gc() should cause them all to be garbage-collected at that point (it's not guaranteed); since x has been reset to 0 and finalize() will increment it, that means x will go from 1 to N. (Note that the first finalize() will increment x from 0 to 1 before the x % 10000 test.) You should see true x for every x in the range 1 to N that is a multiple of 10,000.

But since N could be anything from 0 to 100,000, that means that we may or may not see any true outputs--we can't tell. That's why neither A nor B is "always true". If we do see any true outputs, since the output will show every multiple of 10,000 in its range, it's certain that the true output will have the same number as a previous false output, which explains why C is correct and D is not.

ajb
  • 31,309
  • 3
  • 58
  • 84