F
Frank Cisco
If you null and object ie. obj = null, when is it cleared from memory?
Immediately or at the next garbage collection?
Immediately or at the next garbage collection?
Frank said:If you null and object ie. obj = null, when is it cleared from memory?
Immediately or at the next garbage collection?
Frank said:If you null and object ie. obj = null, when is it cleared from memory?
Immediately or at the next garbage collection?
You null a ref to an object. The object that the ref previously
pointed to will be GC'ed after that assuming that there are no other
refs to it.
Note that there is very rarely any use for explicit nulling
in Java. Having the ref not being ref'ed any more is sufficient.
You null a ref to an object. The object that the ref previously
pointed to will be GC'ed after that assuming that there are no other
refs to it.
Note that there is very rarely any use for explicit nulling in Java.
Having the ref not being ref'ed any more is sufficient.
Tom said:You null a ref to an object. The object that the ref previously
pointed to will be GC'ed after that assuming that there are no other
refs to it.
Note that there is very rarely any use for explicit nulling in Java.
Having the ref not being ref'ed any more is sufficient.
The only time it's important is where you have a reference from a
long-lived structure to a large structure that you no longer need. The
long-lived structure can be an object or a stack frame. If you're
writing a class where the lifetime is unknown (a library class, say),
and the size of the referent is large or unknown, i think it's prudent
to null out the variable when you can. ArrayList nulls out slots in its
array when elements are removed, for example; ISTR that an early version
didn't, and that this led to hard-to-debug memory leaks.
An example of the stack frame case was a program i worked on a little
while ago which looked like:
public void main(String[] args) {
BigXMLDocument conf = loadConfigFile();
Problem prob = initialiseProblem(conf);
prob.solve();
printResult(prob);
}
The XML tree for the config file wasn't needed after the creation of the
problem object, but because the reference to it was still live, it
couldn't be collected, and so sat around wasting memory while the
long-running solve method ran. Explicitly setting the variable to null
before going into solve would have avoided this.
However, what we actually did was to simply do an extract method
refactoring on the first two lines. That pushed the reference down into
a stack frame which died before solve was called, and shaved tens of
megabytes (woo!) off the heap usage. Where you can do this, it's more
elegant than explicit nulling - putting short-lived things on the stack
is generally a good idea.
Lew said:This is much better than explicit nulling.
Tom said:However, what we actually did was to simply do an extract method
refactoring on the first two lines. That pushed the reference down
into a stack frame which died before solve was called, and shaved
tens of megabytes (woo!) off the heap usage. Where you can do this,
it's more elegant than explicit nulling - putting short-lived
things
Mike said:Why? I'd think
document = null; // Allow the document to be collected
makes the intent clearer than
doInit();
giving the reader no clue why that part of the initialization logic
was put into a seperate method.
What intent? To uselessly help the GC?
The closing brace gives ample clarity to the intent that a variable go out of
scope.
Explicit nulling implies that such a thing is necessary to the logic of the
program, a false implication in most cases. Putting almost any explicit logic
in to "help" GC is a red herring, not germane to the business logic of the
code. Ergo, documenting such non-germane code is only compounding the error.
Authors like Brian Goetz refer to explicit nulling as a mistake:
Sun warned of this risk [reference retention] and explained how explicit
nulling was needed in cases like the pop() example above. Unfortunately,
programmers often take this advice too far, using explicit nulling in the
hope of helping the garbage collector. But in most cases, it doesn't help
the garbage collector at all, and in some cases, it can actually hurt your
program's performance. ....
Explicit nulling should be saved for cases where your program is subverting
normal scoping rules for performance reasons, such as the stack example in
Listing 3
Peter said:In fact, even the example Lew gives of a Stack is in reality unlikely to
require specific handling. In particular, if you're actually _done_
with the Stack, simply getting rid of the reference to the Stack itself
is sufficient for releasing all the objects that the Stack itself
references. Once the Stack becomes unreachable, so too do all the
objects the Stack references (assuming they aren't referenced elsewhere,
of course). It's only if you intend to retain the Stack, but no longer
want the objects to which it refers do you need to do any clearing of
references (and of course, the most direct way to do that is simply to
call the clear() method).
(Of course, in the real world a Stack is usually not discarded until
empty, at which point it doesn't have references to other objects
anyway, but that's not really germane to the point here ).
Lew said:Tom said:However, what we actually did was to simply do an extract method
refactoring on the first two lines. That pushed the reference
down
into a stack frame which died before solve was called, and shaved
tens of megabytes (woo!) off the heap usage. Where you can do
this,
it's more elegant than explicit nulling - putting short-lived
things
What intent? To uselessly help the GC?
The closing brace gives ample clarity to the intent that a variable
go out of scope.
We were specifically discussing the case where it is necessary,
because the variable won't go out of scope anytime soon. This can
also occur with nested scopes within a method, since variables within
them don't go "out of scope" for GC purposes until the method returns.
Explicit nulling implies that such a thing is necessary to the logic
of the program, a false implication in most cases. Putting almost
any explicit logic in to "help" GC is a red herring, not germane to
the business logic of the code. Ergo, documenting such non-germane
code is only compounding the error.
The most important code to comment is that put in for an important but
non-obvious reason .
Peter said:In fact, even the example Lew gives of a Stack is in reality
unlikely
to require specific handling. In particular, if you're actually
_done_ with the Stack, simply getting rid of the reference to the
Stack itself is sufficient for releasing all the objects that the
Stack itself references.
Mike said:We were specifically discussing the case where it is necessary,
because the variable won't go out of scope anytime soon. This can
also occur with nested scopes within a method, since variables within
them don't go "out of scope" for GC purposes until the method returns.
Peter said:Whether those you named disagree with me depends on what they consider a
bug-free implementation of a stack.
I would say that a stack implementation that retains a reference to an
object popped or otherwise cleared from the stack is not bug-free.
But yes, if you're dealing with a buggy stack implementation, you might
have to go to extra work to ensure your popped object really is no
longer referenced by the stack. What that "extra work" might be would
depend on the implementation, but in the most obvious case would involve
pushing and then immediately popping a null reference.
My comments are all intended to be in the context of assuming a bug-free
implementation. YMMV.
Lew said:That sounds like it would be better fixed by properly scoping the
variable than by a null-assignment hack. In the specific discussion
to which you refer, that was the answer in fact; Tom Anderson
discussed how his project solved it by a far better means than the
null-assignment hack.
In all JVM implementations? In the presence of Hotspot? Forever
more?
Normally the source should not make assumptions specific to a
particular version of the JVM.
In the case of a putative
optimization, there should be measurement and evidence first,
re-evaluation of the algorithm second, and micro-optimization third.
Tom Anderson's anecdote was a good example; it showed how changing
the algorithm solved the measured performance problem without
resorting to implementation-specific hacks.
Why? I'd think
document = null; // Allow the document to be collected
makes the intent clearer than
doInit();
giving the reader no clue why that part of the initialization logic
was put into a seperate method.
Peter said:[...]My comments are all intended to be in the context of assuming a
bug-free implementation. YMMV.
And my comments are all intended to be in the context of one writing
that implementation to ensure that clients may safely make that
assumption.
You should have made that clear from the outset then. Your statement
was: "when you have hidden references to an object, such as in a
collection like a Stack, those references keep an object alive even
after the program is through with it".
You wrote "a collection like a Stack", not "an implementation of a
stack". The built-in Stack class surely does not have that particular bug.
Frank Cisco said:If you null and object ie. obj = null, when is it cleared from memory?
Immediately or at the next garbage collection?
Peter said:And frankly, I could have tolerated the comments, except that
you insisted on making it about how what I had written was _wrong_,
when in fact nothing I wrote was wrong.
Peter said:The reason that one does not normally need to be concerned is that what's
important is whether the object is reachable, not whether references to it
exist. You can have a very complicated data structure, but which is
referenced at the root by a single object reference. Once you're done
with that data structure, there's no need to traverse it, nulling out
references. As long as the root reference is discarded (which may in fact
involve nulling out a single reference), the rest of the data structure is
no longer reachable, and thus is automatically eligible for garbage
collection with no special effort from the program.
Frank Cisco said:If you null and object ie. obj = null, when is it cleared from memory?
Immediately or at the next garbage collection?
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.