Java Performance Services
Training, Seminars, Benchmarking, Tuning

Java Performance Tuning Course


Chania Crete, May 17-20, 2010


Sun Extreme Learning EXL-2025

Houston, December 1-4,2009
New York, December 8-11, 2009
Washington DC, January 5-8, 2010



San Francisco, January 11-14

Anti-if

I have joined Anti-IF Campaign

Calendar

««Nov 2009»»
SMTWTFS
1234
5
67
891011121314
15161718192021
22232425262728
2930

Performance Anti-Patterns

My Top Tags

                                       

Mailing List

My RSS Feeds








Code Smell, X = null;

posted Thursday, 1 July 2004
I see in a number of places that people are recommending that you null out a variable in order to help the garbage collector along. What is interesting is that no one bothers to explain how setting a reference to null might help the garbage collector. But if one thinks about the ebbs and flows of the treads running in an application, then an explanation starts to emerge from the darkness. When one calls a method or enters a new block, the VM allocates a new stack frame for the thread. The stack frame is used to hold all references that are local to that particular code block. When the thread of execution exits the block, the block goes “out of scope” and the stack frame is released. When the stack frame is released, it takes with it every local reference contained with-in. This allows GC to recover the space used by these references. In other words, unless a variable that is local to the block has been assigned to another reference in an outer scope, the variable is now unreachable and consequently is eligible for GC. Variables or references can exists as static (or class variables), fields (or instance variables), parameters, variables local to a method, or variables local to a block. If we follow the best practice of narrowing a variables scope to the smallest possible window, then these variables should (via the natural ebb and flow of the application) go out of scope quite quickly. If the scope of a variable has not been narrowed, then it will (quite naturally) stay in scope for a much longer period of time. In the worst case in which one may have assigned a local variable to a static, the value maybe in scope for the duration of the application’s lifetime. In this instance, nulling out the reference would shorten the life span. Shortening the lifespan could help the GC cope with it’s task and here is why. With generational GC, the age of an object is determined by the number of GC cycles they survive. If an object survives long enough (31 GCs by default), then it will be tenured into old space. However, there are cases when objects may be “prematurely” tenured (or moved into old space). One of these cases is when a survivor space shows up. It does not seem like coincidence that applications that hold onto variables longer than they need to may fill up a survivor space and cause objects to be tenured. Why should we care about where an object lives or dies? The answer is simple; it is much cheaper to GC an object that is in young space. A GC in young may last 10s of ms but in old they can run for seconds. So if you want to avoid long GC pauses, try nulling out a few of the values in the outer scope. A better solution is to narrow the scope of the reference that you are needing to null. The code smell is someVariable = null, which looks very much like the destroy call in C++. It’s a clear sign that the variable’s scope should be narrowed to the block in which it’s being nulled. But what if the variable is being set else where in the code? Again, it’s not an indication that one should null out a variable. It is an indication that either something is wrong in the flow, or that the variable should have been passed in as a parameter. Thus, as the stack unwinds, the variable will come out of scope when it should and this will help us to avoid the multitude of problems that are a result of improper scoping.



1. a reader left...
Friday, 2 July 2004 1:07 am

Blocks within methods do not get their own stack frames; only methods do. Each local variable is allocated at the method level and has a physical scope of the entire method, even though its logical scope may be only a small block within the method.

During the parts of the method outside of the logical scope, the local variable is said to be "invisible." See http:/ /java.sun.com/docs/books/performance/1st_edition/html/JPAppGC.fm.html#99741 4 for some official scoop on this.

Doug


2. a reader left...
Friday, 2 July 2004 1:27 am

I've been using the Jrockit 1.4.2_04 vm for a little while and I think it actually nulls the references for you when they fall out of logical scope. At least it seems this way because when I'm debugging, this is what I see through variable watches.

Ron [b0b0b0b@gmail.com]


3. a reader left...
Friday, 2 July 2004 1:32 am

Doug,

Whilst I understand what you say to be true, could we instead, refactor in order to move the nested block into a private method and let the VM inline the call if it sees fit?

Simon [simon@redhillconsulting.com.au]


4. Mark left...
Friday, 2 July 2004 6:08 am

Take a look at this article: http://www-106.ibm.com/developerworks/library/j- jtp01274.html.

It pretty much covers what you talk about and points out that the whole premise behind nulling to help the GC may no longer hold true.


Mark


5. Kirk Pepperdine left...
Friday, 2 July 2004 8:08 am

Doug,

Thank you for your comment. You are of course correct in that blocks inside a method will not get their own stack frame. My explination in this instance is a bit light. And, there are other things going on that I didn't mention. For example, the compiler may move the declaration of a variable to a broader scope. That said, the only way that I can see how nulling a variable would help GC is that it would release the reference earlier than it might otherwise do so. My point is that if you are "suddenly" release large number of objects, then I would suspect that there are some problems in the code. Improper scoping seems like one possible candidate. Certianly needing to null out variables is a code smell.


6. Kirk Pepperdine left...
Friday, 2 July 2004 12:19 pm

in response to Mark's trackback at http://io.dnsalias.net/roller/comments/markwoon/Weblog/let_the_gc_be
My premise is that you shouldn't have to help out the garbage collector. If you do find yourself in a postion where you do have to "help", then you've most likely done something wrong in your code. I've run into small number of cases where the garbage collector legitimately could not keep up. These cases do exists because after all, every system has a finite capacity. That said, we do want to be wise in how we utilize that capacity.


7. a reader left...
Friday, 2 July 2004 8:50 pm

Kirk: Completely agreed. I just wanted to clarify that putting the variables in an anonymous block won't necessarily help. The only way it would help is if the compiler puts in the "=null" that we just took out, as Ron thinks that JRockit might do.

Simon: Yes, that would be the way to do what Kirk's talking about: refactor into a separate method. Unfortunately, if the compiler (or more likely the JIT) *does* inline the method call, you lose the automatic descoping of the stack frame. The compiler/JIT may or may not insert the "=null" back in for you -- I don't think that this is required.

I suspect that Simon has a particular interest in this topic, given his recent run-in with JUnit :-)

Doug


8. a reader left...
Monday, 23 August 2004 1:58 pm

While setting the variable to null, we must always keep in mind that somewhere down the line this might me used again and may throw NPE.

This would typically happen when the code is long and maintained by multiple developers. If you set the variable to null and then later use it, it will bomb. For example:

Car myCar = new Car();
mCar.setColor(BLUE);
mCar = null;
............
if ()
{
int color = mCar.getColor();
}

Note: Even if you test run and test the code, it will _appear_ to work, but say in customer place if that condition becomes true, it will throw NPE. This would then require us to unit test all the flow, which is practically impossible.

Kamal [ksinghdev@hotmail.com]