Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java garbage collector - When does it collect?

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?

like image 510
nalo Avatar asked Oct 17 '09 13:10

nalo


People also ask

How does Java know when to garbage collect?

As long as an object is being referenced, the JVM considers it alive. Once an object is no longer referenced and therefore is not reachable by the application code, the garbage collector removes it and reclaims the unused memory.

Does Java garbage collection happen automatically?

Java garbage collection is an automatic process. The programmer does not need to explicitly mark objects to be deleted. The garbage collection implementation lives in the JVM. Each JVM can implement garbage collection however it pleases; the only requirement is that it meets the JVM specification.

How often is garbage collected in Java?

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.

When exactly JVM runs garbage collector?

Application allocates new objects into Eden and some objects in the Survivor 0 space become unreachable. After Eden is full again, JVM tries to allocate space to Eden. It fails and triggers the Minor GC to run again. The new reachable objects are moved from Eden to Survivor 1.


2 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.

like image 145
jalf Avatar answered Sep 21 '22 05:09

jalf


  • 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/

like image 38
Xinus Avatar answered Sep 22 '22 05:09

Xinus