先附一段對新生代中複製算法較好的理解:
首先得明白複製算法的思想:
將原有的內存空間劃分成兩塊,每次只使用其中一塊,在垃圾回收的時候,將正在使用的內存中的存活對象複製到另一塊內存區域中,然後清除正使用過的內存區域,交換兩個區域的角色,完成垃圾回收。然後為什麼要在新生代中使用複製算法:
因為新生代gc比較頻繁、對象存活率低,用複製算法在回收時的效率會更高,也不會產生內存碎片。但複製算法的代價就是要將內存摺半,為了不浪費過多的內存,就劃分了兩塊相同大小的內存區域survivor
from和survivor to。在每次gc後就會把存活對象給複製到另一個survivor上,然後清空Eden和剛使用過的survivor。
以上引用自:https://www.zhihu.com/question/44929481/answer/98016105,上述回答解釋了:
- 為什麼新生代要在標記清除死亡對象後使用複製算法,而不是標記清除死亡對象後進行壓縮整理以消除內存碎片(此處內存碎片是死亡對象之前所佔用的空間)。
- 新生代使用複製算法存在的缺陷,由於使用了複製算法,每次只能使用 1/2 的空間,可使用的內存空間變成了 1/2。
- 由於存在 2. 中描述的缺陷,要想辦法優化,讓複製算法中可使用內存空間 > 1/2。優化辦法是從 eden 區 : survivor 區 = 1 : 1,變為 eden 區 : survivor 區 = 8 : 2,這樣可使用內存空間就變成了 8/10。但是這樣在下一次 Young GC 後,存活對象移動到 survivor 區,我們的可使用區域只有 2/8,太小了。
- 繼續優化 3. 中描述的問題,我們把新生代分為 eden 區 : survivor0(from) : survivor1(to) = 8 : 1 : 1,每次新生代對象在 eden 區創建,上一次 GC 存活的對象在 from 區,下次 GC 時要移動的對象是 eden 區和 from 區中存活的對象,移動至 to 區,然後 from 區和 to 區身份交換。這樣我們新生代可使用的內存空間就有 9/10(eden + from) 了。
上述解決方案的演進為 "JVM 新生代為什麼要有兩個 survivor(from, to) 區" 的原因。