michael nesterenko
michael nesterenko

Reputation: 14449

garbage collection of invisible variables

I have following code:

void method() {
   Object o1 = new Object();
   {
      Object o2 = new Object();
      System.out.println(o2);
   }
   // any long operation
}

will o2 object be eligible for garbage collection during execution of long operation?

Upvotes: 1

Views: 214

Answers (4)

Mike
Mike

Reputation: 674

No. Even though the object referenced by o2 is not reachable, it will not be garbage-collected. It is in a state between reachable and unreachable called "invisible" because the reference variable o2 is still on the stack.

To make the object garbage-collectible, assign o2 = null or put that block in another function.

source: A 2001 book on Java performance

Upvotes: 0

Stephen C
Stephen C

Reputation: 719386

The JLS definition of reachability is:

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

In this case, the reference ceases to be theoretically accessible to ongoing combutations before the println call returns. (I'm assuming that println(o2) doesn't save its the reference somewhere.)


However, in practice no JVMs in existence can tell that the Object becomes unreachable during the call, and most JVMs will only notice this when ... or after ... o2 goes out of scope. And even then, a GC run is not guaranteed to remove the object.


Note: that doesn't contradict the JLS, because the "reachable object" test is really telling you when the object won't be garbage collected, not when it will be. The JLS is careful to specify that an object may be finalized and garbage collected at some point after it becomes unreachable, but that it also may never be finalized and garbage collected.

Upvotes: 2

Hot Licks
Hot Licks

Reputation: 47749

You need to understand that your variable o2 and the OBJECT DESIGNATED BY o2 are different.

The variable o2 is actually a pointer (though Java prefers to call them "references") and occupies 4 or 8 bytes in the automatic stack frame. This storage is not garbage collected and only goes away when you return from the procedure (or possibly when you exit the {} brackets depending on compiler implementation).

The object "designated by" (pointed to by) o2 is essentially available for possible garbage collection as soon as the new Object() operation ends, and the existence of a pointer to it in o2 is all that prevents this. Once the variable o2 either no longer exists in a stack frame or has a different pointer value stored into it then the object is eligible to be collected.

So in your particular case the answer is "maybe". It depends on how the compiler and JIT handle the {}, along with a few "luck" issues as to whether, having exited the {} block (but not the method as a whole), the storage location for o2 is reused for something else.

Upvotes: 0

ratchet freak
ratchet freak

Reputation: 48216

yes however this will depend on whether the JVM/JIT won't optimize this to avoid superfluous stack operations

which would make it

Object o1 = new Object();
Object o2 = new Object();
System.out.println(o2);
// any long operation

many compilers will group all local variable needed and figure out the maximum needed space to keep them all (and some will be eliminated and just kept in registers) and grow the stack accordingly and only shrink it after the function can return

this would mean that o2 will remain in "accessible" memory according to GC unless it was overwritten with another variable in another scope

Upvotes: 0

Related Questions