回收方法区
方法区虽然被称为永久代,但是方法区也存在着垃圾回收,只不过方法区的垃圾回收的效率很低。
方法区的垃圾回收主要包括两部分,回收废弃的常量跟无用的类。
回收废弃的常量
回收废弃的常量跟回收java堆中的对象非常相似,例如如果一个字符串“garbage”已经被放入了常量池中,但是当前系统没有一个String对象是叫做“garbage”的,也就是说没有任何String对象引用常量池中garbage常量,也没有其他地方引用了这个字面量,如果这个时候发生了垃圾回收,而且必要的话,这个对象将会被从常量池中移除。常量池中其他类,接口,方法的符号引用也是如此。
回收无用的类
判定一个类是否是无用的类标准,条件比较苛刻。类需要同时满足下面三个条件才能算是无用的类:
- 该类的所有实例都已经被回收;
- 加载这个类的ClassLoader已经被回收;
- 该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问这个类的方法;
虚拟机可以对满足上面三个条件的无用的类进行垃圾回收,只是可以进行回收,并不是一定进行回收,是否进行回收,可以通过设置jvm的参数来实现。
对于大量使用反射,动态代理等频繁自定义ClassLoader的场景都需要jvm具备类卸载的功能,以保证永久代不会溢出。