Garbage collection on a local variable

2019-01-05 04:54发布

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++?

3条回答
太酷不给撩
2楼-- · 2019-01-05 05:19

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.

查看更多
我只想做你的唯一
3楼-- · 2019-01-05 05:27

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++.)

查看更多
劫难
4楼-- · 2019-01-05 05:31

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;
查看更多
登录 后发表回答