JVM——垃圾收集器(一)——如何判斷對象「已死」

目錄:java

1.爲何要了解垃圾回收機制?算法

2.哪幾類內存須要進行垃圾收集?併發

3.如何判斷對象「已死」?——兩種算法高併發

4.引用的細分this

5.對象的自救spa

 

 

1.爲何要了解垃圾回收機制?線程

當須要排查各類內存溢出、內存泄漏問題時,當垃圾收集成爲系統達到更高併發了的瓶頸時,咱們就須要對這些「自動化」技術實施必要的監控和調節。對象

 

2.哪幾類內存須要進行垃圾收集?接口

java運行時內存中,程序計數器、虛擬機棧、本地方法棧3個區域是線程私有的,隨線程而生,隨線程而滅;而Java堆和方法區則不同,一個接口中的多個實現類須要的內存可能不同,一個方法中的多個分支須要的內存也可能不同,咱們只有在程序處於運行期間才能知道會建立哪一個對象,這部份內存的分配和回收都是動態的,垃圾收集器關注的也是這部份內存。隊列

 

3.如何判斷對象「已死」?

引用計數算法

來記錄一個對象被引用的次數,當引用計數器爲0時,表明這個對象再也不被使用。

優勢:實現簡單,判斷效率也很高。

缺點:它很難解決對象之間相互循環引用的問題。

 

可達性分析算法:

在主流的商用程序語言的主流實現都是經過可達性分析來判斷對象是否存活的。這個算法的基本思路就是經過一系列的稱爲「GC Roots」的對象做爲起始點,從這些節點開始向下搜索,搜索所走過的路徑稱爲引用鏈(Reference Chain),當一個對象到GC Roots沒有任何引用相連時,證實此對象是不可用的。

java語言中,可做爲GC Roots的對象包括下面幾種:

①虛擬機棧(棧幀中的本地變量表)中引用的對象。

②方法區中靜態屬性引用的對象。

③方法區中常量引用的對象。

④本地方法棧中JNI(即通常說的Native方法)引用的對象。

 

4.引用的細分:

java中的引用定義很傳統:若是reference類型的數據中存儲的數值表明的是另一塊內存的起始地址,就稱這塊內存表明着一個引用。這種定義很純粹,可是太過狹隘,一個對象在這種定義下只有被引用或者沒有被引用兩種狀態,對於如何描述一些「食之無味,棄之惋惜」的對象就顯得無能爲力。

咱們但願能描述這樣一組對象:當內存空間還足夠時,則可以保存在內存中;若是內存空間在進行垃圾收集後仍是很是緊張,就能夠拋棄這些對象。

在JDK1.2以後,java對引用的概念進行了擴充,將引用分爲強引用(Strong Reference)、軟引用(Soft Reference)、弱引用(Weak Reference)、虛引用(Phantom Reference)4種。

強引用:就是指在程序代碼之中廣泛存在的,相似「Object obj=new Object()」這類引用,只要強引用還在,垃圾收集器永遠不會回收掉被引用的對象。

軟引用:是用來描述一些還有用但並不是必須的哦對象。對於軟引用關聯着的對象,在系統將要發生的內存溢出異常以前,將會把這些對象列進回收範圍之中進行第二次回收,若是此次回收尚未足夠的內存,纔會拋出內存溢出的異常。

弱引用:也是用來描述非必須對象的,可是他的強度比軟引用更弱一點,只能生存到下一次垃圾收集以前。

虛引用:最弱的引用關係,徹底不會對其生存時間構成影響,也沒法經過虛引用來取得一個對象的實例。爲一個對象設置虛引用的惟一目的就是可以在這個對象被收集器回收時收到一個系統通知。
 

5.對象的自救

即便在可達性分析算法中不可達的對象,也並不是是「非死不可」的,這時候他們暫時處於「緩刑」階段,要真正宣告一個對象死亡,至少要經歷兩次標記過程:若是對象在進行可達性分析後發現沒有與GC Roots相鏈接的引用鏈,那它將會被第一次標記而且進行一次篩選,篩選的條件是對此對象是否有必要執行finalize()方法。

當對象沒有覆蓋finalize()方法,或者finalize()方法已經被虛擬機調用過(對象自救機會只有一次),虛擬機將這兩種狀況都視爲「沒有必要執行」。

若是這個對象被斷定爲有必要執行的finalize()方法,那麼這個對象將會被放置在一個叫作F-Queue的隊列之中,並在稍後由一個由虛擬機自動創建的、低優先級的Finalize線程去執行它。這裏所謂的「執行」是指虛擬機會觸發這個方法,但並不承諾會等待它運行結束,這樣作的緣由是,若是一個對象在finalize()方法中執行緩慢,或者發生了死循環,極可能回到藕汁F-Queue隊列中的其餘對象永久處於等待狀態,甚至致使整個內存回收系統崩潰。

Finalize()方法是對象逃脫死亡命運的最後一次機會,稍後GC將堆F-Queue中的對象進行第二次小規模的標記,若是對象要在finalize()中成功拯救本身——只須要從新與引用鏈的任何一個對象創建關聯便可,譬如把this賦值給某變量或者對象的成員變量,拿在第二次標記時,它將被移除出「即將回收」的集合;若是對象這個時候還有逃脫,那基本上他就真的被回收了。

相關文章
相關標籤/搜索