問:對象斷定爲垃圾的標準?java
沒有被其餘對象引用算法
問:對象斷定爲垃圾的算法?線程
引用計數算法3d
- 經過判斷對象的引用數量來判斷對象是否能夠被回收
- 每一個對象實例都有一個引用計數器,被引用則+1,完成引用-1
- 任何引用計數爲0的對象實例能夠當垃圾收集的
優勢:執行效率高,程序受影響較小日誌
缺點:沒法檢測出循環引用的狀況,致使內存泄漏memory leak對象
可達性分析算法blog
- 經過判斷對象的引用鏈是否可達來決定對象是否能夠被回收
能夠做爲GC Root的對象排序
- 虛擬機棧中的引用對象(棧幀中的本地變量表)
- 方法區中的常量引用對象
- 方法區中的類靜態屬性引用的對象
- 本地方法棧中JNI(Native方法)的引用對象
- 活躍線程的引用對象
問:談談你瞭解的垃圾回收算法?生命週期
標記-清除算法(mark and sweep)內存
- 標記:從根集合進行掃描,對存活的對象進行標記
- 清楚:對堆內存從頭至尾進行線性遍歷,回收不可達對象內存,並把原來標記爲可達的標記清除掉
優勢:效率高,由於不須要對對象的移動操做。
缺點:碎片化,標記清除以後會留下大量不連續的內存空間,碎片太多可能會致使之後程序運行過程當中沒法提供連續內存,而不得不進行另外一次垃圾回收
複製算法(Copying)
- 分爲對象面和空閒面
- 對象在對象面上建立
- 存活的對象從對象面複製到空閒面
- 將對象面全部對象內存清除
優勢:
- 解決了碎片化的問題 (每次複製到空閒面的對象都是連續排放的)
- 順序分配內存,簡單高效 (每次直接清理一半的內存空間,因此簡單高效)
- 適用於對象存活率低的場景,好比年輕代(如今成熟的商業虛擬機中都採用這種算法回收年輕代,由於年輕代通常只有10%的對象存活,因此使用這種算法效率還不錯)
缺點:在應對對象存活率較高時就有些力不從心了,由於有較多的複製操做,效率將會變低。並且不想浪費額外的50%空間,就須要更多的空間進行擔保,由於須要應對全部對象都100%存活的極端狀況,因此老年代通常不能選用這種算法。
標記-整理算法(Compacting)
- 標記:從根集合進行掃描,對存活的對象進行標記
- 清除:移動全部存活的對象,且按照內存地址次序一次排序,而後將末端內存地址之後的內存所有回收
優勢:解決了內存碎片化的問題,清理以後內存是連續的,也不用設置兩塊內存互換,適用於存活率較高的場景
缺點:須要移動標記存活的對象,成本較高
分代收集算法(Generational Collector) 如今主流的GC算法
- 垃圾回收算法的組合拳
- 按照對象生命週期的不一樣劃分區域以採用不一樣的垃圾回收算法
- 目的:提升JVM的回收效率
JDK8以後沒有永久代,可是年輕代、老年代都保留了下來,年輕代使用的是複製算法,老年代使用的標記整理算法
問:分代收集算法的GC分幾種?
- Minor GC (發生在年輕代中的垃圾收集工做,使用複製算法。年輕代是全部java對象出生的地方,新對象通常存活率較低,因此MinorGC比較頻繁)
- Full GC
年輕代:
- Eden區(就是伊甸園,表明這人類的起源,新對象存放的區域,若是eden區放不下新對象,也有可能會放在survivor區甚至是老年代中)
- 兩個Survivor區(倖存者區,from區和to區,這兩個區也不是固定的,會隨着垃圾回收而相互轉換)
默認是8:1:1的比例分配,垃圾清理時會將eden和from區的存活對象一次性複製到to區,to區不夠用的時候須要老年代作擔保
年輕代垃圾回收的過程演示:
每次存活就會標記+1,默認是15歲,也能夠設置-XX:MaxTenuringThreshold設置最大年齡限制,到達限制就會進入老年代,固然若是eden或者survivor裝不下也會進入老年代
對象如何晉升爲老年代:
- 經歷必定Minor次數依然存活的對象
- Survivor區放不下的對象
- 新生成的大對象(能夠設置-XX:+PretenuerSizeThreshold設置大對象大小,超過這個大小的大對象會直接放入老年代)
經常使用的調優參數:
- -XX:SurvivorRatio:Eden和Survivor的比值,默認8:1
- -XX:NewRatio:老年代和年輕代內存大小比例,好比2表示老年代是年輕代的2倍
老年代:存放生命週期較長的對象
通常會伴隨着新生代的回收及整個堆的回收(FullGC和MajorGC,FullGC比MinorGC慢,但執行頻率低)
問:出發FullGC的條件?
- 老年代空間不足(最好不要建立太大對象)
- 永久代空間不足(JDK7之前的版本,這也是JDK8使用元空間替代永久代的緣由,下降了FullGC的頻率)
- CMS GC時出現promotion failed ,concurrent mode failure(注意日誌裏是否出現這兩個狀況,這兩種狀況很容易觸發FullGC)
- Minor GC 晉升到老年代的平均大小大於老年代剩餘空間(hotspot在進行MinorGC作了個統計,若是晉升到老年代的平均大小大於老年代剩餘空間就直接觸發Full GC)
- 調用System.gc()(這只是程序提醒虛擬機,碼農但願這裏進行一下回收,但回不回收仍是要看JVM)
- 使用RMI來進行RPC或者管理JDK應用,默認每小時執行一次FullGC