I understand that when the Eden is full, a minor garbage collection is done. Surviving objects go to the survivol spaces. These objects will eventually arrive to the old generation.
Does the objects in the survivol spaces get garbage collected as well, or they will just be moved to the tenure generation and be GC there later (so the survivol spaces are no more than buffers for performance reasons)?
In other words, which one of the following algorithms is correct? NOTE: Let’s call YG to the Eden, OG the old generation, SE the survivol space that is (E)mpty at a given time, and SN the one that is (N)ot.
YG is full. Minor GC runs on it and survivors go to SE while objects from SN go to OG.
YG is full. Minor GC runs on it and survivors go to SN first until SN is full, and remaining YG survivors go to SE. SN, which is now full, runs its own GN and its survivors go to OG. If all YG survivors weren’t enough to make SN full, all YG survivors go to SN anyway but no GC runs on SN.
YG is full. Minor GC runs on it and SN together (regardless of whether SN is full or not). SN survivors go to OG. YG survivors go to SE.
NOTE: I have assumed that the number of YG survivors is never big enough as to fill SE more than once. What happens if, for instance, the number of YG survivors is twice or more the size of SE?
I found a documentation that explains it nicely.
The documentation from Oracle (https://www.oracle.com/webfolder/technetwork/Tutorials/obe/java/gc01/index.html) basically shows the same, although I find that documentation confusing because the first two images in the section “The Generational Garbage Collection Process” contain a partially filled survivor space, whereas the third image assumes the process started with two empty survivor spaces.
Please note that naming Eden as YG is misleading – the survivor spaces are also part of the young generation.
Basically the steps are:
Eden is full. Minor GC runs on YG, survivors (from Eden and from SN) go to SE.
Survivors from Eden now have a generation count of 1, survivors from SN have their generation count incremented.
Survivors with a generation count above some threshold are not copied to SE but to the old generation.
What happens if SE is too small? https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/sizing.html explains this case:
If survivor spaces are too small, copying collection overflows directly into the tenured generation.
I found no documentation for the following claim, but it seems reasonable that copying into SE starts with live objects from Eden and the live objects from SN are copied last. This way if an overflow occurs chances are that the overflowing objects are from SN (i.e. already older objects that have a higher chance of being promoted anyway.)