轉(zhuǎn)載、引用請(qǐng)標(biāo)明出處
http://www.reibang.com/p/7c6c9507e48f
本文出自zhh_happig的簡(jiǎn)書博客羞延,謝謝
以下內(nèi)容伴箩,是本人學(xué)習(xí)的筆記和工作中的總結(jié),僅供大家參考棺蛛,有誤的地方還請(qǐng)指正
一 Java內(nèi)存分配:分代分配
對(duì)象將根據(jù)存活的時(shí)間被分為:
- 年輕代(Young Generation)
- 年老代(Old Generation)
- 永久代(Permanent Generation,也就是方法區(qū))
1 年輕代(Young Generation)
- 對(duì)象被創(chuàng)建時(shí)桦踊,內(nèi)存的分配首先發(fā)生在年輕代(大對(duì)象可以直接被創(chuàng)建在年老代)终畅,大部分的對(duì)象在創(chuàng)建后很快就不再使用声离,于是被年輕代的GC機(jī)制清理掉(IBM的研究表明,98%的對(duì)象都是很快消亡的)术徊,這個(gè)GC機(jī)制被稱為Minor GC或叫Young GC赠涮。注意,Minor GC并不代表年輕代內(nèi)存不足斜友,它事實(shí)上只表示在Eden區(qū)上的GC垃它。
- 年輕代上內(nèi)存分配
- 年輕代可以分為3個(gè)區(qū)域:Eden區(qū)(首次分配的區(qū)域)和兩個(gè)存活區(qū)from、to(Survivor 0 洛史、Survivor 1:大小相等)
- 內(nèi)存分配過程為絕大多數(shù)剛創(chuàng)建的對(duì)象會(huì)被分配在Eden區(qū)酱吝,其中的大多數(shù)對(duì)象很快就會(huì)消亡务热。Eden區(qū)是連續(xù)的內(nèi)存空間,因此在其上分配內(nèi)存極快
- 最初一次捆毫,當(dāng)Eden區(qū)滿的時(shí)候该镣,執(zhí)行Minor GC响谓,將消亡的對(duì)象清理掉娘纷,并將剩余的對(duì)象復(fù)制到一個(gè)存活區(qū)Survivor0(此時(shí)跋炕,Survivor1是空白的,兩個(gè)Survivor總有一個(gè)是空白的)遏插,清空Eden區(qū)
- 下次Eden區(qū)滿了纠修,再執(zhí)行一次Minor GC扣草,將消亡的對(duì)象清理掉,將存活的對(duì)象復(fù)制到Survivor1中鹰祸,然后清空Eden區(qū)密浑,將Survivor0中消亡的對(duì)象清理掉,將其中可以晉級(jí)的對(duì)象晉級(jí)到老年代區(qū)街图,將存活的對(duì)象也復(fù)制到Survivor1區(qū)懒构,然后清空Survivor0區(qū)痴脾;
- 當(dāng)兩個(gè)存活區(qū)切換了幾次之后梳星,仍然存活的對(duì)象(其實(shí)只有一小部分,比如前域,我們自己定義的對(duì)象)韵吨,將被復(fù)制到老年代
- HotSpot虛擬機(jī)默認(rèn)切換15次,用-XX:MaxTenuringThreshold控制椿疗,大于該值進(jìn)入老年代
-
但這只是個(gè)最大值届榄,并不代表一定是這個(gè)值;每次Minor GC靖苇,Survivor中的存活對(duì)象的age都加1班缰,如果有一組age相同的對(duì)象贤壁,并且它們大于Survivor空間的一半,那么這一組對(duì)象都會(huì)被賦值到老年代埠忘,不一定要等到最大值
從上面的過程可以看出脾拆,Eden區(qū)是連續(xù)的空間,且Survivor總有一個(gè)為空给梅。經(jīng)過一次GC和復(fù)制假丧,將Eden區(qū)和一個(gè)Survivor中仍然存活的對(duì)象拷貝到另一個(gè)Survivor中,而Eden區(qū)和另一個(gè)Survivor區(qū)的內(nèi)容都不再需要了动羽,可以直接清空包帚,到下一次GC時(shí),兩個(gè)Survivor的角色再互換运吓。這種垃圾回收的方式就是著名的“停止-復(fù)制(Stop-and-copy)”清理法。
2 年老代(Old Generation)
- 對(duì)象如果在年輕代存活了足夠長(zhǎng)的時(shí)間而沒有被清理掉(即在幾次Young GC后存活了下來)拘哨,則會(huì)被復(fù)制到年老代
- 年老代的空間一般比年輕代大谋梭,能存放更多的對(duì)象,在年老代上發(fā)生的GC次數(shù)也比年輕代少倦青。當(dāng)年老代內(nèi)存不足時(shí)瓮床,將執(zhí)行Major GC,也叫 Full GC产镐。
- 對(duì)象比較大(比如長(zhǎng)字符串或大數(shù)組)隘庄,Young空間不足,則大對(duì)象會(huì)直接分配到老年代上
- 用-XX:PretenureSizeThreshold來控制直接升入老年代的對(duì)象大小癣亚,大于這個(gè)值的對(duì)象會(huì)直接分配在老年代上丑掺。
- 可能存在年老代對(duì)象引用新生代對(duì)象的情況,如果需要執(zhí)行Young GC述雾,則可能需要查詢整個(gè)老年代以確定是否可以清理回收街州,這顯然是低效的兼丰。
- 解決的方法是,年老代中維護(hù)一個(gè)”card table“唆缴,所有老年代對(duì)象引用新生代對(duì)象的記錄都記錄在這里鳍征。Young GC時(shí),只要查這里即可琐谤,不用再去查全部老年代蟆技,因此性能大大提高。
3 方法區(qū)(永久代)
- 常量池斗忌,類信息
- 無垃圾收集行為质礼,也可以被回收
二 Java GC機(jī)制:分代收集
1 年輕代--Young
- 每次進(jìn)行GC清理時(shí),將Eden區(qū)和一個(gè)Survivor中仍然存活的對(duì)象拷貝到 另一個(gè)Survivor中织阳,然后清理掉Eden和剛才的Survivor眶蕉。
- 由于絕大部分的對(duì)象都是短命的,甚至存活不到Survivor中唧躲,所以造挽,Eden區(qū)與Survivor的比例較大,HotSpot默認(rèn)是 8:1弄痹,即分別占新生代的80%饭入,10%,10%肛真,可通過jvm參數(shù)設(shè)置谐丢。
- 如果一次回收中,Survivor+Eden中存活下來的內(nèi)存超過了10%蚓让,則需要將一部分對(duì)象分配到 老年代乾忱。
- 用-XX:SurvivorRatio參數(shù)來配置Eden區(qū)域Survivor區(qū)的容量比值,默認(rèn)是8历极,代表Eden:Survivor1:Survivor2=8:1:1
2 老年代--Tenured
- 老年代存儲(chǔ)的對(duì)象比年輕代多得多窄瘟,而且不乏大對(duì)象,對(duì)老年代進(jìn)行內(nèi)存清理時(shí)趟卸,如果使用停止-復(fù)制算法蹄葱,則相當(dāng)?shù)托А?/li>
- 老年代一般用的算法是標(biāo)記-整理算法,即:標(biāo)記出仍然存活的對(duì)象(存在引用的)锄列,將所有存活的對(duì)象向一端移動(dòng)新蟆,以保證內(nèi)存的連續(xù)。
- 在年輕代發(fā)生Minor GC時(shí)右蕊,虛擬機(jī)會(huì)檢查每次晉升進(jìn)入老年代的大小是否大于老年代的剩余空間大小,如果大于吮螺,則直接觸發(fā)一次Full GC饶囚,所以老年代不經(jīng)常GC帕翻;可以看出年輕代發(fā)生Minor GC時(shí),內(nèi)存還是有空間的萝风;老年代發(fā)生Full GC時(shí)嘀掸,內(nèi)存已經(jīng)沒有空間了
- Full GC,對(duì)整個(gè)堆進(jìn)行整理规惰,包括Young睬塌、Tenured和Perm,所以Full GC比較慢歇万。頻繁Full GC影響性能揩晴,有如下原因可能導(dǎo)致Full GC
- 年老代被寫滿
- 永久代被寫滿
- System.gc()被顯示調(diào)用
-
在發(fā)生MinorGC前:先檢查老年代是否有連續(xù)空間,如下圖所示
- 大部分情況下都還是會(huì)將HandlePromotionFailure開關(guān)打開贪磺,避免Full GC過于頻繁硫兰,但是也增加了OutOfMemoryError的風(fēng)險(xiǎn)。
- JDK 6 Update 24之后的規(guī)則變?yōu)橹灰夏甏倪B續(xù)空間大于新生代對(duì)象總大小或者歷次晉升的平均大小就會(huì)進(jìn)行Minor GC寒锚,否則將進(jìn)行Full GC劫映。
3 方法區(qū)(永久代--Perm)
- 永久代的回收有兩種:常量池中的廢棄常量,無用的類信息刹前,常量的回收很簡(jiǎn)單泳赋,沒有引用了就可以被回收
- 對(duì)于無用的類信息進(jìn)行回收(類的卸載),必須保證3點(diǎn):
- 類的所有實(shí)例都已經(jīng)被回收
- 加載類的ClassLoader已經(jīng)被回收
- 類對(duì)象的Class對(duì)象沒有被引用(即沒有通過反射引用該類的地方)
- 永久代的回收并不是必須的喇喉,可以通過jvm參數(shù)來設(shè)置是否對(duì)類信息進(jìn)行回收
以上內(nèi)容祖今,是本人學(xué)習(xí)的筆記和工作中的總結(jié),僅供大家參考轧飞,有誤的地方還請(qǐng)指正
轉(zhuǎn)載衅鹿、引用請(qǐng)標(biāo)明出處
http://www.reibang.com/p/7c6c9507e48f
本文出自zhh_happig的簡(jiǎn)書博客,謝謝