3

What objects are available for garbage collection at the time of the call System.gc() and why?

public class GCTest {
    static class A {
        private String myName;
        public A(String myName) {
            this.myName = myName;
        }
    }

    public static void main(String[] args) {
        A a1 = new A("a1");
        A a2 = new A("a2");
        ArrayList list = new ArrayList();
        list.add(a1);
        A[] mas = new A[2];
        mas[0] = a2;
        a2 = a1;
        clear(mas);
        a1 = null;
        a2 = null;
        System.gc();
        // some code
        ...
    }

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

if object == null it becomes a garbage or not?

I think a1, a2 and mas are available for garbage collection at the time of the call System.gc() because it state null. or I'm wrong?

Tunaki
  • 132,869
  • 46
  • 340
  • 423
ip696
  • 6,574
  • 12
  • 65
  • 128

5 Answers5

8

First, your program variables are never "available for garbage collection". Only objects are collected by the GC and program variables are references to objects, not objects themselves. (The common terminology in referring to Java variables confuses this point.)

Second, none of the objects referenced by a1, a2, or mas are going to be GC'ed. This is despite the fact that a1 and a2 have been set to null. This is because references to those objects are still reachable through either list or mas. Why is the object referenced by a2 still reachable through mas even after calling clear()? Because you cannot change the value of the variable mas in main() by passing the variable to the method clear(). All you are doing in that method is changing the formal parameter (also named mas), which is a separate variable from the local variable in main(). Java is strictly pass by value. However, when it comes to objects, what's always being passed is a reference.

In general, the rule is that objects are GC'ed only if the objects are unreachable from any program variable, either directly or indirectly.

Ted Hopp
  • 232,168
  • 48
  • 399
  • 521
  • I admit this is one of the test tasks on the job. most likely I will not send him, but I was very interested in how it works. thank you explained. I would also like to read about the intricacies and workings of Java if you recommend an interesting article or book – ip696 Aug 30 '15 at 16:34
  • @ip696 - I always suggest starting with [the Java tutorials](https://docs.oracle.com/javase/tutorial/). They are accurate and quite thorough. – Ted Hopp Aug 30 '15 at 16:52
2

None will be eligible for GC:

  1. The ArrayList is still reachable and references a1.
  2. Both a2 and a1 refer to the same object.
  3. Most importantly, since Java is pass-by-value, the method clear will not actually clear the array mas passed from main.

Below is an illustration of the objects in memory when GC is invoked:

enter image description here

M A
  • 71,713
  • 13
  • 134
  • 174
2

Nothing is available to GC at this time:

  • you still have a reference (list) referencing the ArrayList containing the object initially referenced by a1 (the one with the "a1" string inside)
  • you still have a reference (mas) referencing the array containing the object initially referenced by a2 (the one with the "a2" string inside)

Note that your method

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

does nothing.

Java is pass by value. So when calling this method, a copy of the reference to the array is created and passed to the method. The method then assigns null to the copy of the original reference, leaving the original reference untouched.

See Is Java "pass-by-reference" or "pass-by-value"? for more explanations.

Community
  • 1
  • 1
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
1

The only specified rule regarding object reachability is as follows (§12.6.1):

A reachable object is any object that can be accessed in any potential continuing computation from any live thread.

Examining your code it is quite clear that no object can be accessed in any potential continuing computation. No reference to any of them will exist after main completes; furthermore System.gc() is the last statement in the program and that statement's computation will not access those or any other objects (it has no semantics at all at the Java level). Therefore all objects are in fact unreachable at that point, whether the actual implementation of garbage collection realizes that or not.

Marko Topolnik
  • 195,646
  • 29
  • 319
  • 436
  • 1
    It isn't really the last statement, since the method ends with `// some code ..."`, which, most probably, means that more code follows the call to gc(). And even if no code follows, does the GC have enough information to know that no code follows and that the variables won't ever be used again. I'm not a low-level GC and JVM expert, but I don't think it does. I see your answer as factually correct if you stick to the specifications, but a bit... nitpicking, because in practice, AFAIK, nothing is effectively eligible to GC at that point. – JB Nizet Aug 30 '15 at 16:15
  • I think this is a nitpicking question: it's from an assignment/interview, and it obviously asks for an authoritative answer derived straight from the specification. So it vitally depends on what that "some code" is. BTW it becomes far less nitpicking when people use loose reasoning to decide whether an OOME is possible at some point. For example, even variables out of scope can prevent effectively unreachable objects from being GC'd in practice (that's the flip side of my current answer). – Marko Topolnik Aug 30 '15 at 16:17
  • 2
    OK. +1 for reminding us the specs. But given that the OP doesn't understand yet how references are passed to methods and that he's thus probably interviewing for an entry-level position, I would be very surprised if the interviewer expected such a precise answer :-) – JB Nizet Aug 30 '15 at 16:21
  • True, the question indirectly probes into the understanding of other language semantics; these could have been more directly investigated by asking whether a certain statement will throw an NPE. – Marko Topolnik Aug 30 '15 at 16:23
  • Always a pleasure to argue with you Marko. Could you expand on "even variables out of scope can prevent effectively unreachable objects from being GC'd in practice" with a small example? – JB Nizet Aug 30 '15 at 16:26
  • 1
    Here: `void x() { { long[] longs1 = new long[Integer.MAX_VALUE]; } System.gc(); long[] longs2 = new long[Integer.MAX_VALUE]; }` Note the nested `{}` block. `longs1` is clearly unreachable at the point where `longs2` is assigned, but this can still give an OOME. I had an opportunity to give detailed treatment to this a while ago: http://stackoverflow.com/questions/13531004/java-outofmemoryerror-strange-behaviour/13531615#13531615 – Marko Topolnik Aug 30 '15 at 16:30
  • A comment on `even if no code follows, does the GC have enough information to know that no code follows and that the variables won't ever be used again`: the GC indirectly benefits from the JIT compiler, and the latter does indeed go into the minute details of what is used where. It will produce code which aggressively reuses stack/register locations and at each safepoint there is an `oopmap` detailing the location of possibly live object pointers. This is why my answer is not just an academic tidbit. – Marko Topolnik Aug 30 '15 at 17:10
0

The object created by new A("a1"), new A("a2") and mas was not garbage collected when you call System.gc().

Any object referenced directly or indirectly by Threads are not available for gc. The thread is running this method, so local variables would be kept.

Using the object created by new A("a1") (let's call it A1) as an example, .

In the moment of System.gc() is run, list referencing object A1 in its internal structure, therefore it is not garbage collected even though it is not referenced in a1.

Derek Fung
  • 8,171
  • 1
  • 25
  • 28
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/88729/discussion-between-cfi-and-derek-fung). I have delete my other comments here, because they no longer apply or are irrelevant for this Q&A – cfi Sep 03 '15 at 17:46