Below is an example of this. To start with, we have an empty managed heap (no objects). The entire heap is considered Generation 0, since we haven’t yet done a garbage collection.

We now allocate three Dog objects on the heap. They are allocated in the first available space within Gen 0.

We now set the yourDog reference to null, so that Jack is no longer referenced. Before garbage collection, the heap looks like this:

Assume that a GC pass runs now and collects objects in Gen 0 (the only generation available). Memory for Jack is released, everything in Gen 0 is compacted, and whatever remains is marked as Gen 1. Gen 0 now starts again at the free space pointer.

Assume that we run for a while and allocate a couple more Dog objects–Lassie and Rin Tin Tin. Then assume that the reference to Lassie is removed and that the reference to Ruby is also removed. Before collection, the heap looks as follows. Notice that there are unreachable objects in both Gen 0 and Gen 1.

Assume that a garbage collection now runs and collects only Gen 0. Memory for Lassie is reclaimed, Gen 0 is compacted and and its objects are promoted to Gen 1. The existing Gen 1, however, is not collected and its objects remain in Gen 1.

Finally, let’s assume that the garbage collection runs one more time. It begins with Gen 0, but there is nothing to collect. Let’s assume that there are high memory demands that cause the GC to decide to also collect Gen 1. It can now release memory for Ruby and then compacts Gen 1 and promotes its surviving objects to Gen 2.