JVM系列
1.JVM運(yùn)行機(jī)制的整體脈絡(luò)
2.JVM的分代模型及對象流動
3.常見的垃圾回收器及算法
4.ParNew和CMS的工作原理
1.哪些變量引用不能回收
被GC Roots引用的變量不能被回收伶选,GC Roots有方法的局部變量尖昏,類的靜態(tài)變量构资。
2.不同的引用類型
- 強(qiáng)引用:一般都是我們直接new的對象,不會被回收迹淌。
- 軟引用: 一般不會被回收唉窃,但回收后內(nèi)存不夠存放新對象的時候再回收纹笼。
- 弱引用: 垃圾回收時就會進(jìn)行回收背镇。
-
虛引用: 一般不用笋额。
如下代碼:
//強(qiáng)引用
User user = new User();
//軟引用
SoftReference<User> softUser = new SoftReference<User>(new User());
//弱引用
WeakReference<User> weakUser = new WeakReference<>(new User());
3.新生代的復(fù)制算法
-
復(fù)制算法的介紹(適用于存活率低的時候使用。存活高時茉盏,大量對象復(fù)制厦滤,效率低)
把新生代內(nèi)存分為同等大小的兩塊內(nèi)存歼狼,程序運(yùn)行時斷地先在一塊創(chuàng)建對象羽峰,直到放不下了,這時觸發(fā)垃圾回收值纱。就在第一塊內(nèi)存存活的對象復(fù)制到另一塊內(nèi)存中坯汤,如下圖:
上面的復(fù)制算法惰聂,優(yōu)點(diǎn)是解決了內(nèi)存碎片問題咱筛,缺點(diǎn)內(nèi)存利用率太低迅箩,只有50%饲趋。那么JAVA是怎么優(yōu)化的呢撤蟆?
-
復(fù)制算法的優(yōu)化
新生代的對象特點(diǎn)的生命周期短,大部分對象可能某個方法運(yùn)行完就失去引用了爵川,那么每次回收存活下來的對象可能就1%息楔。那么JVM重新把新生代分成了1個Eden,2個Survivor區(qū),比例為8:1:1圃泡。每次對象創(chuàng)建在Eden區(qū)颇蜡,當(dāng)?shù)谝淮位厥諘r辆亏,把回收對象放在S1區(qū)。第二次回收時缤弦,把Eden和S1一起回收彻磁,把回收對象放到S2,這時清空前者。過程如下圖:
已經(jīng)把內(nèi)存的使用率提高到90%了。
4.什么時候?qū)ο髸M(jìn)入老年代
- 每次對象在S區(qū)轉(zhuǎn)移一次磁浇,年齡就會加1,那么當(dāng)對象年齡達(dá)到15歲時无虚,在第16次回收時骑科,這些對象會進(jìn)行老年代。年齡通過-XX:MaxTenuringThreshold設(shè)置梁棠,默認(rèn)為15斗埂。
- 動態(tài)年齡判斷:當(dāng)S區(qū)有一批對象大小大于S區(qū)總大小的50%,那么大于等于該年齡的對象全總轉(zhuǎn)移到老年代男娄。運(yùn)行時的邏輯漾稀,年齡1+年齡2+...+年齡n的對象大于S區(qū)內(nèi)存50%崭捍,那么大于年齡n的對象轉(zhuǎn)移到老年代。注意:S區(qū)指s1區(qū)或s2區(qū)其中一塊实夹。
- 大對象直接進(jìn)入老年代粒梦,通過-XX:PretenureZiseThreshold,避免大對象在年輕代來回復(fù)制,影響效率缴淋。
- minor gc后對象太多昼蛀,S區(qū)放不下圆存,對象進(jìn)入老年代。這里面包括下面的空間分配擔(dān)保規(guī)則判斷夫植。
5.老年代空間分配擔(dān)保規(guī)則
1.minor gc 之前,會判斷老年代剩余內(nèi)存大小是否大于年輕代總內(nèi)存大小延欠。因為有可能minor gc后所有對象都存活由捎。
-- 如果老年代剩余內(nèi)存大于年輕代總內(nèi)存大小饿凛,直接進(jìn)行minor gc。
-- 如果老年代剩余內(nèi)存小于年輕代總內(nèi)存大小心肪,則判斷-XX:HandlePromotionFailure有沒設(shè)置纠吴。沒設(shè)置直接進(jìn)行Full gc。
2.設(shè)置了-XX:HandlePromotionFailure參數(shù)
-- 判斷老年代大小是否大于年輕代minor gc后進(jìn)入老年代的平均大小固该。
-- 如果小于的話蹬音,則進(jìn)行Full GC
3.如果大于的話休玩,則進(jìn)行minor gc,當(dāng)minor gc后,會有以下幾種情況永部。
- 存活對象大小小于S區(qū)呐矾,則直接進(jìn)入S區(qū)。
- 存活對象大于S區(qū)组橄,小于老年代內(nèi)存罚随,則進(jìn)入老年代淘菩。
- 存活對象大于S區(qū)和老年代內(nèi)存,則進(jìn)行Full GC
4.當(dāng)Full GC 后狭郑,老年代還是不夠內(nèi)存存放minor gc 后的對象,則直接報OOM內(nèi)存溢出錯誤脏答,內(nèi)存實(shí)在不夠了亩鬼。
5.當(dāng)老年代內(nèi)存占用比例達(dá)到-XX:CMSInitiatingOccupancyFaction比例,默認(rèn)92%丛肮,也會自動觸發(fā)Full GC
邏輯圖如下:
6.老年代使用什么回收算法
- 標(biāo)記-整理算法:先把存活的對象標(biāo)記出來宝与,然后再移動到一邊去习劫,最后把邊界以外的全部清空嚼隘。
7.垃圾回收器的簡單介紹
Serial和Serial Old 垃圾回收器,分別回收年輕代和老年代谤狡,單線程工作卧檐,當(dāng)回收的時候,我們的工作線程全部停止捕仔。
Par New和CMS垃圾回收器盈罐,Par New用于新生代,CMS用于老年代钓葫,多線程工作湾揽,一般是現(xiàn)在生產(chǎn)上的標(biāo)配库物。
G1垃圾回收器,全新的垃圾回收器,統(tǒng)一收集新生代和老年代诱告,更優(yōu)秀的設(shè)計和性能民晒,最大好處可以設(shè)置系統(tǒng)停頓時間。
8.JVM調(diào)優(yōu)的目的
盡可能讓對象者在新生代分配和回收靴姿,盡量別讓太多對象頻繁地進(jìn)入老年代磁滚,避免頻繁的老年代回收,分配充足的內(nèi)存給新生代维雇,盡量避免新生代頻繁回收吱型。