《深入理解java虛擬機》學習筆記03

第三章 垃圾收集器與內存分配策略

1、對象已死嗎

1.1 引用計數器算法
定義:給對象中添加一個引用計數器,每當有一個地方引用它時,計數器就加1;當應用失效時,計數器就減1;任何時刻計數器爲0的對象就是不可能再被使用的對象。
缺點:循環引用。

1.2 可達性分析算法

通過一系列成爲GC Roots的對象作爲起始點,從這些節點開始向下搜索,搜索所走過的路徑成爲引用鏈(Reference Chain),當一個對象到GC Roots沒有任何應用鏈項鍊時,則證明該對象不可用。
在java中 可作爲GC Roots的對象包含以下幾種:
(1)虛擬機棧(棧幀中的本地變量表)中引用的對象。
(2)方法區中類靜態屬性引用的對象。
(3)方法去中常量引用的對象。
(4)本地方法棧中JNI(即一般說的Native方法)引用的對象。


1.3再談引用
jdk1.2以後,java對引用的概念進行了擴充,將引用分爲強引用(Strong Reference)、軟引用(Soft Reference)、弱引用(Weak Reference)、虛引用(Phantom Reference)四種
(1)強引用就是指在程序代碼中普遍存在的,new出來的對象,只要強引用存在,垃圾回收器就永遠不會回收這部分引用。
(2)軟引用就是用來描述一些還有用但是非必須的對象,在系統將要發生內存溢出時,將把這些對象列在二次回收的範圍。如果這次回收後還沒有足夠的內存,纔會拋異常。
(3)弱引用用來描述非必須的對象,強度比軟引用更弱,被弱引用關聯的對象只能生存到下一次垃圾收集發生之前。
(4)虛引用也成爲幽靈引用或者幻影引用,是最弱的一種引用。一個對象是否有虛引用的存在,完全不會對其生存時間構成引用,也無法通過虛引用來取得一個對象實例。
1.4 生存還是死亡
即使可達性分析算法中不可用的對象,也並非直接回收,還會經過兩次標記過程。
第一次標記:第一次篩選的條件是此對象是否有必要執行finalize方法,如果該對象的finalize方法被覆蓋過或者finalize方法已經被虛擬機調用過,當沒有時,虛擬機認爲沒有必要,直接回收。
如果認爲有必要執行finalize方法,那麼這個對象將會放在一個叫做F-Queue的隊列中,並在稍後由一個虛擬機自動建立、低優先級的Finalizer線程中執行,所謂執行,是指虛擬機會觸發這個方法,但是虛擬機並不會等待該方法執行完畢。finalize方法是對象逃脫死亡的最後一次機會。如果在該方法中自救成功。那麼在第二次標記時將被移除“即將回收”的集合。
第二次標記:第二次標記發生在F-Queue隊列中。
1.5回收方法區
方法去(永久代)的回收包括兩部分:廢棄常量和無用類。
廢棄常量的回收和java堆中對象的回收很相似,沒有引用,常量就會被系統清理出常量池。
類需要同時滿足下面三個條件才能判斷爲無用類:
(1)該類所有的實例已經被回收,也就是java堆中不存在該類的任何實例。
(2)加載該類的ClassLoader已經被回收。
(3)該類對應的java.lang.Class對象沒有在任何地方被引用,無法再任何地方通過反射訪問該類的方法。
在大量使用反射、動態代理、CGLib等的ByteCode框架頻繁的自定義ClassLoader的場景都需要虛擬機設置類卸載的功能,以保證永久代不會溢出。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章