需要《深入理解JVM虛擬機》第三版 掃描版PDF的可以加QQ 3454779752 ,有償,謝謝
方法區的垃圾收集主要回收兩部分內容:
廢棄的常量和不再使用的類型。
回收廢棄常量
與回收Java堆中的對象非常類似。
舉個常量池中字面量回收的例子,假如一個字符串“java”曾經進入常量池中,但是當前系統又沒有任何一個字符串對象的值是“java”,換句話說,已經沒有任何字符串對象引用常量池中的“java”常量,且虛擬機中也沒有其他地方引用這個字面量。如果在這時發生內存回收,而且垃圾收集器判斷確有必要的話,這個“java”常量就將會被系統清理出常量池。常量池中其他類(接
口)、方法、字段的符號引用也與此類似。判定一個常量是否“廢棄”還是相對簡單,
回收不再使用的類型
判定一個類型是否屬於“不再被使用的類”的條件就比較苛刻了。需要同時滿足下面三個條件:
·該類所有的實例都已經被回收,也就是Java堆中不存在該類及其任何派生子類的實例。
·加載該類的類加載器已經被回收,這個條件除非是經過精心設計的可替換類加載器的場景,如OSGi、JSP的重加載等,否則通常是很難達成的。
·該類對應的java.lang.Class對象沒有在任何地方被引用,無法在任何地方通過反射訪問該類的方法。
Java虛擬機被允許對滿足上述三個條件的無用類進行回收,這裏說的僅僅是“被允許”,而並不是和對象一樣,沒有引用了就必然會回收。
關於是否要對類型進行回收,HotSpot虛擬機提供了-Xnoclassgc參數進行控制,還可以使用-verbose:class以及-XX:+TraceClass-Loading、-XX:+TraceClassUnLoading查看類加載和卸載信息,其中-verbose:class和-XX:+TraceClassLoading可以在Product版的虛擬機中使用,-XX:+TraceClassUnLoading參數需要FastDebug版的虛擬機支持。
在大量使用反射、動態代理、CGLib等字節碼框架,動態生成JSP以及OSGi這類頻繁自定義類加載器的場景中,通常都需要Java虛擬機具備類型卸載的能力,以保證不會對方法區造成過大的內存壓力。
參考:
深入理解JVM第三版 第三章 第三節