开发者

How far will the GC go

How far will the Java GC go? Lets say I have this code:

public class MyClass {
    private Object myObject = new Object();
    public void clear() {
        myObject = null;
    }
}

public class MyMain {
    ...
    MyClass myClass = new MyClass();
    ...
    myClass.clear();
   开发者_高级运维 myClass = null;
}

Do I need to call myClass.clear() before setting myClass to null to be sertain the GC will delete myObject inside myClass? Or is it enough to set myClass to null and the GC will delete all nested objects?

Maybe I'm a bit paranoid and the answer is as easy as "The GC will eventually delete any objects that is not reachable by any running code or any future available code". So if a created object is not available, or never will be available, in any running code, it will eventually be a victim of the GC even thought it is nested and makes a C++ programmer scared?


No, you don't need to call myClass.clear(). When there is no way of reaching an object via live references, it will be eligible for garbage collection. That doesn't mean it'll be collected straight away, but it will be eligible for collection.

It's very rarely appropriate to set references to null for the sake of garbage collection - and it hurts the readability of your code to do so. There are exceptions to this, of course - for example, ArrayList<T> will set an element of its internal buffer to null when it's no longer needed, in order to avoid accidentally preventing the object from being garbage collected - but usually the fields within an object are valid and useful for as long as the object itself is required. In short, I would almost never even write a method like MyClass.clear(), let alone call it.

It's rarely worth setting local variables to null either. Your code in MyMain isn't clear, because it's not valid outside a method... if you meant all of the code to be in a method then you don't need to set myClass to be null either. When the method finishes, the variable will no longer contribute as a GC root for the object it was referring to - of course, if other GC roots exist, the object still won't be eligible for garbage collection. However, setting a local variable to null at the end of a method is pointless.


You don't need to set anything to null in order for it to be GC'd. Don't be paranoid.

Don't try to program Java like C++.


"Helping" gc through reference nulling is rarely really needed.

Here is an artificial case where nulling does help:

    long[] arr = new long[7000000];
    //arr = null;
    arr = new long[7000000];

If you run this with -Xmx100M,it will fail with OutOfMemoryError. If you uncomment the line that makes arr null, it will work fine. This happens because arr reference is still holding the huge array while another one is being created. The memory allocation occurs before the assignment, it triggers a garbage collection, and it fails. When nulling the reference, the GC succeeds making enough space.


No, you don't need to call clear first. The GC will happily find the unused myObject reference and reclaim it.

In fact, the GC can handle quite complex object graphs, including circular references:

public class Foo
{
    public HashMap a;
    public HashMap b;

    public Foo() {
        a = new HashMap();
        b = new HashMap();
        a.put("b", b);
        b.put("a", a);
    }
}
// ...
public void someFunction() {
   Foo f = new Foo();
}

(I wouldn't normally make a and b public, but I'm trying to be extreme-ish here.)

You don't have to clear f, or a, or b. If nothing is referencing f, eventually f will be checked for reachability, and the GC won't have an issue with the fact that a and b mutually reference each other.

Details (lots and lots of details) in the JLS.


Yes, you're being overly paranoid. As long as an object is not reachable by running code, it will be collected eventually (though "eventually" may mean "when the program exits", if there's plenty of memory and the GC doesn't need to run). References within unreachable objects aren't reachable either, so they don't count anymore as far as the GC's concerned.

Note, though, that this means that finalize might have already run in your sub-objects, so you can't rely on any sub-stuff that isn't a primitive if you want to do any work in a finalizer.


The GC will eventually dispose of the objects correctly. I think you may be a bit too paranoid. Although it does not hurt to set the object to null.

And to answer your question if you've called myObject.clear which just does myObject = null then there is no reason to reset it to null again.


You don't even need to set myclass to null. Once it falls out of scope it is eligible for garbage collection.


The GC will dispose of everything that has no reference to it left. So, after MyClass is disposed of, there will be no reference left to myObject and hence it will be removed by the GC


Do I need to call myClass.clear() before setting myClass to null to be sertain the GC will delete myObject inside myClass?

You don't have to call clear, nor set myClass to null.

You cannot be certain it will be collected either, but if the VM needs memory, it will be elegible when myClass it self is not referenceable.

So you don't need to worry in this case.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜