GC需要完成的3件事情:
哪些內存需要回收?
什麼時候回收?
如何回收?
如何怕暖對象已經死去、
1、引用計數算法(無法解決循環引用的對象需要回收的問題)
引用計數器:給對象添加一個引用計數器,當有房引用它的時候就計數器值加1,否則就建議,當計算器爲0的時候對象不能再使用,這種不可行,商用不可用,循環引用的對象需要被清除,無法解決
2、可達性分析算法
通過對一些列稱爲GC ROOTs對象作爲起始點,從這些節點開始往下搜索,搜索走過的路徑稱爲引用連,當一個對象到GC roots沒有任何引用能夠引用到,則證明此對象不可用,被判定爲可回收對象。
可作爲GC Roots的對象包括下面集中
虛擬機棧
方法區中類靜態屬性引用的對象
方法區中常量引用的對象
本地方法棧中JNI(native方法)引用的對象
強引用,軟引用,弱引用,虛引用
生存還是死亡?
當對象被判定爲不可達對象的時候並非非死不可,處於緩刑階段,宣告對象死亡至少經理兩次標記過程,
第一次標記並且進行一次判定是否執行finalize()方法,如果該方法成功拯救自己,就不會被回收,否則執行完該方法之後如果再次被標記爲不可達就需要被回收。(建議忘掉這個方法的存在)
回收方法區,一個類需要滿足3個條件才能算是無用的類
該類的所有的實例都已經被回收,也就是java堆中不存在該類的任何實例
加載該類的classloader已經被回收
該類對應的java.lang.class對象沒有在任何地方唄應用過
滿足上述三個條件的無用類進行回收(可以進行)
垃圾收集算法
標記-清除算法
1)首先標記出所有需要回收的對象(可達性分析算法進行標記)
2)統一回收效率不高,空間碎片問題
複製算法:
1)將對內存分爲三個部分,eden ,from, to ,每次新建對象在eden,將還活着的eden,和from survior中的還活着的對象放到 to survivor中去,清理to surviror內存,將from 和 to的地位交換重複上述操作。
標記整理:
對老年代進行垃圾回收不適合使用複製算法,而是採用標記整理算法,標記的過程和可達性分析的算法一樣,但是在整理的時候,將所有存貨額對象向一端移動,清理掉邊界以外的內存
分代收集算法:
將堆內存空間劃分爲新生代和老年代,根據不同的年代的特點採用適當的收集算法。在新生代中,使用複製算法,老年代採用標記清理算法。
垃圾回收切入時間點:(線程停頓)
枚舉根節點
安全點(達到安全點才能夠暫停,進行可達性分析)
安全區域(在安全的區域內進行gc,這部分的區域引用關係沒有發生變化)
可達性分析對執行---必須在一個額能夠確保一致性快照中進行,這裏的一致性表示真個分析期間執行系統看起來就像是被凍結在某個時間點上,不可以出現分析過程中對象引用關係還在不同的變化的情況
主流的java虛擬機使用精準gc,有辦法得到執行上下文和全局的引用個位置,oopmap的數據結構來達到這個目的。
內存分配與回收策略(進行參數調節)
1)對象優先在Eden分配
2)大對象直接進入老年代
大對象是一個壞消息,比遇到一個大對象更加壞的消息就是遇到一羣朝生夕死的大對象
3)長期存活的對象將進入老年代
4)動態對象年齡判斷
5)空間分配的安保