1. Java 如何標(biāo)識垃圾
常用的標(biāo)識算法主要是兩類,一是計數(shù)器引用法杰刽,二是可達(dá)性分析(根搜索算法)缀匕。
計數(shù)器引用法
-
可達(dá)性分析
基本思路:- 已根對象集合為起點(diǎn)强窖,按照從上之下的方式搜索被根對象集合所連接的目標(biāo)對象是否可達(dá)泪姨。
- 使用可達(dá)性分析算法后游沿,內(nèi)存中的存活對象都會被根對象集合直接或間接連接著,搜索所走過的路徑成為
引用鏈
.
2. GC ROOTS 包含哪些肮砾?
- 虛擬機(jī)棧中引用的對象
》 比如各個線程中被調(diào)用的方法中使用的參數(shù)诀黍,局部變量 - 本地方法棧引用的對象
- 方法區(qū)中類靜態(tài)屬性引用的對象
》 java類的引用類型靜態(tài)變量 - 方法區(qū)中常量引用的對象
》 字符串常量池里面的應(yīng)用 - 被synchronized持有的對象
- java虛擬機(jī)內(nèi)部的引用
- 反映java虛擬機(jī)內(nèi)部情況的JMXBean,JVMTI中的回調(diào)唇敞,本地代碼緩存等蔗草。
特殊情況:
有對象“臨時性”的加入咒彤,共同構(gòu)成完成GC Roots集合疆柔。比如分代收集和局部回收(Partial GC)
3. 為什么會產(chǎn)生STW
如果要使用可達(dá)性分析算法來判斷內(nèi)存是否可回收,那么分析工作必須在一個能保障一致性的快照中進(jìn)行镶柱。這點(diǎn)不滿足的話旷档,那分析的結(jié)果準(zhǔn)確性也就無法保障。
所以就會產(chǎn)生了Stop The World的一個重要原因歇拆。
4. 對象的finalization機(jī)制
用于開發(fā)人員對對象被銷毀前的自定義邏輯處理鞋屈。通常用于對象被回收時范咨,進(jìn)行資源釋放和清理的工作。
關(guān)閉文件流厂庇,關(guān)閉數(shù)據(jù)庫連接等渠啊。
finalization為什么不要手工調(diào)用
- 有可能導(dǎo)致對象復(fù)活
- finalization的執(zhí)行時間點(diǎn)不確定。在極端情況下权旷,如果不發(fā)生GC替蛉,那么finalization將永遠(yuǎn)不會被執(zhí)行。
finalization 導(dǎo)致對象復(fù)活的情況
在虛擬機(jī)定義中拄氯,對象存在三種狀態(tài)
1. 可觸及的:從GC ROOT可達(dá)
2. 可復(fù)活的:對象多有的引用都被釋放了躲查,但是對象可能在finalization() 被復(fù)活。
3. 不可觸及的:對象的finalization()被調(diào)用译柏,并且沒有復(fù)活镣煮。那么就會就如不可觸及的狀態(tài)。不可觸及的對象就一定會被回收鄙麦。因?yàn)?code>finalization只會被調(diào)用一次典唇。
5. 如何判斷一個對象是否可以被回收?
判斷一個對象能否被收回黔衡,至少要經(jīng)歷兩次判斷蚓聘。
- 如果objA到GC Roots沒有引用鏈,則進(jìn)行第一次標(biāo)記
- 判斷對象是否有必要執(zhí)行finalization()方法
- 如果
沒有重寫finalization()
或者finalization()已經(jīng)被執(zhí)行過了
盟劫,則被判斷為不可觸及的夜牡。 - 如果對象重寫了finalization()方法,且還未被執(zhí)行過侣签。那么objA會被插入到F-Queue隊(duì)列中塘装,由一個虛擬機(jī)自動創(chuàng)建的低優(yōu)先級的finalizer線程觸發(fā)其finalization()。
- 如果
- finalization()是對象逃脫死亡的最后機(jī)會影所。稍后GC會對F-Queue 隊(duì)列中的對象進(jìn)行二次標(biāo)記蹦肴。 如果objA在此時與引用鏈上的任何一個對象建立了聯(lián)系,那么objA會被移出“即將回收”集合猴娩。
6. JVM GC 清除階段的算法
6.1 標(biāo)記-清除算法(Mark-Sweep)
- 優(yōu)點(diǎn): 比較容易理解
- 缺點(diǎn)
- 效率不算高
- 會產(chǎn)生內(nèi)存碎片阴幌,還需要額外的空間維護(hù)一個空閑列表。
6.2 復(fù)制算法(Copying)
優(yōu)點(diǎn):
- 保證空間連續(xù)卷中,不會出現(xiàn)碎片問題
- 實(shí)現(xiàn)相對簡單矛双,運(yùn)行高效
缺點(diǎn):
- 需要兩倍的空間
- 當(dāng)系統(tǒng)存活的對象數(shù)量很多時,性能較低蟆豫。(所以只能用于新生代)
6.3 標(biāo)記-壓縮算法(Mark-Compact)
優(yōu)點(diǎn)
- 沒有內(nèi)存碎片
- 減少了內(nèi)存的浪費(fèi)
缺點(diǎn)
- 從效率來說议忽,標(biāo)記整理算法要低于復(fù)制算法
- 移動對象的同時,如果對象被其他對象引用十减,則還需調(diào)整引用地址栈幸。
- STW的時間相比于其他要長一些愤估,因?yàn)樯婕暗綄ο蟮囊苿雍鸵酶隆?/li>
7. GC 分帶收集算法&增量收集算法&分區(qū)算法
分帶收集算法
增量收集算法
分區(qū)算法
8. System.gc()和Runtime.getRuntime().gc()的理解
- 默認(rèn)情況下固歪,通過System.gc()和Runtime.getRuntime().gc()顯示調(diào)用時仇轻,會觸發(fā)Full GC,同時對老年代和新生代進(jìn)行回收募疮,嘗試釋放對象占用的內(nèi)存芍锚。
- System.gc()無法保證對垃圾回收器的調(diào)用
- Sysmte.gc()等同與Runtime.getRuntime().gc()
gc與slot的關(guān)系
image.png
在這個案例中 buffer所占用空間不會被回收震捣,因?yàn)閟lot=1的位置還是被buffer這個變量所占用。在gc時闹炉,屬于GC Root可達(dá)的情況蒿赢。
9. 程序的并行與并發(fā)
垃圾回收器的并行與并發(fā)
10. GC 中的安全點(diǎn)與安全區(qū)域的說明
-
Safepoint
image.png
如何讓線程在安全點(diǎn)中斷:
-
SafeRegion
image.png
實(shí)際執(zhí)行流程
11. java引用:強(qiáng),軟渣触,弱羡棵,虛
-
強(qiáng)引用:不回收
- 強(qiáng)引用的對象的GC Root可達(dá)的,所以垃圾回收器永遠(yuǎn)不會回收嗅钻。
- 強(qiáng)引用也是造成內(nèi)存泄漏的主要原因之一皂冰。
-
SoftReference 軟引用:內(nèi)存不足時及回收
- 用于描述一下有用但是非必須的對象。只被弱引用關(guān)聯(lián)者的對象养篓,在系統(tǒng)將要發(fā)生內(nèi)存溢出前秃流,會把這些對象列入回收范圍內(nèi)進(jìn)行二次回收。如果這次回收還是沒有足夠的內(nèi)存柳弄,才會報出OOM舶胀。
- 一般使用場景是:如mybaits中的本地緩存
WeakReference 弱引用:發(fā)現(xiàn)即回收
- 只被弱引用關(guān)聯(lián)的對象,只能存活到下一次GC發(fā)生為止碧注。
- 常用的實(shí)現(xiàn)類是WeekHashMap嚣伐,在Tomcat中作為了一個LRU的cache實(shí)現(xiàn)。
軟引用和弱引用的區(qū)別點(diǎn):
-
PhantomReference 虛引用:
image.png
- 使用場景:追蹤垃圾回收
-
** 終結(jié)器引用:**
對象finalization的底層實(shí)現(xiàn)
image.png