What is it that determines when the garbage collector actually collects? Does it happen after a certain time or after a certain amount of memory have been used up? Or are there other factors?
6 Answers
It runs when it determines that it is time to run. A common strategy in generational garbage collectors is to run the collector when an allocation of generation-0 memory fails. That is, every time you allocate a small block of memory (big blocks are typically placed directly into "older" generations), the system checks whether there's enough free space in the gen-0 heap, and if there isn't, it runs the GC to free up space for the allocation to succeed. Old data is then moved to the gen-1 heap, and when space runs out there, the GC runs a collection on that, upgrading the data which has been there longest to the gen-2 heap, and so on. So the GC doesn't just "run". It might run on the gen-0 heap only (and most collections will do just that), or it might check every generation if it really has to free up a lot of memory (which is only necessary fairly rarely).
But this is far from the only strategy. A concurrent GC runs in the background, cleaning up while the program is running. Some GC's might run as part of every memory allocation. An incremental collector might do that, scanning a few objects at every memory allocation.
The entire point in a garbage collector is that it should just do its thing without requiring any input from the user. So in general, you can't, and shouldn't, predict when it'll run.
I believe Suns JVM gained a generational GC not too long ago (v1.6 maybe? I haven't coded Java for ages, so not sure on this, but I remember being surprised not too long ago, when one of the selling points for the new version was "a generational GC". Not least because .NET has had one since day 1.)
Other JVM's are of course free to pick whichever strategy they like.
EDIT: The above part about Java and generational GC is not true. See below for more details:
The 1.0 and 1.1 Virtual Machines used a mark-sweep collector, which could fragment the heap after a garbage collection. Starting with Java 1.2, the Virtual Machines switched to a generational collector, which has a much better defragmentation behavior (see Java theory and practice: Garbage collection and performance).
So Java actually has a generational GC for ages. What's new in Java 6 is the Garbage-First garbage collector (G1) that is available in Java 6u14. According to the article claiming the release in 1.6.0_14: It is not enabled by default. The parallel collector is still the default GC and is the most efficient GC for common household usage. G1 is meant to be an alternative for the concurrent collector. It is designed to be more predictable and enable fast allocation with memory regions design.

- 562,542
- 136
- 1,062
- 1,124

- 243,077
- 51
- 345
- 550
-
Java has a generational GC since JDK 1.3 (see e.g. here: http://www.javaworld.com/javaworld/jw-01-2002/jw-0111-hotspotgc.html ) – Johannes Weiss Oct 17 '09 at 17:27
-
1@Johannes Weiß No, it's since JDK 1.2. The 1.0 and 1.1 Virtual Machines used a mark-sweep collector, which could fragment the heap after a garbage collection. Starting with Java 1.2, the Virtual Machines switched to a generational collector, which has a much better defragmentation behaviour. See http://www.ibm.com/developerworks/library/j-jtp01274.html. – Pascal Thivent Oct 17 '09 at 18:24
-
@Pascal Thivent: Ok, the article I linked to said that JDK1.2 had an 'exact garbage collector' which was optimized and renamed to 'generational GC' in JDK 1.3 but you may be right... – Johannes Weiss Oct 17 '09 at 18:51
-
thanks for correcting me then. :) As I said, I haven't really followed Java development for ages. – jalf Oct 17 '09 at 22:23
-
Does this mean the garbage is only moved to a higher Gen, instead of really removing it? Is this endless? Or when is it completely removed? – Rafael Nov 24 '14 at 20:16
-
1@Mr.Goose no, when garbage is identified, it is freed. A generational GC means that the GC only checks for certain objects whether they are garbage. It frequently checks if any newly created objects (generation 0) can be freed. If an object survives long enough to reach a certain threshold, then it is put into generation 1, which means the GC won't check it during normal, fast, garbage collections. Every once in a while, the GC will look at gen1 objects to see if any of them can be released as garbage, and rarer still, it'll look at gen2 objects (up to however many generations the GC uses) – jalf Nov 25 '14 at 11:55
-
It is just an implementation of the heuristic that "if an object was just created, the odds are good it'll become garbage soon, so any time we need to free up memory, these should be the first objects we check. But if it's been alive for a long time, it'll probably *stay* alive for a long time. So checking up on it constantly would be inefficient" – jalf Nov 25 '14 at 11:56
-
1@S.R Lobato: this (pretty old, admittedly) question is typical for mistakenly thinking that “garbage has to be removed”. The generational GC will move all surviving objects from a memory space to another, which implies that everything remaining is either, unused memory or garbage, which does not need any additional action, as the memory space as a whole is now free, per definition. – Holger Oct 21 '16 at 11:33
-
1@jalf: older generations are not only traversed less frequently, the JVM also switches strategies. While young generations require traversal of all young references, the JVM will track changes of older generations, as old objects change less frequently, so the GC also can skip regions of old objects that haven’t changed since the last major GC, hence still reference the same objects as before. – Holger Oct 21 '16 at 11:36
- It depends on way program JIT compiled.
- From outside we cannot definitely tell when it will run.
- It follows some algorithm which depends on that particular GC.
- Java virtual machine runs on the client machine with some virtual memory in case of windows default is 4GB. It also depends on that free virtual memory at that particular time.
You can try this small program to check behavior of GC
public class GCTest {
final int NELEMS = 50000;
void eatMemory() {
int[] intArray = new int[NELEMS];
for (int i=0; i<NELEMS; i++) {
intArray[i] = i;
}
}
public static void main (String[] args) {
GCTest gct = new GCTest();
// Step 1: get a Runtime object
Runtime r = Runtime.getRuntime();
// Step 2: determine the current amount of free memory
long freeMem = r.freeMemory();
System.out.println("free memory before creating array: " + freeMem);
// Step 3: consume some memory
gct.eatMemory();
// Step 4: determine amount of memory left after consumption
freeMem = r.freeMemory();
System.out.println("free memory after creating array: " + freeMem);
// Step 5: run the garbage collector, then check freeMemory
r.gc();
freeMem = r.freeMemory();
System.out.println("free memory after running gc(): " + freeMem);
}
}
possible output -- May be different in your case
free memory before creating array: 4054912
free memory after creating array: 3852496
free memory after running gc(): 4064184
Check this link http://www.devdaily.com/java/edu/pj/pj010008/

- 29,617
- 32
- 119
- 165
-
output:free memory before creating array: 263777600 free memory after creating array: 263577584 free memory after running gc(): 14174392 . why shows less memory after running GC? – Yugraaj Sandhu Dec 11 '22 at 02:35
When the JVM doesn't have necessary memory space to run, the garbage collector will run and delete unnecessary objects to free up memory.
Unnecessary objects are the objects which have no other references (address) pointing to them.
There are mainly 4 ways an object can eligible for garbage collection.
Null Referencing
The garbage collector can delete an object when the reference variable of the object is assigned
null
as its value.A a = new A(); a = null;
Re-assigning
When another object is assigned to the reference variable of an object, the older referenced object can be deleted by the garbage collector.
A a = new A(100); a =new A(200);
Local Scope
If an object is created inside a block, then that object will be eligible for garbage collection outside that block.
if(condition){ A a = new A(); }
Isolation
An object can contain a reference to another object, but there must be at least one reference (address) variable for those objects in the stack, otherwise all those objects are eligible for garbage collection.
class A{ A r; A(int i){ //something } } A a1 = new A(100); a1.r = new A(101); a1.r.r = new A(102); a1.r.r.r = a1; a1 = null //all ojects are eligible to garbage collector

- 13
- 2

- 7,237
- 4
- 28
- 34
This completely depends on the actual JVM and what it chooses to do, and is basically out of your hands as a programmer. Greybearded die-hard experts may want to tell the JVM they know better, but for mere mortals this should be considered black magic better left alone.
What should concern you is if it can keep up with the rate that your programs creates and discards objects. If not your whole program is halted while global cleaning up occurs. That turns out to very bad response times, but happens rarely for modern JVM's on modern computers.
If you are curious about what happens in your program and when, then investigate the "jvisualvm" tool in the recent versions of the Java 6 JDK. It is really great for peeking inside.

- 73,784
- 33
- 194
- 347
The garbage collector runs when it needs resources and on a regular basis that you able to influence by telling when is a good time to spend CPU on collecting, using System.gc()
You can help the garbage collector by nulling references explicitly, for instance by giving your objects init()
methods that allocate resources and cleanup()
methods that explicitly clean up those resources and nulling their references. By nulling references yourself you prevent tye garbage collector from having to find clusters of obects that have to more paths to a root.

- 23,135
- 6
- 55
- 69
-
1For a modern gc, setting variables to null or not will make no difference and calling System.gc() is really almost always just stupid. – Fredrik Oct 17 '09 at 14:34
-
3@Fredrik, please don't use terms like "stupid". Setting variables to null is a good practice and it helps the garbage collect to execute in smalls steps instead of bigger chunks. (Mind you I talk about class attributes not temporary method variables on the stack.) As for calling System.gc() trivial applications need not bother with it, but large applications that get massive concurrent requests sometimes need it so smooth the collecting times keeping the application responsive at all times. – rsp Oct 17 '09 at 14:54
-
@rsp: The way GCs work it is almost always stupid or at least damaging for gc performance to call System.gc() and it doesn't help at all which is why it is a) not mandatory for the gc to even bother b) possible to turn it off to not be hit by code written by someone who think he is smarter than the gc algoritm. The reason it is still possible is because it is as I said "almost always" stupid, meaning there are a few places where you really might want to do it. Setting variables to null gives you nothing but more code, it will not affect the gc at all. – Fredrik Oct 17 '09 at 15:47
-
@rsp: For better understanding about why setting to null doesn't matter in most cases, take a look at the following blog posts. They are not perfect but good enough to explain it for a layman: http://chaoticjava.com/posts/how-does-garbage-collection-work/ and http://chaoticjava.com/posts/parallel-and-concurrent-garbage-collectors/ The only time nulling out something help is if the variable keeping the reference is going to stay alive whereas the referenced data is not needed anymore but that is sort of obvious and not at all like "null every reference yourself". – Fredrik Oct 17 '09 at 15:51
-
@FRerik, it's not a matter of thinking to be smarter, it's a matter of hinting the garbage collector "now is a good time to spend some CPU because I don't need it". The garbage collector can use the hint or ignore it, in my experience it can be the difference between an application server that runs smoothly and one that is unresponsive when it does get to do garbage collecting. I agree with you that most applications don't need it but it is good to know. Cleaning up your resources _DOES_ help. I spend months refactoring code from people who say it doesn't halving CPU usage in the process. – rsp Oct 17 '09 at 16:00
-
@rsp: well, it doesn't hurt you to null out references for no use so if you are happy doing it please continue doing so (I never said that part was stupid). Regarding System.gc() I think you need to either read up on how concurrent garbage collectors work or just look at the frequency of their work, doing so might give you a hint on how easily you will be able to hit the right millisecond with your "this is a good time to call the gc". The following link is what JRockit say about it and both Sun and IBM share that view: http://tinyurl.com/yfh32sm – Fredrik Oct 17 '09 at 16:11
-
I do know how garbage collectors work, its just that sometimes with high volumes of traffic they tend to postpone collecting until they need to do too much in one step getting in the way of business. Funny you mentioned IBM. I recall one particular instance involving their code on their application server, JVM and OS that would hickup if the garbage collector wasn't hinted. – rsp Oct 17 '09 at 18:43
-
@rsp: Ok. I can assure you that even IBM have decent garbage collectors nowadays. You shouldn't be too afraid of its JVMs just because you were once hit. – Fredrik Oct 17 '09 at 19:05