強引用勋颖、軟引用、弱引用勋锤、虛引用是什么饭玲,有什么區(qū)別?
強引用:在程序中普遍存在的引用賦值叁执,類似Object obj = new Object()這種引用關系茄厘。只要強引用關系還存在,垃圾收集器就永遠不會回收掉被引用的對象谈宛。
軟引用:如果內存空間足夠次哈,垃圾回收器就不會回收它,如果內存空間不足了吆录,就會回收這些對象的內存窑滞。
//軟引用
SoftReference<String> softRef = new SoftReference<String>(str);
弱引用:在進行垃圾回收時,不管當前內存空間足夠與否恢筝,都會回收只具有弱引用的對象哀卫。
//弱引用
WeakReference<String> weakRef = new WeakReference<String>(str);
虛引用:虛引用并不會決定對象的生命周期。如果一個對象僅持有虛引用撬槽,那么它就和沒有任何引用一樣此改,在任何時候都可能被垃圾回收。虛引用主要是為了能在對象被收集器回收時收到一個系統(tǒng)通知恢氯。
Minor GC 和 Full GC的區(qū)別带斑?
Minor GC:回收新生代,因為新生代對象存活時間很短勋拟,因此Minor GC會頻繁執(zhí)行勋磕,執(zhí)行的速度一般也會比較快。
Full GC:回收老年代和新生代敢靡,老年代的對象存活時間長挂滓,因此Full GC很少執(zhí)行,執(zhí)行速度會比Minor GC慢很多啸胧。
內存的分配策略赶站?
對象優(yōu)先在 Eden 分配
大多數情況下,對象在新生代Eden上分配纺念,當Eden空間不夠時贝椿,觸發(fā)Minor GC。
大對象直接進入老年代
大對象是指需要連續(xù)內存空間的對象陷谱,最典型的大對象有長字符串和大數組烙博∩冢可以設置JVM參數-XX:PretenureSizeThreshold,大于此值的對象直接在老年代分配渣窜。
長期存活的對象進入老年代
通過參數-XX:MaxTenuringThreshold可以設置對象進入老年代的年齡閾值铺根。對象在Survivor區(qū)每經過一次Minor GC,年齡就增加 1 歲乔宿,當它的年齡增加到一定程度位迂,就會被晉升到老年代中。
動態(tài)對象年齡判定
并非對象的年齡必須達到MaxTenuringThreshold才能晉升老年代详瑞,如果在Survivor中相同年齡所有對象大小的總和大于Survivor空間的一半掂林,則年齡大于或等于該年齡的對象可以直接進入老年代,無需達到MaxTenuringThreshold年齡閾值蛤虐。
空間分配擔保
在發(fā)生Minor GC之前党饮,虛擬機先檢查老年代最大可用的連續(xù)空間是否大于新生代所有對象總空間,如果條件成立的話驳庭,那么Minor GC是安全的刑顺。如果不成立的話虛擬機會查看HandlePromotionFailure的值是否允許擔保失敗。如果允許饲常,那么就會繼續(xù)檢查老年代最大可用的連續(xù)空間是否大于歷次晉升到老年代對象的平均大小蹲堂,如果大于,將嘗試著進行一次Minor GC贝淤;如果小于柒竞,或者HandlePromotionFailure的值為不允許擔保失敗,那么就要進行一次Full GC播聪。
Full GC 的觸發(fā)條件朽基?
????????對于 Minor GC,其觸發(fā)條件比較簡單离陶,當 Eden 空間滿時稼虎,就將觸發(fā)一次 Minor GC。而 Full GC 觸發(fā)條件相對復雜招刨,有以下情況會發(fā)生 full GC:
調用 System.gc()
????????只是建議虛擬機執(zhí)行 Full GC霎俩,但是虛擬機不一定真正去執(zhí)行。不建議使用這種方式沉眶,而是讓虛擬機管理內存打却。
老年代空間不足
????????老年代空間不足的常見場景為前文所講的大對象直接進入老年代、長期存活的對象進入老年代等谎倔。為了避免以上原因引起的 Full GC柳击,應當盡量不要創(chuàng)建過大的對象以及數組。除此之外片习,可以通過 -Xmn 參數調大新生代的大小腻暮,讓對象盡量在新生代被回收掉彤守,不進入老年代。還可以通過 -XX:MaxTenuringThreshold 調大對象進入老年代的年齡哭靖,讓對象在新生代多存活一段時間。
空間分配擔保失敗
????????使用復制算法的 Minor GC 需要老年代的內存空間作擔保侈离,如果擔保失敗會執(zhí)行一次 Full GC试幽。
JDK 1.7 及以前的永久代空間不足
????????在 JDK 1.7 及以前,HotSpot 虛擬機中的方法區(qū)是用永久代實現的卦碾,永久代中存放的為一些 Class 的信息铺坞、常量、靜態(tài)變量等數據洲胖。當系統(tǒng)中要加載的類济榨、反射的類和調用的方法較多時,永久代可能會被占滿绿映,在未配置為采用 CMS GC 的情況下也會執(zhí)行 Full GC擒滑。如果經過 Full GC 仍然回收不了,那么虛擬機會拋出 java.lang.OutOfMemoryError叉弦。
垃圾回收算法有哪些丐一?
垃圾回收算法有四種,分別是標記清除法淹冰、標記整理法库车、復制算法、分代收集算法樱拴。
標記清除算法
首先利用可達性去遍歷內存柠衍,把存活對象和垃圾對象進行標記。標記結束后統(tǒng)一將所有標記的對象回收掉晶乔。這種垃圾回收算法效率較低珍坊,并且會產生大量不連續(xù)的空間碎片。
復制清除算法
????????半區(qū)復制瘪弓,用于新生代垃圾回收垫蛆。將內存分為大小相同的兩塊,每次使用其中的一塊腺怯。當這一塊的內存使用完后袱饭,就將還存活的對象復制到另一塊去,然后再把使用的空間一次清理掉呛占。
特點:實現簡單虑乖,運行高效,但可用內存縮小為了原來的一半晾虑,浪費空間疹味。
標記整理算法
根據老年代的特點提出的一種標記算法仅叫,標記過程仍然與標記-清除算法一樣,但后續(xù)步驟不是直接對可回收對象進行清理糙捺,而是讓所有存活的對象都向一端移動诫咱,然后直接清理掉邊界以外的內存。
分類收集算法
根據各個年代的特點采用最適當的收集算法洪灯。一般將堆分為新生代和老年代坎缭。
新生代使用復制算法
老年代使用標記清除算法或者標記整理算法
????????在新生代中,每次垃圾收集時都有大批對象死去签钩,只有少量存活掏呼,使用復制算法比較合適,只需要付出少量存活對象的復制成本就可以完成收集铅檩。老年代對象存活率高憎夷,適合使用標記-清理或者標記-整理算法進行垃圾回收。
有哪些垃圾回收器昧旨?
垃圾回收器主要分為以下幾種:Serial拾给、ParNew、Parallel Scavenge臼予、Serial Old鸣戴、Parallel Old、CMS粘拾、G1窄锅。
這7種垃圾收集器的特點:
Serial 收集器
????????單線程收集器,使用一個垃圾收集線程去進行垃圾回收缰雇,在進行垃圾回收的時候必須暫停其他所有的工作線程(Stop The World)入偷,直到它收集結束。
????????特點:簡單高效械哟;內存消耗惺柚;沒有線程交互的開銷暇咆,單線程收集效率高锋爪;需暫停所有的工作線程,用戶體驗不好爸业。
ParNew 收集器
????????Serial收集器的多線程版本其骄,除了使用多線程進行垃圾收集外,其他行為扯旷、參數與Serial收集器基本一致拯爽。
Parallel Scavenge 收集器
????????新生代收集器,基于復制清除算法實現的收集器钧忽。特點是吞吐量優(yōu)先毯炮,能夠并行收集的多線程收集器逼肯,允許多個垃圾回收線程同時運行,降低垃圾收集時間桃煎,提高吞吐量篮幢。所謂吞吐量就是 CPU 中用于運行用戶代碼的時間與 CPU 總消耗時間的比值(吞吐量 = 運行用戶代碼時間 /(運行用戶代碼時間 + 垃圾收集時間))。Parallel Scavenge收集器關注點是吞吐量为迈,高效率的利用 CPU 資源洲拇。CMS垃圾收集器關注點更多的是用戶線程的停頓時間。
????????Parallel Scavenge收集器提供了兩個參數用于精確控制吞吐量曲尸,分別是控制最大垃圾收集停頓時間的-XX:MaxGCPauseMillis參數以及直接設置吞吐量大小的-XX:GCTimeRatio參數。
-XX:MaxGCPauseMillis參數的值是一個大于0的毫秒數男翰,收集器將盡量保證內存回收花費的時間不超過用戶設定值另患。
-XX:GCTimeRatio參數的值大于0小于100,即垃圾收集時間占總時間的比率蛾绎,相當于吞吐量的倒數昆箕。
Serial Old 收集器
????Serial收集器的老年代版本,單線程收集器租冠,使用標記整理算法鹏倘。
Parallel Old 收集器
????Parallel Scavenge收集器的老年代版本。多線程垃圾收集顽爹,使用標記整理算法纤泵。
CMS 收集器
????Concurrent Mark Sweep,并發(fā)標記清除镜粤,追求獲取最短停頓時間捏题,實現了讓垃圾收集線程與用戶線程基本上同時工作。
CMS垃圾回收基于標記清除算法實現肉渴,整個過程分為四個步驟:
初始標記: 暫停所有用戶線程(Stop The World)公荧,記錄直接與GC Roots直接相連的對象 。
并發(fā)標記:從GC Roots開始對堆中對象進行可達性分析同规,找出存活對象循狰,耗時較長,但是不需要停頓用戶線程券勺。
重新標記: 在并發(fā)標記期間對象的引用關系可能會變化绪钥,需要重新進行標記。此階段也會暫停所有用戶線程朱灿。
并發(fā)清除:清除標記對象昧识,這個階段也是可以與用戶線程同時并發(fā)的。
在整個過程中盗扒,耗時最長的是并發(fā)標記和并發(fā)清除階段跪楞,這兩個階段垃圾收集線程都可以與用戶線程一起工作缀去,所以從總體上來說,CMS收集器的內存回收過程是與用戶線程一起并發(fā)執(zhí)行的甸祭。
優(yōu)點:并發(fā)收集缕碎,停頓時間短。
缺點:
標記清除算法導致收集結束有大量空間碎片池户。
產生浮動垃圾咏雌,在并發(fā)清理階段用戶線程還在運行,會不斷有新的垃圾產生校焦,這一部分垃圾出現在標記過程之后赊抖,CMS無法在當次收集中回收它們,只好等到下一次垃圾回收再處理寨典;
G1收集器
G1垃圾收集器的目標是在不同應用場景中追求高吞吐量和低停頓之間的最佳平衡氛雪。
G1將整個堆分成相同大小的分區(qū)(Region),有四種不同類型的分區(qū):Eden耸成、Survivor报亩、Old和Humongous。分區(qū)的大小取值范圍為 1M 到 32M井氢,都是2的冪次方曲梗。分區(qū)大小可以通過-XX:G1HeapRegionSize參數指定淑仆。Humongous區(qū)域用于存儲大對象奏候。G1規(guī)定只要大小超過了一個分區(qū)容量一半的對象就認為是大對象揉燃。
?G1 收集器對各個分區(qū)回收所獲得的空間大小和回收所需時間的經驗值進行排序,得到一個優(yōu)先級列表左胞,每次根據用戶設置的最大回收停頓時間寇仓,優(yōu)先回收價值最大的分區(qū)。
特點:可以由用戶指定期望的垃圾收集停頓時間烤宙。
G1 收集器的回收過程分為以下幾個步驟:
初始標記遍烦。暫停所有其他線程,記錄直接與GC Roots直接相連的對象躺枕,耗時較短 服猪。
并發(fā)標記。從GC Roots開始對堆中對象進行可達性分析拐云,找出要回收的對象罢猪,耗時較長,不過可以和用戶程序并發(fā)執(zhí)行叉瘩。
最終標記膳帕。需對其他線程做短暫的暫停,用于處理并發(fā)標記階段對象引用出現變動的區(qū)域。
篩選回收危彩。對各個分區(qū)的回收價值和成本進行排序攒磨,根據用戶所期望的停頓時間來制定回收計劃,然后把決定回收的分區(qū)的存活對象復制到空的分區(qū)中汤徽,再清理掉整個舊的分區(qū)的全部空間娩缰。這里的操作涉及存活對象的移動,會暫停用戶線程谒府,由多條收集器線程并行完成拼坎。