Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Garbage collection on a local variable

I'm a C++ programmer entering the world of Java. And I cannot get rid of the bad feeling of having to let the Java garbage collector do my cleaning.

How, for example, will this code behave in Java?

public void myFunction() {
    myObject object = new myObject();
    object.doSomething();
}

Will the local variable object be deleted when myFunction() exits?

Do I have to set object to null before exiting, or will it be out of scope and be deleted by the GC? Or, at worst, will it leak like it would in C++?

like image 347
Espen Avatar asked Nov 09 '10 20:11

Espen


People also ask

Which variables are eligible for garbage collection?

An object is eligible to be garbage collected if its reference variable is lost from the program during execution. Sometimes they are also called unreachable objects. What is reference of an object? The new operator dynamically allocates memory for an object and returns a reference to it.

What is garbage collection explain with example?

Garbage collection in Java is the process by which Java programs perform automatic memory management. Java programs compile to bytecode that can be run on a Java Virtual Machine, or JVM for short. When Java programs run on the JVM, objects are created on the heap, which is a portion of memory dedicated to the program.

Do global variables get garbage collected?

Global variables are never disposed of by the GC in the sense that a global variable will still exist. Setting it to null will allow the memory that it references to be collected, however.


3 Answers

It will be garbage collected at some point after it's no longer used. I believe in current implementations of Java it will actually persist until the end of the method, whereas the garbage collector in .NET is more aggressive. (I don't know whether there are any guarantees even in Java. Normally you'd only want the local variable to persist beyond its last possible read when you're debugging.)

But no, you don't need to set the variable to null, and doing so would harm readability.

It's unlikely that the object will garbage collected immediately after the method exits; it's up to when the GC runs... and of course if anything else holds onto a reference to the object, it may not be eligible for garbage collection anyway. Don't forget that the value of the variable is just a reference, not the object itself. (That may take a while to get used to coming from C++.)

like image 96
Jon Skeet Avatar answered Oct 03 '22 14:10

Jon Skeet


GC does the job at least when memory limit approaches, since any object referenced by out-of-scope variables can be garbage collected, but there is an unexpected behavior of out-of-scope local variables of the last exited block.

To look under the hood, let us compare :

{
   final List myTooBigList = new ArrayList();
   ... overfill the list
}
somethingRunOutOfMemory();

somethingRunOutOfMemory() because myTooBigList were not GCable, despite not in scope anymore and more memory was claimed, unlike the following :

{
   final List myTooBigList = new ArrayList();
   ... overfill the list
}
Object fake = null;
somethingDoesNotRunOutOfMemory();

Affectation of fake moves the stack pointer back and let myTooBigList GCable, then GC does its work as soon as memory limit approaches. The surprise is that (at least in the jvm I'm testing) we have to explicitely reuse stack at the same level. It would be expected that local variables be GCable as soon as the block is exited, but I guess it's a compromise with performance. It would complicate much the bytecode.

Like in C, local variables are located in stack beside frames. The stack pointer reserves as much space as required for the local variables in scope. Local variable of an { exited block } become GCable when stack is reused, that is: after a local variable is declared at the same stack level, after the function returns, or after an exit evaluation (catch, loop condition).

They are GCable after :

try { } catch : after exit by catch because catch reuses stack
for { } : after exit loop condition  because evaluation reuses stack
while { } : after exit loop condition because evaluation reuses stack
{ } declare=value : after any declaration+affectation that reuses stack

They are not GCable just after :

try { } : after nothing caught
for { } : after exit by break
while { } : after exit by break
do { }
if { }
{ }

NOTE : for a lab, run GC then compare a WeakReference(my variable) to null.

final WeakReference gctest;
{
   final List myTooBigList = new ArrayList();
   gctest = new WeakReference(myTooBigList);
   ... overfill the list
}
Object fake = null;
System.gc();
assert gctest.get() == null;
like image 24
Thibault LE PAUL Avatar answered Oct 03 '22 14:10

Thibault LE PAUL


It will go out of scope. In Java, when no-one is pointing to an object anymore, it will be garbage collected or at least it will be available for garbage collection. No need to set it to null here. Sometimes setting an object reference to null is needed if your object will live on in you App, but a reference it holds needs to be garbage collected. In this case you are choosing to release the reference.

like image 1
Hannes de Jager Avatar answered Oct 03 '22 16:10

Hannes de Jager