I was \'forced\' to add myLocalVar = null;
statement into finally clause just before leaving method. Reason is to help GC. I was told I will get SMS\'s during n
The Java GC is supposed to be "sound" but is not necessarily immediately "complete". In other words, it is designed so that it would never eliminate objects that are still accessible by at least one path (and thus cause a dangling reference). It is not necessarily immediately complete since it might take time until it removes everything that can be removed.
I think that most GC myths come from a misunderstanding of that concept. Many people keep too many instance variables alive, and that causes problems, but that is of course not the issue here.
Other people put the local variables in an instance variable (e.g., by passing it to function), and then think that nullifying the local variable somehow eliminates the variable, which is of course untrue.
Finally, there are people who overrely on the GC and think it would do functional shutdown for them (E.g., close connections when variable is removed) which is of course not the case. I think the source of this line is the "I'm really really done with it but I'm not sure how to ensure that".
So yeah, you're correct that it's unneccessary.
Not in this case. myLocalVar falls out of scope as soon as the function returns, so setting the reference to null does absolutely nothing.
Nulling local variables can indeed help in some edge cases. This doesn't apply to situation in original question, but is educational anyway... Let's consider this program:
public class Main {
public static void main(String[] args) {
{
Main local = new Main();
// inner = null;
}
while (true) {
// long running method
}
}
}
If inner = null;
is commented out, object in local
variable cannot be garbage-collected during while loop. Reason is that Java Virtual Machine doesn't know about scopes like this. All it has is:
D:\workspaces\workspace-3.4\test\src>javap -verbose -c Main
public class Main extends java.lang.Object
minor version: 0
major version: 50
Constant pool:
const #1 = Method #4.#11; // java/lang/Object."<init>":()V
const #2 = class #12; // Main
const #3 = Method #2.#11; // Main."<init>":()V
const #4 = class #13; // java/lang/Object
const #5 = Asciz <init>;
const #6 = Asciz ()V;
const #7 = Asciz Code;
const #8 = Asciz main;
const #9 = Asciz ([Ljava/lang/String;)V;
const #10 = Asciz StackMapTable;
const #11 = NameAndType #5:#6;// "<init>":()V
const #12 = Asciz Main;
const #13 = Asciz java/lang/Object;
{
public Main();
Code:
Stack=1, Locals=1, Args_size=1
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
Stack=2, Locals=2, Args_size=1
0: new #2; //class Main
3: dup
4: invokespecial #3; //Method "<init>":()V
7: astore_1
8: goto 8
StackMapTable: number_of_entries = 1
frame_type = 8 /* same */
}
There is no information about scope of local variable. So from JVM's point of view, above program is equivalent to:
public class Main
{
public Main() { }
public static void main(String args[])
{
Main main1 = new Main();
do
;
while(true);
}
}
(Generated by JAD decompiler)
Conclusion: there IS some rationale in nulling local variables in very special cases like this. But if method is going to finish soon (like in my original question), it doesn't help.
This was inspired by comment from Zdenek Tronicek on java-cz mailing list (in czech language, sorry)
As you correctly point out, nulling out in this case is totally pointless.
Back on JDK1.3 I did actually have a case with an extremely large object graph that also contained lots of circular references within the graph. Clearing out a few of the references did actually improve GC times quite noticeably.
I am not sure if this would apply with a modern VM. Garbage collectors have become increasingly smarter.
Another possible factor in this myth is that it can make a difference to null out a local variable if you are done with it before the end of the method. This would allow the GC to collect that object before the method is complete, which could be useful.
Someone might have been given that advice at some point and misunderstood it as a need to always null out the local variables.
Not only is nulling a local variable like that meaningless in terms of GC, it may cause unnecessary loading of the variable into a register in order to null it out, which makes the situation worse. Imagine if there is 1000 lines of code between the last read or write to myLocalVar, and then you reference it just to null out the reference. The value is long gone from the register, but you have to load it back in to memory to work with it.