對(duì)于大多數(shù)應(yīng)用,Java 堆是 Java 虛擬機(jī)管理的內(nèi)存中最大的一塊,被所有線程共享。此內(nèi)存區(qū)域的唯一目的就是存放對(duì)象實(shí)例,幾乎所有的對(duì)象實(shí)例以及數(shù)據(jù)都在這里分配內(nèi)存。
為了進(jìn)行高效的垃圾回收,虛擬機(jī)把堆內(nèi)存邏輯上劃分成三塊區(qū)域(分代的唯一理由就是優(yōu)化 GC 性能):
1、新生帶(年輕代):新對(duì)象和沒達(dá)到一定年齡的對(duì)象都在新生代
2、老年代(養(yǎng)老區(qū)):被長(zhǎng)時(shí)間使用的對(duì)象,老年代的內(nèi)存空間應(yīng)該要比年輕代更大
Java 虛擬機(jī)規(guī)范規(guī)定,Java 堆可以是處于物理上不連續(xù)的內(nèi)存空間中,只要邏輯上是連續(xù)的即可,像磁盤空間一樣。實(shí)現(xiàn)時(shí),既可以是固定大小,也可以是可擴(kuò)展的,主流虛擬機(jī)都是可擴(kuò)展的(通過 -Xmx 和 -Xms 控制),如果堆中沒有完成實(shí)例分配,并且堆無(wú)法再擴(kuò)展時(shí),就會(huì)拋出 OutOfMemoryError 異常。
年輕代 (Young Generation)
年輕代是所有新對(duì)象創(chuàng)建的地方。當(dāng)填充年輕代時(shí),執(zhí)行垃圾收集。這種垃圾收集稱為 Minor GC。年輕一代被分為三個(gè)部分——伊甸園(Eden Memory)和兩個(gè)幸存區(qū)(Survivor Memory,被稱為from/to或s0/s1),默認(rèn)比例是8:1:1。
1、大多數(shù)新創(chuàng)建的對(duì)象都位于 Eden 內(nèi)存空間中;
2、當(dāng) Eden 空間被對(duì)象填充時(shí),執(zhí)行Minor GC,并將所有幸存者對(duì)象移動(dòng)到一個(gè)幸存者空間中;
3、Minor GC 檢查幸存者對(duì)象,并將它們移動(dòng)到另一個(gè)幸存者空間。所以每次,一個(gè)幸存者空間總是空的;
4、經(jīng)過多次 GC 循環(huán)后存活下來(lái)的對(duì)象被移動(dòng)到老年代。通常,這是通過設(shè)置年輕一代對(duì)象的年齡閾值來(lái)實(shí)現(xiàn)的,然后他們才有資格提升到老一代。
老年代(Old Generation)
舊的一代內(nèi)存包含那些經(jīng)過許多輪小型 GC 后仍然存活的對(duì)象。通常,垃圾收集是在老年代內(nèi)存滿時(shí)執(zhí)行的。老年代垃圾收集稱為 主GC(Major GC),通常需要更長(zhǎng)的時(shí)間;
大對(duì)象直接進(jìn)入老年代(大對(duì)象是指需要大量連續(xù)內(nèi)存空間的對(duì)象)。這樣做的目的是避免在 Eden 區(qū)和兩個(gè)Survivor 區(qū)之間發(fā)生大量的內(nèi)存拷貝。