對象已死?
-
計數(shù)算法
- 算法很容易理解
在對象中添加一個引用計數(shù)器熊响,每當有一個地方引用它時昧碉,計數(shù)器值就加一蓝纲;當引用失效時阴孟,計數(shù)器值就減一;任何時刻計數(shù)器為零的對象就是不可能再被使用的
優(yōu)點
雖然占用了額外空間税迷, 但判定效率高,原理簡單锹漱,大多數(shù)情況下不錯缺點
主流的Java虛擬機里面都沒有選用引用計數(shù)算法來管理內(nèi)存箭养,主要原因是,這個看似簡單的算法有很多例外情況要考慮哥牍,必須要配合大量額外處理才能保證正確地工作毕泌,譬如單純的引用計數(shù)就很難解決對象之間相互循環(huán)引用的問題。
例如: objA.next = objB objB.next = objA objA與objB的計數(shù)都不為0而 = 1嗅辣,但是實際上他們已經(jīng)不會在被使用
-
可達性分析算法
- 思路
這個算法的基本思路就是通過一系列稱為“GCRoots”的根對象作為起始節(jié)點集撼泛,從這些節(jié)點開始,根據(jù)引用關系向下搜索澡谭,搜索過程所走過的路徑稱為“引用鏈”(ReferenceChain)愿题,如果某個對象到GCRoots間沒有任何引用鏈相連,或者用圖論的話來說就是從GCRoots到這個對象不可達時蛙奖,則證明此對象是不可能再被使用的潘酗。
-
GC root的判定
在虛擬機棧(棧幀中的本地變量表)中引用的對象
在方法區(qū)中類靜態(tài)屬性引用的對象,譬如Java類的引用類型靜態(tài)變量雁仲。
在方法區(qū)中常量引用的對象仔夺,譬如字符串常量池(StringTable)里的引用
在本地方法棧中JNI(即通常所說的Native方法)引用的對象。
Java虛擬機內(nèi)部的引用攒砖,如基本數(shù)據(jù)類型對應的Class對象缸兔,一些常駐的異常對象(比如NullPointExcepiton、OutOfMemoryError)等吹艇,還有系統(tǒng)類加載器惰蜜。
所有被同步鎖(synchronized關鍵字)持有的對象。
反映Java虛擬機內(nèi)部情況的JMXBean掐暮、JVMTI中注冊的回調(diào)蝎抽、本地代碼緩存等。
對象引用
在JDK1.2版之后路克,對象引用有 強引用樟结,軟引用,弱引用精算,虛引用
強引用 :無論如何都不會被gc回收瓢宦,如Objectobj=newObject()
軟引用:還有用,但非必須灰羽,在系統(tǒng)將要發(fā)生內(nèi)存溢出異常前驮履,會把這些對象列進回收范圍之中進行第二次回收鱼辙,如果回收了還不夠,就會拋異常;
弱引用:非必須對象玫镐,被弱引用關聯(lián)的對象只能生存到下一次垃圾收集發(fā)生為止
虛引用: 最弱的一種倒戏,為一個對象設置虛引用關聯(lián)的唯一目的只是為了能在這個對象被收集器回收時收到一個系統(tǒng)通知。
方法區(qū)的垃圾回收
方法區(qū)垃圾回收 基本為常量字符串 + 類卸載
判斷常量不再被使用:如果一個常量x進入方法區(qū)后恐似,虛擬機中不存在任何一個引用 = x杜跷,則會被回收
-
判斷一個類是否要被卸載
該類型不存在任何一個實例 或者 派生子類實例
加載該類的類加載器已經(jīng)被回收 , 這個條件除非是經(jīng)過精心設計的可替換類加載器的場景,如OSGi矫夷、JSP的重加載等葛闷,否則通常是很難達成的。
對應的Class對象沒有被引用過
以上條件實現(xiàn)僅被允許卸載双藕,但不是必然的淑趾,
關于是否要對類型進行回收,HotSpot虛擬機提供了參數(shù)進行控制
- 在大量使用動態(tài)代理(動態(tài)字節(jié)碼技術)的場景 或 動態(tài)生成jsp的忧陪,jvm通常要具備類卸載功能