方法区其实也是需要被回收的,并不是说虚拟机永久代中不需要垃圾收集。而是方法区中的垃圾收集的效率很低,新生代中一次垃圾收集可以回收70%-95%的空间,而永久代中的下效率要远远低于此。
方法区中的回收主要包括两部分内容:废弃的常量和无用的类
- 废弃的常量主要包括两大类 字面量和符号引用
字面量比较接近Java语言中的常量概念。回收废弃的常量和回收Java堆中的对象类似,如:要回收字符串“s”,当系统中没有任何String类型的对象引用常量池中的"s"时,也没有其他地方引用这个字面量,如果发生内存回收,而且有必要的话,则会将该字符串清理出常量池中。其中包括文本字符串、被声明为final的常量值等
而符号引用属于编译方面的概念。常量池中的其他类、接口、方法、字段的符号引用也与此类似,包括
- 类和接口的全限定名
- 字段的名称和描述符
- 方法的名称和描述符
2.无用的类: 要判断一个无用的类的条件非常的苛刻,需要满足:
- 该类的所有实例都被回收,即:Java堆中不存在该类的任何实例
- 该类的Classloader已经被回收
- 该类对用的java.lang.Class对象没有任何地方被引用,无法在任何地方通过反射访问到该类的方法。
当满足以上三个条件时,也未必说是一定要被回收。也仅仅是可以。
在大量使用反射,动态代理,CGLib等框架的场景,以及动态代理生成JSP和OSGI这类频繁自定义的场景都需要虚拟机具备类卸载的功能,以保证永久代不会溢出
参考
周志明《深入理解Java虚拟机》
https://blog.csdn.net/u010571316/article/details/45506567
写在最后
做一个灵魂和肉体分离的人,灵魂不受肉体的束缚,灵魂可以指挥肉体
网友评论