垃圾回收的對象
我們申請的幾乎所有對象都存儲在堆上,并且堆空間在進程啟動時就已經創(chuàng)建了一個初始化的空間,隨著程序的運行蕴侣,堆內存的使用率/大小增長情況下缠犀,為保證程序的內存空間足夠使用数苫,jvm會不定期的對不再使用的對象進行回收,這個過程就是GC辨液。
關于內存結構可以參看上一節(jié)內容虐急。
引用類型
- 強引用,強引用是對對象的強制引用室梅,只要有強引用關聯(lián)垃圾回收器就不會回收該對象戏仓。
- 軟引用,SoftReference亡鼠,系統(tǒng)會在即將發(fā)生內存溢出時回收該類引用赏殃,回收后若還是內存不足才會拋出內存溢出,該引用用在一些最好有间涵,但也不是必須的對象引用上
- 弱引用仁热,WeakReference,系統(tǒng)會在下一次GC時回收該引用對象勾哩,這里用在不阻礙回收的內存引用上抗蠢,常用于一些會導致內存泄漏的對象引用上
- 虛引用,PhantomReference思劳,幽靈引用迅矛,最弱(隨時會被回收掉),垃圾回收的時候收到一個通知,就是為了監(jiān)控垃圾回收器是否正常工作潜叛。
分配在棧上的對象引用不會參與GC
jvm為優(yōu)化內存回收設計了逃逸對象分析秽褒。
逃逸算法是針對棧幀中創(chuàng)建的臨時對象,若該對象會被當做參數(shù)傳遞到其他方法則滿足逃逸的條件威兜。
如果該對象還會被外部線程訪問销斟,則滿足線程逃逸條件。
滿足線程逃逸條件的對象會在堆內存中創(chuàng)建椒舵,而只滿足全局逃逸條件的對象則可在棧中分配內存創(chuàng)建蚂踊,這種對象將不會參與GC,生命周期跟隨棧(即線程)
垃圾回收算法
-
垃圾收集
1.可達性分析
這個算法的基本思路是以RC Roots為起始點笔宿,找出所有被RC Roots引用的對象犁钟,之后回收那些沒有被引用的對象棱诱。
RC Roots包括以下幾種對象
- 方法區(qū)中靜態(tài)屬性引用的對象
- 方法區(qū)中常量引用的對象
- 虛擬機棧(棧幀中的本地變量表)中引用的對象
- 本地方法棧JNI(native方法)中引用的對象
- jvm的內部引用(class對象,異常對象NullPointException特纤、OutofMemoryError军俊,系統(tǒng)類加載)
- 所有被同步鎖(synchronized)持有的對象
- JVM 內部的JMXBean、JVMTI 中注冊的回調捧存、本地代碼緩存等
- JVM 實現(xiàn)中的“臨時性”對象粪躬,跨代引用的對象(在使用分代模型回收只回收部分代時)
2.引用計數(shù)
這個算法比較好理解,在對象中添加一個引用計數(shù)昔穴,當有對象引用該對象則計數(shù)加一镰官,當引用失效則計數(shù)減一,不過目前主流的虛擬機都沒有使用這個算法吗货,原因是這個算法在處理相互引用的情況時需要額外的機制來協(xié)助計算泳唠,這樣做的效率不是很高
-
垃圾回收
1.分代收集回收理論
分代收集理論是在以上兩種收集算法基礎上的一個優(yōu)化算法,它將對象分為新生代和老年代宙搬,經過多次(不同的垃圾回收器不同有的是15有的是6)回收計算都沒有被回收的對象叫做老年代笨腥,有一些垃圾回收器會將大對象直接放入老年代,有些回收時可選擇
1勇垛、新生代回收(Minor GC/Young GC):指只是進行新生代的回收脖母。
2、老年代回收(Major GC/Old GC):指只是進行老年代的回收闲孤。目前只有CMS 垃圾回收器會有這個單獨的收集老年代的行為谆级。(Major GC 定義是比較混
亂,有說指是老年代讼积,有的說是做整個堆的收集肥照,這個需要你根據別人的場景來定,沒有固定的說法)
3勤众、整堆收集(Full GC):收集整個Java 堆和方法區(qū)(注意包含方法區(qū))
2.復制算法
將可用內存按照容量劃分為大小相同的兩塊舆绎,每次只使用其中的一塊,垃圾回收時將存活的對象復制到另一塊上们颜,然后再將這塊內存整個清理掉吕朵,這樣不僅沒有內存碎片的問題,而且實現(xiàn)簡單掌桩,運行高效;當然缺點也是很明顯的姑食,只能使用一半的內存空間
3.標記清除算法
這個算法比較好理解波岛,垃圾收集時將可回收的對象做標記,垃圾回收時將標記的對象清理掉音半,它的缺陷是這種回收會產生大量的內存碎片则拷,過多的內存碎片的存在將導致在創(chuàng)建大對象時由于找不到連續(xù)的內存空間將會導致另一次垃圾回收贡蓖,且存在內存浪費
4.標記-整理算法
該算法是在標記清除算法上的一個進階,垃圾收集時將需要回收的對象打上標記煌茬,然后將所有存活的對象向一端移動斥铺,最后清理掉末端邊界以外的對象,這種算法雖然不會有內存碎片坛善,但效率偏低晾蜘。