【深入Java虚拟机JVM 10】回收方法区
說明:文章所有內(nèi)容均摘自《深入理解Java虛擬機(jī):JVM高級特性與最佳實(shí)踐(第二版)》
很多人認(rèn)為方法區(qū)(或者HotSpot虛擬機(jī)中的永久代)是沒有垃圾收集的,Java虛擬機(jī)規(guī)范中確實(shí)說過可以不要求虛擬機(jī)在方法區(qū)實(shí)現(xiàn)垃圾收集,而且在方法區(qū)中進(jìn)行垃圾收集的“性價(jià)比”一般比較低:在堆中,尤其是在新生代中,常規(guī)應(yīng)用進(jìn)行一次垃圾收集一般可以回收70%~95%的空間,而永久代的垃圾收集效率遠(yuǎn)低于此。
永久代的垃圾收集主要回收兩部分內(nèi)容:廢棄常量和無用的類。回收廢棄常量與回收J(rèn)ava堆中的對象非常類似。以常量池中字面量的回收為例,假如一個(gè)字符串“abc”已經(jīng)進(jìn)入了常量池中,但是當(dāng)前系統(tǒng)沒有任何一個(gè)String對象是叫做“abc”的,換句話說,就是沒有任何String對象引用常量池中的“abc”常量,也沒有其他地方引用了這個(gè)字面量,如果這時(shí)發(fā)生內(nèi)存回收,而且必要的話,這個(gè)“abc”常量就會(huì)被系統(tǒng)清理出常量池。常量池中的其他類(接口)、方法、字段的符號(hào)引用也與此類似。
?
判定一個(gè)常量是否是“廢棄常量”比較簡單,而要判定一個(gè)類是否是“無用的類”的條件則相對苛刻許多。
類需要同時(shí)滿足下面3個(gè)條件才能算是“無用的類”:
- 該類所有的實(shí)例都已經(jīng)被回收,也就是Java堆中不存在該類的任何實(shí)例。
- 加載該類的ClassLoader已經(jīng)被回收。
- 該類對應(yīng)的java.lang.Class對象沒有在任何地方被引用,無法在任何地方通過反射訪問該類的方法。
虛擬機(jī)可以對滿足上述3個(gè)條件的無用類進(jìn)行回收,這里說的僅僅是“可以”,而并不是和對象一樣,不使用了就必然會(huì)回收。是否對類進(jìn)行回收,HotSpot虛擬機(jī)提供了-Xnoclassgc參數(shù)進(jìn)行控制,還可以使用-verbose:class以及-XX:+TraceClassLoading、-XX:+TraceClassUnLoading查看類加載和卸載信息,其中-verbose:class和-XX:+TraceClassLoading可以在Product版的虛擬機(jī)中使用,-XX:+TraceClassUnLoading參數(shù)需要FastDebug版的虛擬機(jī)支持。
在大量使用反射、動(dòng)態(tài)代理、CGLib等ByteCode框架、動(dòng)態(tài)生成JSP以及OSGi這類頻繁自定義ClassLoader的場景都需要虛擬機(jī)具備類卸載的功能,以保證永久代不會(huì)溢出
?
總結(jié)
以上是生活随笔為你收集整理的【深入Java虚拟机JVM 10】回收方法区的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【深入Java虚拟机JVM 09】JVM
- 下一篇: 如何运行一个Java文件?