1、對(duì)象是否存活
1.1 可達(dá)性分析算法
(1) java是通過(guò)可達(dá)性分析來(lái)判定對(duì)象是否存活:通過(guò)GC Roots的對(duì)象作為起始點(diǎn)向下搜索,搜索走過(guò)的路徑稱為引用鏈,當(dāng)一個(gè)對(duì)象到GC Roots沒(méi)有任何引用鏈相連時(shí),證明該對(duì)象不可用届谈。如上圖所示,Object5和Object6到GC Roots沒(méi)有引用鏈弯汰,它們將被判定為可回收對(duì)象
(2) 可作為GC Roots的對(duì)象包括:
虛擬機(jī)棧(棧幀中的本地變量表)中引用的對(duì)象
方法區(qū)中靜態(tài)屬性引用的對(duì)象
方法區(qū)中常量引用的對(duì)象
本地方法棧中JNI(即一般說(shuō)的Native方法)引用的對(duì)象
1.2 引用概念的擴(kuò)充
(1) 強(qiáng)引用:類似Object obj = new Object()的引用艰山,只要強(qiáng)引用還在,永遠(yuǎn)不會(huì)被GC回收
(2) 軟引用:通過(guò)SoftReference實(shí)現(xiàn)軟引用咏闪,虛擬機(jī)將要拋出OutOfMemoryError異常之前程剥,將會(huì)發(fā)起一次GC動(dòng)作,回收掉所有非強(qiáng)引用的對(duì)象
(3) 弱引用:通過(guò)WeakReference實(shí)現(xiàn)弱引用,比軟引用更弱织鲸,無(wú)論當(dāng)前內(nèi)存是否足夠,都會(huì)回收掉被弱引用關(guān)聯(lián)的對(duì)象
(4) 虛引用:通過(guò)PhantomReference實(shí)現(xiàn)虛引用溪胶,最弱的一種引用搂擦,唯一作用是該對(duì)象回收時(shí)收到一個(gè)通知
1.3 對(duì)象的自我拯救 - finalize方法
被虛擬機(jī)判定為不可達(dá)的對(duì)象,還有一次拯救自己的機(jī)會(huì)哗脖。如果對(duì)象在進(jìn)行可達(dá)性分析后發(fā)現(xiàn)沒(méi)有與GC Roots相連接的引用鏈瀑踢,將會(huì)被第一次標(biāo)記,并進(jìn)行一次篩選才避,如果該對(duì)象沒(méi)有重寫finalize()方法橱夭,或者finalize()方法被虛擬機(jī)調(diào)用過(guò),將視為不必執(zhí)行桑逝。
如果被判定為有必要執(zhí)行finalize()方法棘劣,該對(duì)象將會(huì)放入F-Queue隊(duì)列,并在稍后由虛擬機(jī)自動(dòng)創(chuàng)建的楞遏、低優(yōu)先級(jí)的Finalizer線程去執(zhí)行茬暇,finalize()方法是對(duì)象逃脫死亡的最后一次機(jī)會(huì),如果對(duì)象在finalize()方法中重新和引用鏈建立連接寡喝,就可避免被回收糙俗。finalize()方法只會(huì)被系統(tǒng)自動(dòng)調(diào)用一次
1.4 方法區(qū)(永久代)的回收
(1) gc主要回收兩部分內(nèi)容:廢棄常量和無(wú)用的類≡蓿回收廢棄常量和回收堆中的對(duì)象類似巧骚。判定一個(gè)類是否無(wú)用,需同時(shí)滿足3個(gè)條件:一是該類的所有實(shí)例都被回收格二,二是加載該類的ClassLoader已被回收劈彪,三是該類對(duì)應(yīng)的java.lang.Class對(duì)象沒(méi)有在任何地方被引用
(2) HotSpot虛擬機(jī)通過(guò) -Xnoclassgc 參數(shù)進(jìn)行控制是否啟用類卸載功能。在大量使用反射蟋定、動(dòng)態(tài)代理粉臊、CGLib等框架,需要虛擬機(jī)具備類卸載功能驶兜,避免方法區(qū)發(fā)生內(nèi)存溢出
2扼仲、垃圾回收算法
2.1 標(biāo)記-清除(Mark-Sweep)算法
(1) 算法分為標(biāo)記和清除兩個(gè)階段:首先標(biāo)記出所有需要回收的對(duì)象,然后統(tǒng)一回收有標(biāo)記的對(duì)象
(2) 兩個(gè)不足:一是效率不高抄淑,二是會(huì)產(chǎn)生大量不連續(xù)的內(nèi)存碎片
2.2 復(fù)制(Copying)算法
(1) 新生代分為一個(gè)Eden屠凶,兩個(gè)Survival空間,默認(rèn)比例是8:1肆资〈@ⅲ回收時(shí),將Eden和一個(gè)Survival的存活對(duì)象全部放入到另一個(gè)Survival空間中,最后清理掉剛剛的Eden和Survival空間
(2) 當(dāng)Survival空間不夠時(shí)唉韭,由老年代進(jìn)行內(nèi)存分配擔(dān)保
2.3 標(biāo)記-整理(Mark-Compact)算法
標(biāo)記過(guò)程和“標(biāo)記-清除”算法類似夜涕,不同之處是讓所有存活的對(duì)象向一端移動(dòng),然后直接清理掉邊界以外的對(duì)象
2.4 分代收集(Generational Collection)算法
將堆分為新生代和老年代属愤,新生代對(duì)象存活率低女器,選用復(fù)制算法,老年代存活率高住诸,選用標(biāo)記-清除或標(biāo)記-整理算法
3驾胆、hotspot的算法實(shí)現(xiàn)
3.1 枚舉根節(jié)點(diǎn)
(1) 可達(dá)性分析時(shí),必須停頓所有java執(zhí)行線程(Stop The World)
(2) HotSpot通過(guò)OopMap記錄對(duì)象引用存放的地址贱呐,類加載完后丧诺,HotSpot把偏移量對(duì)應(yīng)的類型數(shù)據(jù)計(jì)算出來(lái),JIT編譯過(guò)程中奄薇,會(huì)在特定位置記錄下棧和寄存器中哪些位置是引用
3.2 安全點(diǎn)
(1) 程序執(zhí)行時(shí)驳阎,只有到達(dá)安全點(diǎn)才能停頓下來(lái)開始GC
(2) 安全點(diǎn)的選定以“是否讓程序長(zhǎng)時(shí)間執(zhí)行”為標(biāo)準(zhǔn),“長(zhǎng)時(shí)間執(zhí)行”最明顯的特征是指令序列復(fù)用惕艳,如方法調(diào)用搞隐、循環(huán)跳轉(zhuǎn)、異常跳轉(zhuǎn)等
(3) 采用主動(dòng)中斷的方式讓所有線程都跑到最近的安全點(diǎn)上停頓下來(lái)远搪。設(shè)置一個(gè)標(biāo)志劣纲,各個(gè)程序執(zhí)行的時(shí)候輪詢這個(gè)標(biāo)志,發(fā)現(xiàn)中斷標(biāo)志為真時(shí)自己就中斷掛起
3.3 安全區(qū)域
安全區(qū)域是指在代碼片段中谁鳍,引用關(guān)系不會(huì)發(fā)生變化癞季。在這塊區(qū)域任何地方GC都是安全的,可以把Safe Region看做是Safe Point的擴(kuò)展
4倘潜、垃圾回收器
上圖展示了7種作用于不同分代的收集器绷柒,如果兩個(gè)收集器之間存在連線,說(shuō)明它們可以搭配使用涮因,所處區(qū)域表示收集器屬于新生代還是老年代废睦。
4.1 Serial收集器
? ? ? ?Serial收集器是一款年輕代的垃圾收集器,使用標(biāo)記-復(fù)制算法养泡。它是一款歷史最悠久的垃圾收集器嗜湃。Serial收集器只能使用一條線程進(jìn)行垃圾收集工作,并且在進(jìn)行垃圾收集的時(shí)候澜掩,所有的工作線程都需要停止工作购披,等待垃圾收集線程完成以后,其他線程才可以繼續(xù)工作肩榕。工作過(guò)程可以簡(jiǎn)單的用下圖來(lái)表示:
4.2 ParNew收集器
(1) ParNew收集器是Serial收集器的多線程版本刚陡,除了多線程外,與Serial相比沒(méi)有太多創(chuàng)新之處
(2) 多線程版本的年輕代收集器中,只有它可以和CMS一起搭配搭配使用
(3) ParNew收集器在單核環(huán)境性能不如Serial收集器(線程交互的開銷)筐乳,默認(rèn)開啟的收集線程數(shù)和CPU數(shù)量相同歌殃,可以使用 -XX:ParallelGCThreads 限定垃圾回收的線程數(shù)
4.3 Parallel Scavenge收集器
(1) 目標(biāo)是達(dá)到一個(gè)可控的吞吐量(Throughput),吞吐量=運(yùn)行用戶代碼時(shí)間/(運(yùn)行用戶代碼時(shí)間+GC時(shí)間)
(2) 控制吞吐量的兩個(gè)參數(shù):-XX:MaxGCPauseMillis(最大GC停頓時(shí)間)和-XX:GCTimeRatio(設(shè)置吞吐量大小)
(3) -XX:MaxGCPauseMillis允許設(shè)置一個(gè)大于0的毫秒數(shù)哥童,GC停頓時(shí)間短是以犧牲吞吐量和新生代空間換取的
(4) -XX:GCTimeRatio是一個(gè)大于0且小于100的整數(shù)挺份,默認(rèn)值是99,即允許的最大GC時(shí)間1%(即1/(1+99)
(5) -XX:UseAdaptiveSizePolicy贮懈,打開后虛擬機(jī)會(huì)根據(jù)當(dāng)前系統(tǒng)的允許情況收集監(jiān)控信息,動(dòng)態(tài)調(diào)整以提供最適合的停頓時(shí)間或最大的吞吐量优训,該方式稱為GC自適應(yīng)的調(diào)節(jié)
4.4 Serial Old收集器
Serial Old收集器是Serial收集器的老年代版本朵你,同樣是一個(gè)單線程收集器,使用“標(biāo)記-整理”算法揣非,主要用于Client模式下老年代的垃圾收集器抡医。在Server模式下,主要是在JDK1.5版本之前和Parallel Scavenge年輕代收集器配合使用早敬,或者作為CMS收集器的后備收集器
4.5 Parallel Old收集器
Parallel Old收集器是Parallel Scavenge收集器的老年代版本忌傻,使用多線程和"標(biāo)記-整理"算法,主要是和Parallel Scavenge收集器一起配合(注重吞吐量及CPU資源敏感的場(chǎng)景)搞监,可以實(shí)現(xiàn)對(duì)Java堆內(nèi)存的吞吐量?jī)?yōu)先的垃圾收集策略
4.6 CMS收集器
(1) CMS(Concurrent Mark Sweep)收集器是以最短GC停頓時(shí)間為目標(biāo)的收集器水孩,符合重視服務(wù)響應(yīng)時(shí)間的應(yīng)用
(2) CMS收集器的工作過(guò)程可以分為4個(gè)階段:
初始標(biāo)記(CMS initial mark)階段、并發(fā)標(biāo)記(CMS concurrent mark)階段琐驴、重新標(biāo)記(CMS remark)階段俘种、并發(fā)清除(CMS concurrent sweep)階段
從圖中可以看出,在這4個(gè)階段中绝淡,初始標(biāo)記和重新標(biāo)記這兩個(gè)階段都只有GC線程在運(yùn)行宙刘,用戶線程會(huì)被停止,所以這兩個(gè)階段會(huì)發(fā)送STW(Stop The World)牢酵。初始標(biāo)記階段的工作是標(biāo)記GC Roots可以直接關(guān)聯(lián)到的對(duì)象悬包,速度很快。并發(fā)標(biāo)記階段馍乙,會(huì)從GC Roots 出發(fā)布近,標(biāo)記處所有可達(dá)的對(duì)象,這個(gè)過(guò)程可能會(huì)花費(fèi)相對(duì)比較長(zhǎng)的時(shí)間潘拨,但是由于在這個(gè)階段吊输,GC線程和用戶線程是可以一起運(yùn)行的,所以即使標(biāo)記過(guò)程比較耗時(shí)铁追,也不會(huì)影響到系統(tǒng)的運(yùn)行季蚂。重新標(biāo)記階段,是對(duì)并發(fā)標(biāo)記期間因用戶程序運(yùn)行而導(dǎo)致標(biāo)記變動(dòng)的那部分記錄進(jìn)行修正,重新標(biāo)記階段耗時(shí)一般比初始標(biāo)記稍長(zhǎng)扭屁,但是遠(yuǎn)小于并發(fā)標(biāo)記階段算谈。最終,會(huì)進(jìn)行并發(fā)清理階段料滥,和并發(fā)標(biāo)記階段類似然眼,并發(fā)清理階段不會(huì)停止系統(tǒng)的運(yùn)行,所以即使相對(duì)耗時(shí)葵腹,也不會(huì)對(duì)系統(tǒng)運(yùn)行產(chǎn)生大的影響高每。
由于并發(fā)標(biāo)記和并發(fā)清理階段是和應(yīng)用系統(tǒng)一起執(zhí)行的,而初始標(biāo)記和重新標(biāo)記相對(duì)來(lái)說(shuō)耗時(shí)很短践宴,所以可以認(rèn)為CMS收集器在運(yùn)行過(guò)程中鲸匿,是和應(yīng)用程序是并發(fā)執(zhí)行的。由于CMS收集器是一款并發(fā)收集和低停頓的垃圾收集器阻肩,所以CMS收集器也被稱為并發(fā)低停頓收集器带欢。
(3) 不足:一是CMS收集器對(duì)CPU資源非常敏感;二是CMS收集器在處理垃圾收集的過(guò)程中烤惊,可能會(huì)產(chǎn)生浮動(dòng)垃圾乔煞,由于它無(wú)法處理浮動(dòng)垃圾,所以可能會(huì)出現(xiàn)Concurrent Mode Failure問(wèn)題而導(dǎo)致觸發(fā)一次Full GC柒室。所謂的浮動(dòng)垃圾渡贾,是由于CMS收集器的并發(fā)清理階段,清理線程是和用戶線程一起運(yùn)行伦泥,如果在清理過(guò)程中剥啤,用戶線程產(chǎn)生了垃圾對(duì)象,由于過(guò)了標(biāo)記階段不脯,所以這些垃圾對(duì)象就成為了浮動(dòng)垃圾府怯,CMS無(wú)法在當(dāng)前垃圾收集過(guò)程中集中處理這些垃圾對(duì)象;三是它在進(jìn)行垃圾收集時(shí)使用的"標(biāo)記-清除"算法防楷,在進(jìn)行垃圾清理以后牺丙,會(huì)出現(xiàn)很多內(nèi)存碎片,過(guò)多的內(nèi)存碎片會(huì)影響大對(duì)象的分配复局,會(huì)導(dǎo)致即使老年代內(nèi)存還有很多空閑
4.7 G1收集器
為解決CMS算法產(chǎn)生空間碎片和其它一系列的問(wèn)題缺陷冲簿,HotSpot提供了另外一種垃圾回收策略,G1(Garbage First)算法亿昏,通過(guò)參數(shù)-XX:+UseG1GC來(lái)啟用峦剔,該算法在JDK 7u4版本被正式推出,官網(wǎng)對(duì)此描述如下:
The Garbage-First (G1) collector is a server-style garbage collector, targeted for multi-processor machines with large memories. It meets garbage collection (GC) pause time goals with a high probability, while achieving high throughput. The G1 garbage collector is fully supported in Oracle JDK 7 update 4 and later releases. The G1 collector is designed for applications that:
1.Can operate concurrently with applications threads like the CMS collector.
2.Compact free space without lengthy GC induced pause times.
3.Need more predictable GC pause durations.
4.Do not want to sacrifice a lot of throughput performance.
5.Do not require a much larger Java heap.
在G1算法中角钩,堆內(nèi)存被劃分為多個(gè)大小相等的內(nèi)存塊(Region)吝沫,每個(gè)Region是邏輯連續(xù)的一段內(nèi)存呻澜,結(jié)構(gòu)如下:
每個(gè)Region被標(biāo)記了E、S惨险、O和H羹幸,說(shuō)明每個(gè)Region在運(yùn)行時(shí)都充當(dāng)了一種角色,其中H是以往算法中沒(méi)有的辫愉,它代表Humongous栅受,表示這些Region存儲(chǔ)的是巨型對(duì)象(humongous object,H-obj)恭朗,當(dāng)新建對(duì)象大小超過(guò)Region大小一半時(shí)屏镊,直接在新的一個(gè)或多個(gè)連續(xù)Region中分配,并標(biāo)記為H痰腮。
堆內(nèi)存中一個(gè)Region的大小可以通過(guò)-XX:G1HeapRegionSize參數(shù)指定闸衫,大小區(qū)間只能是1M、2M诽嘉、4M、8M弟翘、16M和32M虫腋,總之是2的冪次方。
GC模式:G1中提供了三種模式垃圾回收模式稀余,young gc悦冀、mixed gc 和 full gc,在不同的條件下被觸發(fā)睛琳。
young gc:發(fā)生在年輕代的GC算法盒蟆,一般對(duì)象(除了巨型對(duì)象)都是在eden region中分配內(nèi)存,當(dāng)所有eden region被耗盡無(wú)法申請(qǐng)內(nèi)存時(shí)师骗,就會(huì)觸發(fā)一次young gc历等,這種觸發(fā)機(jī)制和之前的young gc差不多,執(zhí)行完一次young gc辟癌,活躍對(duì)象會(huì)被拷貝到survivor region或者晉升到old region中寒屯,空閑的region會(huì)被放入空閑列表中,等待下次被使用黍少。
參數(shù)含義:-XX:MaxGCPauseMillis設(shè)置G1收集過(guò)程目標(biāo)時(shí)間皆怕,默認(rèn)值200ms瞻佛;-XX:G1NewSizePercent新生代最小值,默認(rèn)值5%;-XX:G1MaxNewSizePercent新生代最大值辜梳,默認(rèn)值60%
mixed gc:當(dāng)越來(lái)越多的對(duì)象晉升到老年代old region時(shí),為了避免堆內(nèi)存被耗盡铲觉,虛擬機(jī)會(huì)觸發(fā)一個(gè)混合的垃圾收集器窝稿,即mixed gc野揪,該算法并不是一個(gè)old gc,除了回收整個(gè)young region传于,還會(huì)回收一部分的old region囱挑,這里需要注意:是一部分老年代,而不是全部老年代沼溜。
mixed gc中有一個(gè)閾值參數(shù)-XX:InitiatingHeapOccupancyPercent平挑,當(dāng)老年代大小占整個(gè)堆大小百分比達(dá)到該閾值時(shí),會(huì)觸發(fā)一次mixed gc系草。mixed gc的執(zhí)行過(guò)程有點(diǎn)類似cms通熄,主要分為以下幾步:
(1) initial mark: 初始標(biāo)記過(guò)程,整個(gè)過(guò)程STW找都,標(biāo)記了從GC Root可達(dá)的對(duì)象
(2) concurrent marking: 并發(fā)標(biāo)記過(guò)程唇辨,整個(gè)過(guò)程gc collector線程與應(yīng)用線程可以并行執(zhí)行,標(biāo)記出GC Root可達(dá)對(duì)象衍生出去的存活對(duì)象能耻,并收集各個(gè)Region的存活對(duì)象信息
(3) remark: 最終標(biāo)記過(guò)程赏枚,整個(gè)過(guò)程STW,標(biāo)記出那些在并發(fā)標(biāo)記過(guò)程中遺漏的晓猛,或者內(nèi)部引用發(fā)生變化的對(duì)象
(4) clean up: 垃圾清除過(guò)程饿幅,如果發(fā)現(xiàn)一個(gè)Region中沒(méi)有存活對(duì)象,則把該Region加入到空閑列表中
full gc:如果對(duì)象內(nèi)存分配速度過(guò)快戒职,mixed gc來(lái)不及回收栗恩,導(dǎo)致老年代被填滿,就會(huì)觸發(fā)一次full gc洪燥,G1的full gc算法就是單線程執(zhí)行的serial old gc磕秤,會(huì)導(dǎo)致異常長(zhǎng)時(shí)間的暫停時(shí)間,需要進(jìn)行不斷的調(diào)優(yōu)捧韵,盡可能的避免full gc
4.8 理解GC日志
33.125:[GC[DefNew:3324K->152K(3712K)市咆,0.0025925secs]3324K->152K(11904K),0.0031680 secs]
100.667:[FullGC[Tenured:0K->210K(10240K)纫版,0.0149142secs]4603K->210K(19456K)床绪,[Perm:2999K->2999K(21248K)],0.0150007 secs][Times:user=0.01 sys=0.00其弊,real=0.02 secs]
最前面的數(shù)字“33.125:”和“100.667:”代表了GC發(fā)生的時(shí)間癞己,這個(gè)數(shù)字的含義是從Java虛擬機(jī)啟動(dòng)以來(lái)經(jīng)過(guò)的秒數(shù)。
GC日志開頭的“[GC”和“[Full GC”說(shuō)明了這次垃圾收集的停頓類型梭伐,而不是用來(lái)區(qū)分新生代GC還是老年代GC的痹雅。如果有“Full”,說(shuō)明這次GC是發(fā)生了Stop-The-World的糊识,例如下面這段新生代收集器ParNew的日志也會(huì)出現(xiàn)“[Full GC”(這一般是因?yàn)槌霈F(xiàn)了分配擔(dān)保失敗之類的問(wèn)題绩社,所以才導(dǎo)致STW)摔蓝。如果是調(diào)用System.gc()方法所觸發(fā)的收集,那么在這里將顯示“[Full GC(System)”愉耙。
[Full GC 283.736:[ParNew:261599K->261599K(261952K)贮尉,0.0000288 secs]
接下來(lái)的“[DefNew”、“[Tenured”朴沿、“[Perm”表示GC發(fā)生的區(qū)域猜谚,這里顯示的區(qū)域名稱與使用的GC收集是密切相關(guān)的,例如上面樣例所使用的Serial收集器中的新生代名為“Default New Generation”赌渣,所以顯示的是“[DefNew”魏铅。
如果是ParNew收集器,新生代名稱就會(huì)變?yōu)椤癧ParNew”坚芜,意為“Parallel New Generation”览芳。
如果采用Parallel Scavenge收集器,那它配套的新生代稱為“PSYoungGen”鸿竖,老年代和永久代同理沧竟,名稱也是由收集器決定的。
后面方括號(hào)內(nèi)部的“3324K->152K(3712K)”含義是“GC前該內(nèi)存區(qū)域已使用容量->GC后該內(nèi)存區(qū)域已使用容量(該內(nèi)存區(qū)域總?cè)萘浚薄?
而在方括號(hào)之外的“3324K->152K(11904K)”表示“GC前Java堆已使用容量->GC后Java堆已使用容量(Java堆總?cè)萘浚薄?/p>
再往后缚忧,“0.0025925 secs”表示該內(nèi)存區(qū)域GC所占用的時(shí)間屯仗,單位是秒。
有的收集器會(huì)給出更具體的時(shí)間數(shù)據(jù)搔谴,如“[Times:user=0.01 sys=0.00,real=0.02 secs]”桩撮,這里面的user敦第、sys和real與Linux的time命令所輸出的時(shí)間含義一致,分別代表用戶態(tài)消耗的CPU時(shí)間店量、內(nèi)核態(tài)消耗的CPU事件和操作從開始到結(jié)束所經(jīng)過(guò)的墻鐘時(shí)間(Wall Clock Time)芜果。
CPU時(shí)間與墻鐘時(shí)間的區(qū)別是,墻鐘時(shí)間包括各種非運(yùn)算的等待耗時(shí)融师,例如等待磁盤I/O右钾、等待線程阻塞,而CPU時(shí)間不包括這些耗時(shí)旱爆。當(dāng)系統(tǒng)有多CPU或者多核的話舀射,多線程操作會(huì)疊加這些CPU時(shí)間,所以讀者看到user或sys時(shí)間超過(guò)real時(shí)間是完全正常的怀伦。
5脆烟、內(nèi)存分配和回收策略
5.1 對(duì)象優(yōu)先在Eden區(qū)分配
一般情況下,對(duì)象在新生代Eden區(qū)分配房待,當(dāng)Eden區(qū)沒(méi)有足夠空間時(shí)邢羔,將發(fā)起一次Minor GC驼抹。-XX:PrintGCDetails可以設(shè)置虛擬機(jī)在發(fā)生GC時(shí)打印內(nèi)存回收日志,并在進(jìn)程退出時(shí)輸出當(dāng)前內(nèi)存各區(qū)域分配情況拜鹤。
5.2 大對(duì)象直接進(jìn)入老年代
大對(duì)象是指需要大量連續(xù)內(nèi)存空間的對(duì)象框冀,如很長(zhǎng)的字符串或數(shù)組。通過(guò)設(shè)置-XX:PretenureSizeThreshold參數(shù)的值敏簿,大于該值的對(duì)象直接在老年代分配
5.3 長(zhǎng)期存活的對(duì)象將進(jìn)入老年代
虛擬機(jī)給每個(gè)對(duì)象定義了年齡明也,每經(jīng)過(guò)一次Minor GC且在新生代存活的對(duì)象,年齡加1极谊,當(dāng)達(dá)到年齡閥值(默認(rèn)15诡右,可以通過(guò)-XX:MaxTenuringThreshold設(shè)置),將會(huì)被晉升到老年代中
5.4 對(duì)象年齡動(dòng)態(tài)判斷
為了更好的適應(yīng)不同程序的內(nèi)存情況轻猖,并不是完全根據(jù)對(duì)象的年齡來(lái)晉升到老年代帆吻,如果Survivor空間中相同年齡所有對(duì)象大小總和大于Survivor空間一半,年齡大于或等于該年齡的對(duì)象將直接進(jìn)入老年代
5.5 空間分配擔(dān)保
在發(fā)生Minor GC之前咙边,虛擬機(jī)會(huì)檢查老年代最大可用連續(xù)空間是否大于新生代所有對(duì)象總空間猜煮,如果成立可以確保Minor GC成功,否則虛擬機(jī)會(huì)查看HandlePromotionFailure是否設(shè)置失敗擔(dān)保败许,如果允許王带,會(huì)檢查老年代最大可用連續(xù)空間是否大于歷次晉升到老年代對(duì)象的平均大小,如果大于市殷,將嘗試進(jìn)行一次Minor GC愕撰,盡管存在風(fēng)險(xiǎn),如果小于醋寝,則進(jìn)行一次Full GC搞挣。