方法區的回收
方法區中進行垃圾回收的“性價比”一般比較低,在堆中,尤其是在新生代中,常規應用進行一次垃圾收集一般可以回收70%-95%的空間,而永久代的垃圾收集效率遠低於此。
永久代的垃圾收集主要回收兩部分內容:廢棄常量和無用的類。回收廢棄常量與回收Java堆中的對象非常類似。以常量池中字面量的回收為例,假如一個字符串的
“abc”已經進入常量池中,但是當前系統沒有任何一個String對象是叫做“abc”的,換句話說,就是沒有任何String對象引用常量池中的“abc”常量,也沒余其他地方應用了這個字面量,如果這時發生內存回收,而且必要的話,這個“abc”常量就會被系統清理出常量池。常量池中的其他類(接口),方法,字段的符號引用也與此類似。判定一個常量是否是“廢棄常量”比較簡單,而要判定一個類是否是“無用的類”的條件則相對苛刻許多。類需要同時滿足下面3個條件才能算是“無用的類”:
1.該類所有的實例都已經被回收,也就是Java堆中不存在該類的任何實例。2.加載該類的ClassLoader已經被回收。3.該類對應的java.lang.Class對象沒有在任何地方被引用,無法再任何地方通過反射訪問該類的方法。虛擬機可以對滿足上述3個無用類進行回收,這個說的僅僅是“可以”,而不是和對象一樣,不使用了就必然回收。
對象回收算法:標記-清除算法,復制算法,標記-整理算法,分代收集算法。
分代收集算法:根據對象的存活周期的不同將內存劃分為幾塊。一般是把Java堆分為新生代和老年代,這樣就可以根據各個年代的特點采用最適當的收集算法。在新生代中,每次垃圾收集時都發現有大批對象死去,只有少量存活,那就采用復制算法,只需要付出少量存活對象的復制成本就可以完成收集。而老年代中因為對象存活率高,沒有額外空間對它進行分配擔保,就必須采用“”標記-清除”或"標記-整理"算法來進行回收。
方法區的回收