1击喂、對象的狀態(tài)
對于jvm中的垃圾收集器中,判斷對象是否可以被回收介时,哪些對象是否需要存活是有以下的方法的。
1.1沸柔、引用計數(shù)法
引用計數(shù)的實現(xiàn)很簡單,判斷方式也很高效会钝,在大多數(shù)情況下都不錯工三,但是如果有a對象和b對象這種相互循環(huán)引用的問題是無法有效的處理的
1.2、可達(dá)性分析算法
算法思路:通過一系列稱為"GC ROOT"的對象作為起始點俭正,從這些節(jié)點開始向下搜索,搜索所走過的路徑被稱為引用鏈掸读,當(dāng)一個對象到GC ROOT沒有任何引用鏈相連接的時候,就證明這個對象是不可用的(如下圖示例中的object5,6,7)澡罚。
對于java而言姥闪,可作為GC ROOT的對象包括以下幾種:
- 虛擬機棧中引用的對象
- 方法區(qū)中類靜態(tài)屬性引用的對象
- 方法區(qū)中常量引用的對象
- 本地方法棧中
JNI
引用的對象
1.3、引用的類別
對于jdk2之后催式,java對于引用的概念進(jìn)行擴(kuò)充荣月,分為以下的幾種:
- 強引用:類似于new出來的對象哺窄,只要強引用在萌业,gc永遠(yuǎn)不會回收
- 軟引用:是一種有用但是非必須的對象生年,系統(tǒng)在將要內(nèi)存溢出異常之前抱婉,把這些對象列進(jìn)回收范圍里進(jìn)行第二次回收蒸绩,如果回收后還沒有足夠的內(nèi)存才會拋出內(nèi)存溢出患亿,jdk2以后用softReference來實現(xiàn)窍育。
- 弱引用:也是非必須對象的一種漱抓,強度要低于軟引用乞娄,被弱引用關(guān)聯(lián)的對象只能生存到下一次gc發(fā)生之前仪或。當(dāng)gc時蕾域,無論內(nèi)存是否充足旨巷,都會回收掉只被弱引用關(guān)聯(lián)的對象采呐,用weakReference來實現(xiàn)。
- 虛引用:是最弱的一種引用關(guān)系仲器。無法通過虛引用來獲得對象實例蝶糯。虛引用的目的就是讓這個對象在gc被回收時收到一個系統(tǒng)通知裳涛,使用phantomReference來實現(xiàn)。
1.4鹃彻、回收的機制
即使是可達(dá)性算法中团赁,不可達(dá)的對象也不是一下就會被回收的欢摄。
一般他們是要經(jīng)歷兩次標(biāo)記過程:如果對象在進(jìn)行可達(dá)性分析后發(fā)現(xiàn)沒有在GC ROOT的引用鏈上,他會被第一次標(biāo)記并且進(jìn)行一次篩選,篩選的條件是此對象是否需要執(zhí)行finalizer()
方法尝盼。當(dāng)對象沒有覆蓋finalizer()
方法裁赠,或者finalizer()
方法已經(jīng)被jvm調(diào)用過组贺,虛擬機講這兩種情況都視為”沒必要執(zhí)行“。
注意:我們在日常的開發(fā)中最好不要去操作finalizer()
方法渐苏。
1.5仪吧、回收方法區(qū)
永久代的gc包含兩個部分的內(nèi)容:廢棄常量和無用的類
沒有任何String對象引用常量池中的這個常量薯鼠,也沒有其他地方引用了這個字面量羞芍,如果這時發(fā)生內(nèi)存回收荷科,而且必要的話畏浆,這個常量就會被系統(tǒng)清理出常量池。常量池中的其他類(接口)将鸵、方法顶掉、字段的符號引用也與此類似痒筒。
類需要同時滿足下面3個條件才能算是“無用的類”:
- 該類所有的實例都已經(jīng)被回收,也就是Java堆中不存在該類的任何實例。
- 加載該類的ClassLoader已經(jīng)被回收螟左。
- 該類對應(yīng)的java.lang.Class 對象沒有在任何地方被引用胶背,無法在任何地方通過反射訪問該類的方法钳吟。
虛擬機可以對滿足上述3個條件的無用類進(jìn)行回收,這里說的僅僅是“可以”涤姊,而并不是和對象一樣砂轻,不使用了就必然會回收厨喂。
在大量使用反射派阱、動態(tài)代理贫母、CGLib等ByteCode框架、動態(tài)生成JSP以及OSGi這類頻繁自定義ClassLoader的場景都需要虛擬機具備類卸載的功能因块,以保證永久代不會溢出趾断。