14

In Java, is there a way to mark an object for garbage collection by the GC, during its next clean up cycle?

I've heard that setting an object to null no longer works.

Jonny Henly
  • 4,023
  • 4
  • 26
  • 43
monksy
  • 14,156
  • 17
  • 75
  • 124
  • 2
    Could you provide some links or documentation regarding why setting the object to `null` would not work? Of course, setting to `null` won't guarantee that it will be gc'ed ever either. – Victor Parmar Mar 16 '11 at 20:41
  • 1
    As soon as you eliminate all references to an object (for example by setting a reference to `null`) it becomes *eligible* for garbage collection. You will not run out of memory before that memory is reclaimed (assuming it makes the difference between running out of heap space and not running out of heap). When that GC actually happens is up to the VM. Why does it concern you? – Mark Peters Mar 16 '11 at 20:49
  • 2
    Its a concern because I'm dealing with a large amount of objects, that contain a fair amount of data. Allocation usually comes in the 1000s at a time. – monksy Mar 16 '11 at 20:54

4 Answers4

11

No, you can't. What would you expect to happen if another variable had a reference to it?

Note that you can't set an object to null - you can only set a variable to null. If another variable still has a reference to the object, it will still not be eligible for garbage collection.

If you think you need to do this, that probably means you're misinterpreting your data - or that you may have a leak somewhere in your code (e.g. a list which you only ever add entries to, referenced by a static variable - those entries will never be eligible for garbage collection while the classloader is alive).

Each JVM has its own GC, but in Hotspot an object will be garbage collected next time the GC runs over the generation that object currently "lives" in (assuming it doesn't have a finalizer, which complicates things). If the object is in a "young" generation, that will probably happen quite soon - if it's in an "old" generation it may well take longer.

You may want to see the Java 6 GC tuning documentation for more information, although of course things have moved on since then for OpenJDK 7 etc.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Well as I said in a comment I'm creating lots and lots of objects, and after I'm done processing, I don't need them anymore. I have a suspicion [supported by the profiler] that they aren't getting destoried. – monksy Mar 16 '11 at 20:56
  • @monksy: Then that suggests you've got a reference to them lurking somewhere, assuming the GC is running at all. – Jon Skeet Mar 16 '11 at 21:01
  • 1
    Thats my suspicion [The amount of objects currently initiated rarely ever drops it keeps growing] Are there any tools you would suggest that could help with this? I had to use Netbeans Profiler just to find this out. – monksy Mar 17 '11 at 00:04
  • @monksy: I'm afraid I don't have any advice there - I haven't used a Java profiler for ages :( – Jon Skeet Mar 17 '11 at 06:23
  • There are valid use cases where you need to do this. For example if you're writing an in memory cache, you might want to preiodically remove less used entries to avoid memory leaks, but instead of setting entry to null you can make it a soft reference, that way after cleanup object will still be available until garbage collection – Ben Jan 14 '21 at 13:14
7

I know this question has been answered, but there are ways you can manipulate the way that the Java Garbage collector looks at your references. You can do this through Soft References, Weak References, and Phantom References. Take a look at the java.lang.ref package for a better explanation.

Also here's a nice sample to determine when a PhantomReference is about to be garbage collected:

A phantom reference is used to determine when an object is just about to be reclaimed. Phantom references are safer to use than finalization because once an object is phantom reachable, it cannot be resurrected.

// Create the phantom reference.
ReferenceQueue rq = new ReferenceQueue();
PhantomReference pr = new PhantomReference(object, rq);

// Wait until the object is about to be reclaimed.
try {
    while (true) {
        Reference r = rq.remove();
        if (r == pr) {
            // The object is about to be reclaimed.
            // Clear the referent so that it can be reclaimed.
            r.clear();
        }
    }
} catch (InterruptedException e) {
}
Sadeq Dousti
  • 3,346
  • 6
  • 35
  • 53
jluzwick
  • 2,005
  • 1
  • 15
  • 23
  • This was also interesting as well: http://weblogs.java.net/blog/2006/05/04/understanding-weak-references – monksy Mar 17 '11 at 14:36
4

The Java Garbage Collector works with a mark and sweep method. This means from object that are known to still be in used all references are followed and the objects that are visited in that way are marked. In that way objects with no references at all are not marked and should be sure to be deleted. So you could ensure that all references to this object are removed, so that in the next turn of the Garbage Collector, the item is deleted.

Additionally you could use

Runtime.getRuntime().gc();

to indicate that the Garbage Collector should run. Note: you can't be sure that it really runs.

RoflcoptrException
  • 51,941
  • 35
  • 152
  • 200
  • The garbage collector is not based on reference counting. All modern JVMs are mark-and-sweep, most of them multi-generational. – Mike Samuel Mar 16 '11 at 20:45
  • Doesn't it depend on the implementation of the JVM? – RoflcoptrException Mar 16 '11 at 20:46
  • No. Reference counting will not allow you to correctly implement the Java language specification because of problems with reference cycles. So not only does no existing JVM implementation use reference counting, none can and be conformant without also implementing an entirely different and correct collection mechanism. – Mike Samuel Mar 16 '11 at 20:47
  • @Mike Samuel. Ok I see. I changed my answer. – RoflcoptrException Mar 16 '11 at 20:50
3

You heard wrong, but then again the description is wrong too.

You don't set an object to null, you set a variable to null. If the variable can be used to get to an object, then the variable has a reference to the object. Setting the variable to null is the same as the variable "losing the reference" to the object.

Once Java detects that an object, or a group of objects can't be reached by the running program, it will remove those objects from memory. It won't remove them from memory one moment sooner, because if it did, and some other part of the program tried to use a reference to the object, then the reference would fail in a way that's not permissible in Java.

The trick is not to set just one reference to null, you have to set all the references that might have been made to null. That's why it's important to consider each time you create a new reference, because you want to create them in such a manner that they will eventually be cleared (unless you want a memory leak).

Jonny Henly
  • 4,023
  • 4
  • 26
  • 43
Edwin Buck
  • 69,361
  • 7
  • 100
  • 138